#!/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 moving of DOS segments.
#
# Test1: Create a 200MB primary segment. Then move it.
# Test2: Expand the segment by 100MB. Then try to move it back to its
#        original position, which should fail.

use strict;
use warnings;

use Evms::Common;
use Evms::Log;
use Evms::Object;
use Evms::Volume;
use Evms::Dos;
use Evms::DM;

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

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

	$rc = assign_dos_plugin($disk);

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

# Test1
# Create a 1GB primary segment. Then move it.
sub Test1
{
	my $disk = $_[0];
	my $freespace = $disk . "_freespace1";
	my $segment = $disk . "1";
	my $volume = "/dev/evms/" . $segment;
	my $size = "200MB";
	my (%details1, %details2);
	my $rc;

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

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

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

	log_info("2. Creating a compatibility volume from segment $segment.\n");

	$rc = create_compatibility_volume($segment);
	if ($rc) {
		log_error("Error creating compatibility volume.\n");
		goto out;
	}

	log_info("3. Getting details for segment $segment before the move.\n");

	%details1 = get_dos_segment_details($segment);
	log_debug("     starting LBA = $details1{'Start'}\n");
	log_debug("     size = $details1{'Size'}\n");
	log_debug("     size in sectors = $details1{'Sectors'}\n");

	log_info("4. Writing initial pattern to volume $volume.\n");

	$rc = write_sequence($volume, $details1{'Sectors'});
	if ($rc) {
		log_error("Error initializing pattern on volume $volume.\n");
		goto out;
	}

	log_info("5. Validating pattern on volume $volume before the move.\n");

	$rc = validate_sequence($volume, $details1{'Sectors'});
	if ($rc) {
		log_error("Error validating pattern on volume $volume.\n");
		goto out;
	}

	log_info("6. Moving segment $segment.\n");

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

	log_info("7. Comparing details for segment $segment after the move.\n");

	%details2 = get_dos_segment_details($segment);
	log_debug("     starting LBA = $details2{'Start'}\n");
	log_debug("     size = $details2{'Size'}\n");
	log_debug("     size in sectors = $details2{'Sectors'}\n");

	$rc = compare_sizes($details1{'Size'}, $details2{'Size'}, 0);
	if ($rc) {
		log_error("Size of segment $segment has changed.\n");
		goto out;
	}

	$rc = compare_sectors($details1{'Sectors'}, $details2{'Sectors'}, 0);
	if ($rc) {
		log_error("Size in sectors in segment $segment has changed.\n");
		goto out;
	}

	$rc = compare_sectors($details1{'Start'} + $details1{'Sectors'},
			      $details2{'Start'}, 1);
	if ($rc) {
		log_error("Starting LBA did not move the correct amount.\n");
		goto out;
	}

	log_info("8. Validating pattern on volume $volume after the move.\n");

	$rc = validate_sequence($volume, $details2{'Sectors'});
	if ($rc) {
		log_error("Error validating volume $volume.\n");
		goto out;
	}

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

# Test2
# Expand the segment. Then try to move it back to its original position
# (which should fail).
sub Test2
{
	my $disk = $_[0];
	my $segment = $disk . "1";
	my $freespace1 = $disk . "_freespace1";
	my $freespace2 = $disk . "_freespace2";
	my $size = "100MB";
	my (%details1, %details2);
	my $rc;

	log_info("Test moving a segment without sufficient freespace.\n");

	log_info("1. Expanding segment $segment by $size.\n");

	$rc = expand_dos_segment($segment, $freespace2, $size);
	if ($rc) {
		log_error("Error expanding segment $segment.\n");
		goto out;
	}

	%details1 = get_dos_segment_details($segment);

	log_info("2. Attempting to move segment $segment to the " .
		 "front of disk $disk.\n");

	$rc = move_dos_segment($segment, $freespace1);
	if (!$rc) {
		log_error("Error: successfully moved segment $segment.\n");
		$rc = 1;
		goto out;
	}

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

	%details2 = get_dos_segment_details($segment);

	$rc = compare_sectors($details1{"Start"}, $details2{"Start"}, 0);
	if ($rc) {
		log_error("Error: Starting LBA for segment $segment " .
			  "has moved.\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, "512MB");
	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;
	}

finish:
}

