#!/usr/bin/perl

#Whether or not to perform interactive tests
$interactive=1;

#The number of sensors being tested
$total_sensor_count = 107;
$total_vv_sensor_count = 134;

#The file to store results from individual queries
$default = "default.txt";
#$default = "default";
#The file to store results from -a queries
$default_a = "d.txt";

#The file to store results from individual queries
$verbose = "verbose.txt";
#The file to store results from -a queries
$verbose_a = "v.txt";

#The file to store results from individual queries
$vverbose = "vverbose.txt";
#The file to store results from -a queries
$vverbose_a = "vv.txt";

#used to differentiate between the current processing mode
#ugly freaking hack
$default_mode = "default_mode";
$verbose_mode = "verbose_mode";
$mode = $default_mode;

#The units that linear sensors use, so we can 
#ignore trival reading differences
$temp = "Degrees C";
$temp_threshold = 10;

$volt = "Volts";
$volt_threshold = 2.0;

$rpms = "RPM";
$rpms_threshold = 100;

#The path to the sensors executable
#print "Please enter the full path to sensors:";
#chomp($sensors = <STDIN>);
$sensors = "/usr/sbin/sensors";

#  print "Would you like to run the interactive portions of the test(y/n)[y]:";
#INTERACTIVE:  
#  chomp($in = <STDIN>);

#  if($in ne "n" && $in ne "y" && $in ne ""){
    #print "Wrong input :$in:\n";
#    print "Please enter (y/n)[y]:";
#    goto INTERACTIVE;
#  }

#  if($in eq "n"){ $interactive = 0;}
  
#  elsif($in eq "y" || $in eq "") {$interactive = 1;}
$interactive = 1;

system("clear");
#test1();
#test2();
#test3();
#test5();
test_group();
#test8();
cleanup();

sub cleanup{
  system(" rm -f *.txt");
}

sub verify_correct{

INPUT:  
  chomp($in = <STDIN>);
  
  if($in ne "n" && $in ne "y" && $in ne ""){
    #print "Wrong input :$in:\n";
    print "Please enter (y/n)[y]:";
    goto INPUT;
  }

  ($in eq "y" || $in eq "") or die "Test Case @_[0] failed!\n";

} 

sub interactive_line_diff {

  open(D1, @_[0]) or die "Can't open file @_[0]";
  open(D2, @_[1]) or die "Can't open file @_[1]";

  while(<D1>){
    $a = <D2>;

    if($_ ne $a){
      check_trivial($_, $a);
    }
  }
}

sub check_linear_verbose{
  my $str_1 = @_[0];
  my $str_2 = @_[1];

  #get the actual reading
  my @words_1 = split(/ /, $str_1);
  my @words_2 = split(/ /, $str_2);

  #get rid of the units
  my $unit_1 = pop(@words_1);
  print "Popped $unit_1\n";
  my $unit_2 = pop(@words_2);
  print "Popped $unit_2\n";

  #get the two values
  my $val_1 = pop(@words_1);
  my $val_2 = pop(@words_2);
  if($val_1 =~/Degrees/){
    $val_1 = pop(@words_1);
    $val_2 = pop(@words_2);
  }
  print "Checking $val_1 : $val_2\n";
  my $diff  = abs($val_1 - $val_2);

  if($unit_1 =~/C/){
    print "temp diff $diff\n";
    return ($diff < $temp_threshold);
  }
  elsif($unit_1 =~/$volt/){
    #print "volt diff $diff\n";
    return ($diff < $volt_threshold);
  }
  elsif($unit_1 =~/$rpms/){
    #print "rpms diff $diff\n";
    return ($diff < $rpms_threshold);
  }
  else{
    return 0;
  } 
}

