#!/usr/bin/perl
#
# (C) Copyright IBM Corp. 2004
#
# This program is free software;  you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY;  without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
# the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program;  if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Script for testing assign, create, and delete of GPT segments.
#
# Test1: Assign the GPT plugin to the disk.
# Test3: Create a segment.
# Test4: Delete the segment.
# Test5: Create a segment with several other options.
# Test7: Create a lot of segments.
# Test8: Unassign the GPT plugin from the disk.

use strict;
use warnings;

use Evms::Common;
use Evms::Log;
use Evms::Object;
use Evms::Gpt;
use Evms::DM;

# Test1
# Assign GPT to the disk.
sub Test1
{
	my $disk = $_[0];
	my @query_output;
	my $pmbr = $disk . "_pmbr";
	my $rc;

	log_info("Test assigning the GPT plugin to a disk.\n");

	log_info("1. Assigning GPT plugin to disk $disk.\n");
	$rc = assign_gpt_plugin($disk);
	if ($rc) {
		log_error("Error assigning GPT plugin to disk $disk.\n");
		goto out;
	}

	log_info("2. Verifying assignment of plugin to disk $disk.\n");

	@query_output = query_object($pmbr);
	if (@query_output == 0) {
		log_error("Error getting details for MBR on disk $disk.\n");
		$rc = 1;
		goto out;
	}

out:
	log_result($rc);
	return $rc;
}

# Test2
# Create a segment.
sub Test2
{
	my $disk = $_[0];
	my $freespace = $disk . "_freespace1";
	my $segment = $disk . "1";
	my $size = "500MB";
	my @query_output;
	my $rc;

	log_info("Test creating a segment.\n");

	log_info("1. Creating $size segment on disk $disk.\n");

	$rc = create_gpt_basic_data_segment($freespace, $size);
	if ($rc) {
		log_error("Error creating segment.\n");
		goto out;
	}

	log_info("2. Verifying creation of segment $segment.\n");

	@query_output = query_object($segment);
	if (@query_output == 0) {
		log_error("Error verifying existence of segment $segment.\n");
		$rc = 1;
		goto out;
	}

	log_info("3. Verifying segment $segment is active in kernel.\n");

	$rc = dm_device_exists($segment);
	if ($rc) {
		log_error("Error getting kernel info for segment $segment.\n");
		$rc = 1;
		goto out;
	}

out:
	log_result($rc);
	return $rc;
}

# Test3
# Delete the segment from Test2.
sub Test3
{
	my $disk = $_[0];
	my $segment = $disk . "1";
	my @query_output;
	my $rc;

	log_info("Test deleting segments.\n");

	log_info("1. Deleting the segment $segment " .
		 "from disk $disk.\n");

	$rc = delete_thing($segment);
	if ($rc) {
		log_error("Error deleting segment $segment.\n");
		goto out;
	}

	log_info("2. Verifying deletion of segment $segment.\n");

	@query_output = query_object($segment);
	if (@query_output != 0) {
		log_error("Error: segment $segment still exists.\n");
		$rc = 1;
		goto out;
	}

	log_info("3. Verifying deactivation of segment in kernel.\n");

	$rc = dm_device_exists($segment);
	if (!$rc) {
		log_error("Error: segment $segment still active in kernel.\n");
		$rc = 1;
		goto out;
	}

	$rc = 0;

out:
	log_result($rc);
	return $rc;
}

