# -*-perl-*-
-# Before `make install' is performed this script should be runnable with
-# `make test'. After `make install' it should work as `perl PSPP.t'
+# Before `make install' is performed this script should be runnable
+# with `make test' as long as libpspp-core-$VERSION.so is in
+# LD_LIBRARY_PATH. After `make install' it should work as `perl
+# PSPP.t'
#########################
# change 'tests => 1' to 'tests => last_test_to_print';
-use Test::More tests => 19;
+use Test::More tests => 37;
use Text::Diff;
use File::Temp qw/ tempfile tempdir /;
BEGIN { use_ok('PSPP') };
#########################
+sub compare
+{
+ my $file = shift;
+ my $pattern = shift;
+ return ! diff ("$file", \$pattern);
+}
+
+my $pspp_cmd = $ENV{PSPP_TEST_CMD};
+
+if ( ! $pspp_cmd)
+{
+ $pspp_cmd="pspp";
+}
+
sub run_pspp_syntax
{
my $tempdir = shift;
my $syntax = shift;
- my $result = shift;
+
my $syntaxfile = "$tempdir/foo.sps";
open (FH, ">$syntaxfile");
print FH "$syntax";
close (FH);
- system ("cd $tempdir; pspp -o raw-ascii $syntaxfile");
+ system ("cd $tempdir; $pspp_cmd -o pspp.csv $syntaxfile");
+}
- my $diff = diff ("$tempdir/pspp.list", \$result);
+sub run_pspp_syntax_cmp
+{
+ my $tempdir = shift;
+ my $syntax = shift;
+
+ my $result = shift;
+
+ run_pspp_syntax ($tempdir, $syntax);
+
+ my $diff = diff ("$tempdir/pspp.csv", \$result);
if ( ! ($diff eq ""))
{
}
-# Insert your test code below, the Test::More module is use()ed here so read
+# Insert your test code below, the Test::More module is used here so read
# its man page ( perldoc Test::More ) for help writing this test script.
{
my $d = PSPP::Dict->new();
ok (ref $d, "Dictionary Creation");
+ ok ($d->get_var_cnt () == 0);
$d->set_label ("My Dictionary");
- $d->set_documents ("These Documents");
+ $d->add_document ("These Documents");
# Tests for variable creation
my $var0 = PSPP::Var->new ($d, "le");
ok (!ref $var0, "Trap illegal variable name");
+ ok ($d->get_var_cnt () == 0);
$var0 = PSPP::Var->new ($d, "legal");
ok (ref $var0, "Accept legal variable name");
+ ok ($d->get_var_cnt () == 1);
my $var1 = PSPP::Var->new ($d, "legal");
ok (!ref $var1, "Trap duplicate variable name");
+ ok ($d->get_var_cnt () == 1);
$var1 = PSPP::Var->new ($d, "money",
(fmt=>PSPP::Fmt::DOLLAR,
width=>4, decimals=>2) );
ok (ref $var1, "Accept valid format");
+ ok ($d->get_var_cnt () == 2);
$d->set_weight ($var1);
)
);
- $d->set_documents ("This should not appear");
+ $d->add_document ("This should not appear");
$d->clear_documents ();
$d->add_document ("This is a document line");
}
ok (-s "$tempfile", "existance2");
- ok (run_pspp_syntax ($tempdir, <<SYNTAX, <<RESULT), "Check output");
+ ok (run_pspp_syntax_cmp ($tempdir, <<SYNTAX, <<RESULT), "Check output");
GET FILE='$tempfile'.
DISPLAY DICTIONARY.
DISPLAY DOCUMENTS.
LIST.
SYNTAX
-1.1 DISPLAY.
-+--------+-------------------------------------------+--------+
-|Variable|Description |Position|
-#========#===========================================#========#
-|id |Format: F2.0 | 1|
-| |Measure: Scale | |
-| |Display Alignment: Right | |
-| |Display Width: 8 | |
-+--------+-------------------------------------------+--------+
-|name |Format: A20 | 2|
-| |Measure: Nominal | |
-| |Display Alignment: Left | |
-| |Display Width: 20 | |
-+--------+-------------------------------------------+--------+
-
-File label:
-This is the file label
-
-Documents in the active file:
+Variable,Description,Position
+id,Format: F2.0,1
+name,Format: A20,2
-This is a document line
+File label: This is the file label
-id name
--- --------------------
-21 wheelbarrow
+Documents in the active dataset:
+This is a document line
+
+Table: Data List
+id,name
+21,wheelbarrow
RESULT
$longstr->set_label ("My Long String");
my $re = $longstr->add_value_label ("xxx", "xfoo");
- ok (($re == 0), "Long strings cant have labels");
-
- ok ($PSPP::errstr eq "Cannot add label to a long string variable", "Error msg");
+ ok ($re, "Value label for long string");
$int->set_missing_values (9, 99);
$sysfile->close ();
- ok (run_pspp_syntax ($tempdir, <<SYNTAX, <<RESULT), "Check output 2");
+ ok (run_pspp_syntax_cmp ($tempdir, <<SYNTAX, <<RESULT), "Check output 2");
GET FILE='$tempfile'.
DISPLAY DICTIONARY.
SYNTAX
-1.1 DISPLAY.
-+----------+-----------------------------------------+--------+
-|Variable |Description |Position|
-#==========#=========================================#========#
-|integer |My Integer | 1|
-| |Format: F8.0 | |
-| |Measure: Scale | |
-| |Display Alignment: Right | |
-| |Display Width: 8 | |
-| |Missing Values: 9; 99 | |
-| +-----+-----------------------------------+ |
-| | 0|Zero | |
-| | 1|Unity | |
-| | 2|Duality | |
-+----------+-----+-----------------------------------+--------+
-|string |My String | 2|
-| |Format: A8 | |
-| |Measure: Nominal | |
-| |Display Alignment: Left | |
-| |Display Width: 8 | |
-| |Missing Values: "this "; "that " | |
-| +-----+-----------------------------------+ |
-| | xx|foo | |
-| | yy|bar | |
-+----------+-----+-----------------------------------+--------+
-|longstring|My Long String | 3|
-| |Format: A9 | |
-| |Measure: Nominal | |
-| |Display Alignment: Left | |
-| |Display Width: 9 | |
-+----------+-----------------------------------------+--------+
-
+Variable,Description,Position
+integer,"Label: My Integer
+Format: F8.0
+Missing Values: 9; 99
+
+Value,Label
+0,Zero
+1,Unity
+2,Duality",1
+string,"Label: My String
+Format: A8
+Missing Values: ""this ""; ""that ""
+
+Value,Label
+xx ,foo
+yy ,bar",2
+longstring,"Label: My Long String
+Format: A9
+
+Value,Label
+xxx ,xfoo",3
RESULT
}
}
+
+sub generate_sav_file
+{
+ my $filename = shift;
+ my $tempdir = shift;
+
+ run_pspp_syntax_cmp ($tempdir, <<SYNTAX, <<RESULT);
+data list notable list /string (a8) longstring (a12) numeric (f10) date (date11) dollar (dollar8.2) datetime (datetime17)
+begin data.
+1111 One 1 1/1/1 1 1/1/1+01:01
+2222 Two 2 2/2/2 2 2/2/2+02:02
+3333 Three 3 3/3/3 3 3/3/3+03:03
+. . . . . .
+5555 Five 5 5/5/5 5 5/5/5+05:05
+end data.
+
+
+variable labels string 'A Short String Variable'
+ /longstring 'A Long String Variable'
+ /numeric 'A Numeric Variable'
+ /date 'A Date Variable'
+ /dollar 'A Dollar Variable'
+ /datetime 'A Datetime Variable'.
+
+
+missing values numeric (9, 5, 999).
+
+missing values string ("3333").
+
+add value labels
+ /string '1111' 'ones' '2222' 'twos' '3333' 'threes'
+ /numeric 1 'Unity' 2 'Duality' 3 'Thripality'.
+
+variable attribute
+ variables = numeric
+ attribute=colour[1]('blue') colour[2]('pink') colour[3]('violet')
+ attribute=size('large') nationality('foreign').
+
+
+save outfile='$filename'.
+SYNTAX
+
+RESULT
+
+}
+
+
+# Test to make sure that the dictionary survives the sysfile.
+# Thanks to Rob Messer for reporting this problem
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+ my $tempfile = "$tempdir/testfile.sav";
+ my $sysfile ;
+
+ {
+ my $d = PSPP::Dict->new();
+
+ PSPP::Var->new ($d, "id",
+ (
+ fmt=>PSPP::Fmt::F,
+ width=>2,
+ decimals=>0
+ )
+ );
+
+ $sysfile = PSPP::Sysfile->new ("$tempfile", $d);
+ }
+
+ my $res = $sysfile->append_case ([3]);
+
+ ok ($res, "Dictionary survives sysfile");
+}
+
+
+# Basic reader test
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ generate_sav_file ("$tempdir/in.sav", "$tempdir");
+
+ my $sf = PSPP::Reader->open ("$tempdir/in.sav");
+
+ my $dict = $sf->get_dict ();
+
+ open (MYFILE, ">$tempdir/out.txt");
+ for ($v = 0 ; $v < $dict->get_var_cnt() ; $v++)
+ {
+ my $var = $dict->get_var ($v);
+ my $name = $var->get_name ();
+ my $label = $var->get_label ();
+
+ print MYFILE "Variable $v is \"$name\", label is \"$label\"\n";
+
+ my $vl = $var->get_value_labels ();
+
+ print MYFILE "Value Labels:\n";
+ print MYFILE "$_ => $vl->{$_}\n" for (sort keys %$vl);
+ }
+
+ while (my @c = $sf->get_next_case () )
+ {
+ for ($v = 0; $v < $dict->get_var_cnt(); $v++)
+ {
+ print MYFILE "val$v: \"$c[$v]\"\n";
+ }
+ print MYFILE "\n";
+ }
+
+ close (MYFILE);
+
+ok (compare ("$tempdir/out.txt", <<EOF), "Basic reader operation");
+Variable 0 is "string", label is "A Short String Variable"
+Value Labels:
+1111 => ones
+2222 => twos
+3333 => threes
+Variable 1 is "longstring", label is "A Long String Variable"
+Value Labels:
+Variable 2 is "numeric", label is "A Numeric Variable"
+Value Labels:
+1 => Unity
+2 => Duality
+3 => Thripality
+Variable 3 is "date", label is "A Date Variable"
+Value Labels:
+Variable 4 is "dollar", label is "A Dollar Variable"
+Value Labels:
+Variable 5 is "datetime", label is "A Datetime Variable"
+Value Labels:
+val0: "1111 "
+val1: "One "
+val2: "1"
+val3: "13197686400"
+val4: "1"
+val5: "13197690060"
+
+val0: "2222 "
+val1: "Two "
+val2: "2"
+val3: "13231987200"
+val4: "2"
+val5: "13231994520"
+
+val0: "3333 "
+val1: "Three "
+val2: "3"
+val3: "13266028800"
+val4: "3"
+val5: "13266039780"
+
+val0: ". "
+val1: ". "
+val2: ""
+val3: ""
+val4: ""
+val5: ""
+
+val0: "5555 "
+val1: "Five "
+val2: "5"
+val3: "13334630400"
+val4: "5"
+val5: "13334648700"
+
+EOF
+
+}
+
+
+# Check that we can stream one file into another
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ generate_sav_file ("$tempdir/in.sav", "$tempdir");
+
+ my $input = PSPP::Reader->open ("$tempdir/in.sav");
+
+ my $dict = $input->get_dict ();
+
+ my $output = PSPP::Sysfile->new ("$tempdir/out.sav", $dict);
+
+ while (my (@c) = $input->get_next_case () )
+ {
+ $output->append_case (\@c);
+ }
+
+ $output->close ();
+
+
+ #Check the two files are the same (except for metadata)
+
+ run_pspp_syntax ($tempdir, <<SYNTAX);
+ get file='$tempdir/in.sav'.
+ display dictionary.
+ list.
+
+SYNTAX
+
+ system ("cp $tempdir/pspp.csv $tempdir/in.txt");
+
+ run_pspp_syntax ($tempdir, <<SYNTAX);
+ get file='$tempdir/out.sav'.
+ display dictionary.
+ list.
+
+SYNTAX
+
+ ok (! diff ("$tempdir/pspp.csv", "$tempdir/in.txt"), "Streaming of files");
+}
+
+
+
+# Check that the format_value function works properly
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ run_pspp_syntax ($tempdir, <<SYNTAX);
+
+data list list /d (datetime17).
+begin data.
+11/9/2001+08:20
+end data.
+
+save outfile='$tempdir/dd.sav'.
+
+SYNTAX
+
+ my $sf = PSPP::Reader->open ("$tempdir/dd.sav");
+
+ my $dict = $sf->get_dict ();
+
+ my (@c) = $sf->get_next_case ();
+
+ my $var = $dict->get_var (0);
+ my $val = $c[0];
+ my $formatted = PSPP::format_value ($val, $var);
+ my $str = gmtime ($val - PSPP::PERL_EPOCH);
+ print "Formatted string is \"$formatted\"\n";
+ ok ( $formatted eq "11-SEP-2001 08:20", "format_value function");
+ ok ( $str eq "Tue Sep 11 08:20:00 2001", "Perl representation of time");
+}
+
+
+# Check that attempting to open a non-existent file results in an error
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ unlink ("$tempdir/no-such-file.sav");
+
+ my $sf = PSPP::Reader->open ("$tempdir/no-such-file.sav");
+
+ ok ( !ref $sf, "Returns undef on opening failure");
+
+ ok ("$PSPP::errstr" eq "An error occurred while opening `$tempdir/no-such-file.sav': No such file or directory.",
+ "Error string on open failure");
+}
+
+
+# Missing value tests.
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ generate_sav_file ("$tempdir/in.sav", "$tempdir");
+
+ my $sf = PSPP::Reader->open ("$tempdir/in.sav");
+
+ my $dict = $sf->get_dict ();
+
+
+ my (@c) = $sf->get_next_case ();
+
+ my $stringvar = $dict->get_var (0);
+ my $numericvar = $dict->get_var (2);
+ my $val = $c[0];
+
+ ok ( !PSPP::value_is_missing ($val, $stringvar), "Missing Value Negative String");
+
+ $val = $c[2];
+
+ ok ( !PSPP::value_is_missing ($val, $numericvar), "Missing Value Negative Num");
+
+ @c = $sf->get_next_case ();
+ @c = $sf->get_next_case ();
+
+ $val = $c[0];
+ ok ( PSPP::value_is_missing ($val, $stringvar), "Missing Value Positive");
+
+ @c = $sf->get_next_case ();
+ $val = $c[2];
+ ok ( PSPP::value_is_missing ($val, $numericvar), "Missing Value Positive SYS");
+
+ @c = $sf->get_next_case ();
+ $val = $c[2];
+ ok ( PSPP::value_is_missing ($val, $numericvar), "Missing Value Positive Num");
+}
+
+
+#Test reading of custom attributes
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ generate_sav_file ("$tempdir/in.sav", "$tempdir");
+
+ my $sf = PSPP::Reader->open ("$tempdir/in.sav");
+
+ my $dict = $sf->get_dict ();
+
+ my $var = $dict->get_var_by_name ("numeric");
+
+ my $attr = $var->get_attributes ();
+
+ open (MYFILE, ">$tempdir/out.txt");
+
+ foreach $k (sort (keys (%$attr)))
+ {
+ my $ll = $attr->{$k};
+ print MYFILE "$k =>";
+ print MYFILE map "$_\n", join ', ', @$ll;
+ }
+
+ close (MYFILE);
+
+ ok (compare ("$tempdir/out.txt", <<'EOF'), "Custom Attributes");
+$@Role =>0
+colour =>blue, pink, violet
+nationality =>foreign
+size =>large
+EOF
+}
+
+
+# Test of the get_case_cnt function
+{
+ my $tempdir = tempdir( CLEANUP => 1 );
+
+ generate_sav_file ("$tempdir/in.sav", "$tempdir");
+
+ my $sf = PSPP::Reader->open ("$tempdir/in.sav");
+
+ my $n = $sf->get_case_cnt ();
+
+ ok ($n == 5, "Case count");
+}