sub check_linear_default{
  my $str_1 = @_[0];
  my $str_2 = @_[1];

  #get the actual reading
  my @words_1 = split(/ /, $str_1);
  my @words_2 = split(/ /, $str_2);
  my $unit_1 = @words_1[$#words_1-2];
  my $unit_2 = @words_2[$#words_2-2];
  my $val_1 = @words_1[$#words_1-3];
  my $val_2 = @words_2[$#words_2-3];

  #get the units
  my $i;
  print "\n\n";
  print"Entered linear_default\n";
  #for($i=1;$i<=$#words_1;$i++){
  #  if( @words_1[$i] =~/Temperature/ ||
  #      @words_1[$i] =~/Voltage/ ||
#	@words_1[$i] =~/RPM/ )
 #     {
 #       $unit_1 = @words_1[$i];
 #       print "Units 1: $unit_1\n";
 #       $unit_2 = @words_2[$i];
 #       print "Units 2: $unit_2\n";
#	last;
#      }
#  }


  #get the two values
  #my $val_1;
  #my $val_2;
  #if($unit_1 =~/RPM/){
  #  $val_1 = @words_1[$i-1];
  #  $val_2 = @words_2[$i-1];
  #}
  #else {
  #  $val_1 = @words_1[$i+1];
  #  $val_2 = @words_2[$i+1];
  #}
  print "Checking $val_1 : $val_2\n";
  my $diff  = abs($val_1 - $val_2);

  print "About to check for units: $unit_1\n";

  if($unit_1 =~/C/){
    print "temp diff $diff\n";
    return ($diff < $temp_threshold);
  }
  elsif($unit_1 =~/V/){
    print "volt diff $diff\n";
    return ($diff < $volt_threshold);
  }
  elsif($unit_1 =~/RPM/){
    print "rpms diff $diff\n";
    return ($diff < $rpms_threshold);
  }
  else{
    return 0;
  } 

}

sub check_trivial {
  my $trivial = 0;
  my $sensor_a = @_[0];
  my $sensor_b = @_[1];
  
  #if the lines are an actual linear reading we can 
  #probably just determine if its trivial automatically
  
  print"Entered check_trivial\n";
  #Temperature Voltage Fan Speed
  #if( ($sensor_a =~/$temp/ && $sensor_b =~/$temp/) ||
  #    ($sensor_a =~/$volt/ && $sensor_b =~/$volt/) ||
  #    ($sensor_a =~/$rpms/ && $sensor_b =~/$rpms/) )
  if( ($sensor_a =~/low\S*nom\S*high/ && 
        $sensor_b =~/low\S*nom\S*high/) && 
	$mode eq $default_mode
    )
  { $trivial = check_linear_default($sensor_a, $sensor_b);}
  elsif($mode eq $verbose_mode && 
        ( ($sensor_a =~/$temp/ && $sensor_b =~/$temp/) ||
          ($sensor_a =~/$volt/ && $sensor_b =~/$volt/) ||
          ($sensor_a =~/$rpms/ && $sensor_b =~/$rpms/) 
	)
       )
  {$trivial = check_linear_verbose($sensor_a, $sensor_b);}
      
  #if it couldn't be resolved automatically, we must
  #go interactive
  if(!$trivial){
    print "$sensor_a\n doesn't match\n$sensor_b\n";
    print("Is the difference trivial? (y/n)[y]:");
    verify_correct(0);
  }
}

sub sensor_diff {

  my $SEN_A = @_[0];
  my $SEN_B = @_[1]; 
 
  #print "In sensor diff\n";
  do{
    chomp($sensor_a = <$SEN_A>);
    chomp($sensor_b = <$SEN_B>);
    #print "READ $sensor_a  :  $sensor_b\n";
    
    if($sensor_a ne $sensor_b){
      check_trivial($sensor_a, $sensor_b);
    }
  
  }while($sensor_a ne "");

  #update on progress
  select(STDOUT);
  $|=1;
  print ".";
}

sub sensor_diff_file {
  my $new_file   = @_[0];
  my $check_file = @_[1];
  my $ordered    = @_[2];
  my $rand_sensors = @_[3];


  #print "About to diff $new_file : $check_file\n";
  if($ordered){
    open(NEW, $new_file) or die "Can't open file @_[0]";
    open(CHECK, $check_file) or die "Can't open file @_[1]";
    do{
      chomp($a = <NEW>);
      chomp($b = <CHECK>);

      #print "READ $a  :  $b\n";
      
      if($a =~/Record ID/){
        print "Checking sensor: $a\n";
        sensor_diff(NEW, CHECK);
      }
      
    }while(!eof(NEW));
  }
  else{
    open(NEW, $new_file) or die "Can't open file @_[0]";
    my @sens = split(/ /, $rand_sensors);
    
    do{
      #make sure that this is a sensor we requested and in the order we requested
      chomp($a = <NEW>);
      ($a =~/$expected_sensor/) or die "sensors -s $rand_sensors option resulted in improper output\n";
      
      #need to index into the file used to validate output 
      #for the record that matches the current record 
      open(CHECK, $check_file) or die "Can't open file @_[1]";
      chomp($b = <CHECK>);
      while($a ne $b){
       chomp($b = <CHECK>);
       #print "Read $b\n";
      }

      #print "READ $a  :  $b\n";
     
      #now that the proper spot has been found
      sensor_diff(NEW, CHECK);
      close(CHECK);
      
    }while(!eof(NEW));
  }
  print "\nOutput Matches!\n\n";
}

sub test1(){
  for($i=1;$i<=$total_sensor_count;$i++){
    system("clear");
    #query the default output level
    if($interactive){
      system("sudo $sensors -s $i");
      print("Is the default level output for sensor $i correct? (y/n)[y]:");
      verify_correct(1);
    }
    system("sudo $sensors -s $i >> $default");

    #
    ##query the verbose output level
    #
    if($interactive){
      system("sudo sensors -v -s $i");
      print("Is the verbose level output for sensor $i correct? (y/n)[y]:");
      verify_correct(1);
    }
    system("sudo $sensors -v -s $i >> $verbose");

    #
    ##query the very verbose output level
    #
    if($interactive){
      system("sudo sensors -vv -s $i");
      print("Is the very verbose level output for sensor $i correct? (y/n)[y]:");
      verify_correct(1);
    }
    system("sudo $sensors -vv -s $i >> $vverbose");
  }

  #need to finish up the sensors that are only displayed in -vv mode
  for($i=$total_sensor_count+1;$i<=$total_vv_sensor_count;$i++){
    #
    ##query the very verbose output level
    #
    if($interactive){
      system("sudo sensors -vv -s $i");
      print("Is the very verbose level output for sensor $i correct? (y/n)[y]:");
      verify_correct(1);
    }
    system("sudo $sensors -vv -s $i >> $vverbose");
  }

}

sub test2 {
  #
  ##Test the default output
  #
  system("sudo $sensors > $default_a");
  print "Checking if the default level output is correct:\n\n";
  $mode=$default_mode;
  interactive_line_diff($default, $default_a, 1);

  #
  ##Test the verbose level output
  #
  system("sudo $sensors -v > $verbose_a");
  print "\n\nChecking if the verbose level output is correct:\n\n";
  $mode=$verbose_mode;
  sensor_diff_file($verbose, $verbose_a, 1);

  #
  ##Test the very verbose level -a output
  #
  system("sudo $sensors -vv > $vverbose_a");
  print "Checking if the very verbose level output is correct:\n";
  sensor_diff_file($vverbose, $vverbose_a, 1);
}

sub file_contains{
  my $file   = @_[0];
  my $exp    = @_[1];
  my $wanted = @_[2];

  #open the file
  open(FILE, $file) or die "Can't open file $file";
  
  while(<FILE>){
    #if its not wanted and we found the pattern in the file
    #the test case failed
    if($_ =~/$exp/ && !$wanted){
      die "Test case failed!\n";
    }
    #if its wanted and we found the pattern just return
    elsif($_ =~/$exp/){
      close(FILE);
      return;
    }
  }

}

$group_file = "groups.txt";
sub test_group{
  system("sudo $sensors --list-groups >groups.txt");
  open(GROUP, "groups.txt") or die "Can't open groups.txt";

  #get rid of the first fluff line
  <GROUP>;

  while(<GROUP>){
    if($interactive){
      system("clear");
    }
   chomp($_);
    #print "String is $_\n";

    if( ($_ =~/System groups/) ||
        ($_ =~/Aliases/) ||
	($_ !~/\S*/)){
      next;
    }

    if(/\=/){
      #print "This is an alias is $_\n";
      @sp = split(/\=/, $_);
      #print "First element is: @sp[0]\n";
      $_ = @sp[0];
      chop;
    }

    print "ABOUT TO CHECK GROUP \"$_\"\n\n";

    #default
    print("sudo $sensors -g \"$_\"\n");
    system("sudo $sensors -g \"$_\"");
    if($interactive){
      print("Is the output for sensor group \"$_\" correct? (y/n)[y]:");
      verify_correct(6);
    }

    #verbose
    print("\nsudo $sensors -v -g \"$_\"\n");
    system("sudo $sensors -v -g \"$_\"");
    if($interactive){
      print("Is the -v output for sensor group \"$_\" correct? (y/n)[y]:");
      verify_correct(6);
    }
    
    #very verbose
    print("\nsudo $sensors -vv -g \"$_\"\n");
    system("sudo $sensors -vv -g \"$_\"");
    if($interactive){
      print("Is the -vv output for sensor group \"$_\" correct? (y/n)[y]:");
      verify_correct(6);
    }
  }
}