# Test4
# Create a segment with extra options.
sub Test4
{
	my $disk = $_[0];
	my $freespace = $disk . "_freespace1";
	my $segment = $disk . "1";
	my %options;
	my @query_output;
	my $value;
	my $rc;

	$options{"Size"} = "1GB";
	$options{"Offset"} = "1GB";

	log_info("Test creating segments with extra GPT options.\n");

	log_info("1. Creating segment on disk $disk with options:\n");
	log_info("     size = $options{'Size'}\n");
	log_info("     offset = $options{'Offset'}\n");

	$rc = create_gpt_segment($freespace, \%options);
	if ($rc) {
		log_error("Error creating segment.\n");
		goto out;
	}

	log_info("2. Verifying creation of segment $segment.\n");

	@query_output = query_object($segment);
	if (@query_output == 0) {
		log_error("Error verifying existence of segment $segment.\n");
		$rc = 1;
		goto out;
	}

	log_info("3. Verifying extra options on segment $segment.\n");

	@query_output = extended_query_object($segment);
	if (@query_output == 0) {
		log_error("Error getting extended info for segment $segment.\n");
		$rc = 1;
		goto out;
	}

	$value = get_extended_info_value("Size", \@query_output);
	$value =~ s/(\d+)\s+sectors/$1/;
	$rc = compare_sectors($value, size_to_sectors($options{"Size"}), 5);
	if ($rc) {
		log_error("Error verifying size of segment $segment.  " .
		"Size is $value.  Size given was " . $options{"Size"} . ".\n");
		goto out;
	}

	$value = get_extended_info_value("Start", \@query_output);
	$rc = compare_sectors($value, size_to_sectors($options{"Offset"}), 5);
	if ($rc) {
		log_error("Error verifying starting offset of " .
			  "segment $segment.  Start is $value.  Offset given was " . $options{"Offset"} . ".\n");
		goto out;
	}

	# Delete the segment now that we're done.
	delete_thing($segment);

out:
	log_result($rc);
	return $rc;
}

# Test5
# Create a lot of segments on the disk.
sub Test5
{
	my $disk = $_[0];
	my $freespace = $disk . "_freespace1";
	my $segment;
	my $count = 25;
	my $size = "50MB";
	my $sectors;
	my ($rc, $i);

	log_info("Test creating large number of segments on a disk.\n");

	log_info("1. Creating $count segments on disk $disk.\n");

	for ($i = 0; $i < $count; $i++) {
		$rc = create_gpt_basic_data_segment($freespace, $size);
		if ($rc) {
			log_error("Error creating segment $i.\n");
			goto out;
		}
		$freespace = $disk . "_freespace2";
	}

	log_info("2. Verifying all $count segments are active in the kernel.\n");

	for ($i = 0; $i < $count; $i++) {
		$segment = $i + 1;
		$segment = $disk . $segment;
		$rc = dm_device_exists($segment);
		if ($rc) {
			log_error("Error: segment $segment not found in " .
				  "the kernel.\n");
			goto out;
		}

		$sectors = get_blkdev_sectors($segment);
		$rc = compare_sectors($sectors, size_to_sectors($size), 10);
		if ($rc) {
			log_error("Error verifying number of sectors in " .
				  "segment $segment.\n");
			goto out;
		}
	}

out:
	log_result($rc);
	return $rc;
}

# Test6
# Unassign GPT from the disk.
sub Test6
{
	my $disk = $_[0];
	my $pmbr = $disk . "_pmbr";
	my @query_output;
	my $rc;

	log_info("Testing unassigning the GPT plugin from a disk.\n");

	log_info("1. Removing the GPT plugin from disk $disk.\n");

	$rc = unassign_gpt_plugin($disk);
	if ($rc) {
		log_error("Error removing GPT plugin from disk $disk.\n");
		goto out;
	}

	log_info("2. Verifying removal of GPT plugin.\n");

	@query_output = query_object($pmbr);
	if (@query_output != 0) {
		log_error("Error: GPT plugin was not removed from disk $disk.\n");
		$rc = 1;
		goto out;
	}

out:
	log_result($rc);
	return $rc;
}

MAIN:
{
	my $disk;
	my $rc;

	# Only use the first disk specified.
	$disk = $ARGV[0];
	$disk || die("USAGE: $0 <disk>\n");

	# Check for minimum-sized disk.
	$rc = check_minimum_object_size($disk, "1.5GB");
	if ($rc) {
		die("Disk $disk isn't large enough for this test.\n");
	}

	# No setup required, as long as $disk is already clean.

	$rc = Test1($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test2($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test3($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test4($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test5($disk);
	if ($rc) {
		goto finish;
	}

	$rc = Test6($disk);
	if ($rc) {
		goto finish;
	}

	clean_object($disk);

finish:
}

