#!/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 resizing of GPT segments.
#
# Test1: Create a 512MB segment. Expand it to 1GB.
# Test2: Create a second segment. Attempt to expand the first
#        segment and verify that it fails.
# Test3: Create a 512MB segment. Expand it to 1GB.
# Test4: Shrink the first segment.

use strict;
use warnings;

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

# Setup
# Assign GPT to the disk.
sub Setup
{
	my $disk = $_[0];
	my $rc;

	log_info("Assigning GPT plugin to disk $disk.\n");

	$rc = assign_gpt_plugin($disk);

	log_info(($rc ? "Failed" : "Success") . "\n\n");
	return $rc;
}

# Test1
# Create a 512MB segment. Then expand it to 1GB.
sub Test1
{
	my $disk = $_[0];
	my $freespace = $disk . "_freespace1";
	my $segment = $disk . "1";
	my ($size1, $size2);
	my ($sectors1, $sectors2);
	my $rc;

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

	log_info("1. Creating a 512MB segment on disk $disk.\n");

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

	$freespace = $disk . "_freespace2";

	$size1 = get_object_size($segment);
	$sectors1 = get_blkdev_sectors($segment);

	$rc = compare_sizes($size1, "512MB", 1);
	if ($rc) {
		log_error("Error verifying size of segment $segment.\n");
		goto out;
	}
	
	log_info("2. Expanding segment $segment by 512MB.\n");

	$rc = expand_gpt_segment($segment, $freespace, "512MB");
	if ($rc) {
		log_error("Error expanding segment $segment.\n");
		goto out;
	}

	log_info("3. Verifying expand of segment $segment.\n");

	$size2 = get_object_size($segment);
	$sectors2 = get_blkdev_sectors($segment);

	$rc = compare_sizes($size2, "1GB", 1);
	if ($rc) {
		log_error("Error verifying size of segment $segment.\n");
		goto out;
	}

	$rc = compare_sectors($sectors2,
			      $sectors1 + size_to_sectors("512MB"), 1);
	if ($rc) {
		log_error("Error verifying number of sectors in " .
			  "segment $segment.\n");
		goto out;
	}

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

# Test2
# Create a second segment. Then attempt to expand the first
# segment and verify that it fails.
sub Test2
{
	my $disk = $_[0];
	my $freespace = $disk . "_freespace2";
	my $segment1 = $disk . "1";
	my ($size1, $size2);
	my $rc;

	log_info("Test expanding a segment without adjoining freespace.\n");

	$size1 = get_object_size($segment1);

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

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

	log_info("2. Attempting to expand the first segment $segment1.\n");

	$rc = expand_gpt_segment($segment1, $freespace, "512MB");
	if (!$rc) {
		log_error("Error: Successfully expanded segment $segment1.\n");
		$rc = 1;
		goto out;
	}

	log_info("3. Verifying segment $segment1 was *not* expanded.\n");

	$size2 = get_object_size($segment1);

	$rc = compare_sizes($size1, $size2, 0);
	if ($rc) {
		log_error("Error: Size of segment $segment1 has changed.\n");
		goto out;
	}

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

# Test3
# Shrink the first segment, currently 1GB, by 512MB.
sub Test3
{
	my $disk = $_[0];
	my $segment = $disk . "1";
	my ($size1, $size2);
	my ($sectors1, $sectors2);
	my $rc;

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

	log_info("1. Shrinking segment $segment by 512MB.\n");

	$size1 = get_object_size($segment);
	$sectors1 = get_blkdev_sectors($segment);

	$rc = shrink_gpt_segment($segment, "512MB");
	if ($rc) {
		log_error("Error shrinking segment $segment.\n");
		goto out;
	}

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

	$size2 = get_object_size($segment);
	$sectors2 = get_blkdev_sectors($segment);

	$rc = compare_sizes($size2, "512MB", 1);
	if ($rc) {
		log_error("Error verifying new size of segment $segment.\n");
		goto out;
	}

	$rc = compare_sectors($sectors2,
			      $sectors1 - size_to_sectors("512MB"), 2);
	if ($rc) {
		log_error("Error verifying new number of sectors in " .
			  "segment $segment.\n");
		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, "2.5GB");
	if ($rc) {
		goto finish;
	}

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

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

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

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

finish:
}

