1 dnl PSPP - a program for statistical analysis.
2 dnl Copyright (C) 2017, 2020, 2021 Free Software Foundation, Inc.
4 dnl This program is free software: you can redistribute it and/or modify
5 dnl it under the terms of the GNU General Public License as published by
6 dnl the Free Software Foundation, either version 3 of the License, or
7 dnl (at your option) any later version.
9 dnl This program is distributed in the hope that it will be useful,
10 dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
11 dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 dnl GNU General Public License for more details.
14 dnl You should have received a copy of the GNU General Public License
15 dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
17 AT_BANNER([Perl module tests])
19 m4_divert_push([PREPARE_TESTS])
20 # Find the Address Sanitizer library that PSPP is linked against, if any.
21 # If it exists, it needs to be preloaded when we run Perl.
22 asan_lib=$("$abs_top_builddir/libtool" --mode=execute ldd \
23 "$abs_top_builddir/src/ui/terminal/pspp" 2>/dev/null \
26 if test -e "$asan_lib"; then
33 dnl This command can be used to run with the PSPP Perl module after it has been
34 dnl built (with "make") but before it has been installed. The -I options are
35 dnl equivalent to "use ExtUtils::testlib;" inside the Perl program, but it does
36 dnl not need to be run with the perl-module build directory as the current
37 dnl working directory.
39 LD_PRELOAD="$asan_lib":"$LD_PRELOAD" \
40 LD_LIBRARY_PATH="$abs_top_builddir/src/.libs" \
41 DYLD_LIBRARY_PATH="$abs_top_builddir/src/.libs" \
42 ASAN_OPTIONS="$ASAN_OPTIONS detect_leaks=false" \
43 $PERL -I"$abs_top_builddir/perl-module/blib/arch" \
44 -I"$abs_top_builddir/perl-module/blib/lib" "$@"
46 m4_divert_pop([PREPARE_TESTS])
48 AT_SETUP([Perl create system file])
49 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
55 my $d = PSPP::Dict->new();
56 die "dictionary creation" if !ref $d;
57 die if $d->get_var_cnt () != 0;
59 $d->set_label ("My Dictionary");
60 $d->set_documents ("These Documents");
62 # Tests for variable creation
64 my $var0 = PSPP::Var->new ($d, "le");
65 die "trap illegal variable name" if ref $var0;
66 die if $d->get_var_cnt () != 0;
68 $var0 = PSPP::Var->new ($d, "legal");
69 die "accept legal variable name" if !ref $var0;
70 die if $d->get_var_cnt () != 1;
72 my $var1 = PSPP::Var->new ($d, "money",
73 (fmt=>PSPP::Fmt::DOLLAR,
74 width=>4, decimals=>2) );
75 die "cappet valid format" if !ref $var1;
76 die if $d->get_var_cnt () != 2;
78 $d->set_weight ($var1);
80 my $sysfile = PSPP::Sysfile->new ('testfile.sav', $d);
81 die "create sysfile object" if !ref $sysfile;
85 AT_CHECK([run_perl_module test.pl])
86 AT_DATA([dump-dict.sps],
87 [GET FILE='testfile.sav'.
93 AT_CHECK([pspp -O format=csv dump-dict.sps], [0], [dnl
101 Name,Position,Measurement Level,Role,Width,Alignment,Print Format,Write Format
102 legal,1,Scale,Input,8,Right,F9.2,F9.2
103 money,2,Scale,Input,8,Right,DOLLAR6.2,DOLLAR6.2
105 dump-dict.sps:5: note: SHOW: WEIGHT is money.
109 AT_SETUP([Perl writing cases to system files])
110 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
116 my $d = PSPP::Dict->new();
117 PSPP::Var->new ($d, "id",
125 PSPP::Var->new ($d, "name",
132 $d->set_documents ("This should not appear");
133 $d->clear_documents ();
134 $d->add_document ("This is a document line");
136 $d->set_label ("This is the file label");
138 # Check that we can write cases to system files.
139 my $sysfile = PSPP::Sysfile->new ("testfile.sav", $d);
140 my $res = $sysfile->append_case ( [34, "frederick"]);
141 die "append case" if !$res;
143 $res = $sysfile->append_case ( [34, "frederick", "extra"]);
144 die "append case with too many variables" if $res;
147 # Check that sysfiles are closed properly automaticallly in the destructor.
148 my $sysfile2 = PSPP::Sysfile->new ("testfile2.sav", $d);
149 $res = $sysfile2->append_case ( [21, "wheelbarrow"]);
150 die "append case 2" if !$res;
152 $res = $sysfile->append_case ( [34, "frederick", "extra"]);
153 die "append case with too many variables" if $res;
155 # Don't close. We want to test that the destructor does that.
157 AT_CHECK([run_perl_module test.pl])
158 AT_DATA([dump-dicts.sps],
159 [GET FILE='testfile.sav'.
165 GET FILE='testfile2.sav'.
171 AT_CHECK([pspp -O format=csv dump-dicts.sps], [0], [dnl
173 Name,Position,Measurement Level,Role,Width,Alignment,Print Format,Write Format
174 id,1,Scale,Input,8,Right,F2.0,F2.0
175 name,2,Nominal,Input,20,Left,A20,A20
178 Label,This is the file label
181 This is a document line
188 Name,Position,Measurement Level,Role,Width,Alignment,Print Format,Write Format
189 id,1,Scale,Input,8,Right,F2.0,F2.0
190 name,2,Nominal,Input,20,Left,A20,A20
193 Label,This is the file label
196 This is a document line
204 AT_SETUP([Perl write variable parameters])
205 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
211 my $dict = PSPP::Dict->new();
212 die "dictionary creation" if !ref $dict;
214 my $int = PSPP::Var->new ($dict, "integer",
215 (width=>8, decimals=>0) );
217 $int->set_label ("My Integer");
219 $int->add_value_label (99, "Silly");
220 $int->clear_value_labels ();
221 $int->add_value_label (0, "Zero");
222 $int->add_value_label (1, "Unity");
223 $int->add_value_label (2, "Duality");
225 my $str = PSPP::Var->new ($dict, "string",
226 (fmt=>PSPP::Fmt::A, width=>8) );
229 $str->set_label ("My String");
230 $str->add_value_label ("xx", "foo");
231 $str->add_value_label ("yy", "bar");
233 $str->set_missing_values ("this", "that");
235 my $longstr = PSPP::Var->new ($dict, "longstring",
236 (fmt=>PSPP::Fmt::A, width=>9) );
239 $longstr->set_label ("My Long String");
240 my $re = $longstr->add_value_label ("xxx", "xfoo");
242 $int->set_missing_values (9, 99);
244 my $sysfile = PSPP::Sysfile->new ("testfile.sav", $dict);
249 AT_CHECK([run_perl_module test.pl], [0], [], [stderr])
251 AT_DATA([dump-dict.sps],
252 [GET FILE='testfile.sav'.
255 AT_CHECK([pspp -O format=csv dump-dict.sps], [0], [dnl
257 Name,Position,Label,Measurement Level,Role,Width,Alignment,Print Format,Write Format,Missing Values
258 integer,1,My Integer,Scale,Input,8,Right,F8.0,F8.0,9; 99
259 string,2,My String,Nominal,Input,8,Left,A8,A8,"""this ""; ""that """
260 longstring,3,My Long String,Nominal,Input,9,Left,A9,A9,
263 Variable Value,,Label
269 My Long String,xxx,xfoo
273 AT_SETUP([Perl dictionary survives system file])
274 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
283 my $d = PSPP::Dict->new();
285 PSPP::Var->new ($d, "id",
293 $sysfile = PSPP::Sysfile->new ("testfile.sav", $d);
296 my $res = $sysfile->append_case ([3]);
297 print "Dictionary survives sysfile\n" if $res;
299 AT_CHECK([run_perl_module test.pl], [0],
300 [Dictionary survives sysfile
304 m4_define([PERL_GENERATE_SYSFILE],
305 [AT_DATA([sample.sps],
306 [[data list notable list /string (a8) longstring (a12) numeric (f10) date (date11) dollar (dollar8.2) datetime (datetime17)
308 1111 One 1 1/1/1 1 1/1/1+01:01
309 2222 Two 2 2/2/2 2 2/2/2+02:02
310 3333 Three 3 3/3/3 3 3/3/3+03:03
312 5555 Five 5 5/5/5 5 5/5/5+05:05
316 variable labels string 'A Short String Variable'
317 /longstring 'A Long String Variable'
318 /numeric 'A Numeric Variable'
319 /date 'A Date Variable'
320 /dollar 'A Dollar Variable'
321 /datetime 'A Datetime Variable'.
324 missing values numeric (9, 5, 999).
326 missing values string ("3333").
329 /string '1111' 'ones' '2222' 'twos' '3333' 'threes'
330 /numeric 1 'Unity' 2 'Duality' 3 'Thripality'.
334 attribute=colour[1]('blue') colour[2]('pink') colour[3]('violet')
335 attribute=size('large') nationality('foreign').
338 save outfile='sample.sav'.
340 AT_CHECK([pspp -O format=csv sample.sps])])
342 AT_SETUP([Perl read system file])
343 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
344 PERL_GENERATE_SYSFILE
350 my $sf = PSPP::Reader->open ("sample.sav");
352 my $dict = $sf->get_dict ();
354 for (my $v = 0 ; $v < $dict->get_var_cnt() ; $v++)
356 my $var = $dict->get_var ($v);
357 my $name = $var->get_name ();
358 my $label = $var->get_label ();
360 print "Variable $v is \"$name\", label is \"$label\"\n";
362 my $vl = $var->get_value_labels ();
364 print "Value Labels:\n";
365 print "$_ => $vl->{$_}\n" for sort (keys %$vl);
368 while (my @c = $sf->get_next_case () )
370 for (my $v = 0; $v < $dict->get_var_cnt(); $v++)
372 print "val$v: \"$c[$v]\"\n";
377 AT_CHECK([run_perl_module test.pl], [0],
378 [Variable 0 is "string", label is "A Short String Variable"
383 Variable 1 is "longstring", label is "A Long String Variable"
385 Variable 2 is "numeric", label is "A Numeric Variable"
390 Variable 3 is "date", label is "A Date Variable"
392 Variable 4 is "dollar", label is "A Dollar Variable"
394 Variable 5 is "datetime", label is "A Datetime Variable"
434 AT_SETUP([Perl copying system files])
435 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
436 PERL_GENERATE_SYSFILE
442 my $input = PSPP::Reader->open ("sample.sav");
444 my $dict = $input->get_dict ();
446 my $output = PSPP::Sysfile->new ("copy.sav", $dict);
448 while (my (@c) = $input->get_next_case () )
450 $output->append_case (\@c);
455 AT_CHECK([run_perl_module test.pl])
456 AT_DATA([dump-dicts.sps],
457 [GET FILE='sample.sav'.
467 AT_CHECK([pspp -O format=csv dump-dicts.sps], [0],
469 Name,Position,Label,Measurement Level,Role,Width,Alignment,Print Format,Write Format,Missing Values
470 string,1,A Short String Variable,Nominal,Input,8,Left,A8,A8,"""3333 """
471 longstring,2,A Long String Variable,Nominal,Input,12,Left,A12,A12,
472 numeric,3,A Numeric Variable,Nominal,Input,8,Right,F10.0,F10.0,9; 5; 999
473 date,4,A Date Variable,Scale,Input,8,Right,DATE11,DATE11,
474 dollar,5,A Dollar Variable,Scale,Input,8,Right,DOLLAR11.2,DOLLAR11.2,
475 datetime,6,A Datetime Variable,Scale,Input,8,Right,DATETIME17.0,DATETIME17.0,
478 Variable Value,,Label
479 A Short String Variable,1111,ones
482 A Numeric Variable,1,Unity
485 Footnote: a. User-missing value
487 Table: Variable and Dataset Attributes
488 Variable and Name,,Value
489 A Numeric Variable,colour[1],blue
496 string,longstring,numeric,date,dollar,datetime
497 1111,One,1,01-JAN-2001,$1.00,01-JAN-2001 01:01
498 2222,Two,2,02-FEB-2002,$2.00,02-FEB-2002 02:02
499 3333,Three,3,03-MAR-2003,$3.00,03-MAR-2003 03:03
501 5555,Five,5,05-MAY-2005,$5.00,05-MAY-2005 05:05
504 Name,Position,Label,Measurement Level,Role,Width,Alignment,Print Format,Write Format,Missing Values
505 string,1,A Short String Variable,Nominal,Input,8,Left,A8,A8,"""3333 """
506 longstring,2,A Long String Variable,Nominal,Input,12,Left,A12,A12,
507 numeric,3,A Numeric Variable,Nominal,Input,8,Right,F10.0,F10.0,9; 5; 999
508 date,4,A Date Variable,Scale,Input,8,Right,DATE11,DATE11,
509 dollar,5,A Dollar Variable,Scale,Input,8,Right,DOLLAR11.2,DOLLAR11.2,
510 datetime,6,A Datetime Variable,Scale,Input,8,Right,DATETIME17.0,DATETIME17.0,
513 Variable Value,,Label
514 A Short String Variable,1111,ones
517 A Numeric Variable,1,Unity
520 Footnote: a. User-missing value
522 Table: Variable and Dataset Attributes
523 Variable and Name,,Value
524 A Numeric Variable,colour[1],blue
531 string,longstring,numeric,date,dollar,datetime
532 1111,One,1,01-JAN-2001,$1.00,01-JAN-2001 01:01
533 2222,Two,2,02-FEB-2002,$2.00,02-FEB-2002 02:02
534 3333,Three,3,03-MAR-2003,$3.00,03-MAR-2003 03:03
536 5555,Five,5,05-MAY-2005,$5.00,05-MAY-2005 05:05
540 AT_SETUP([Perl value formatting])
541 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
543 [DATA LIST LIST /d (DATETIME17).
548 SAVE OUTFILE='dd.sav'.
550 AT_CHECK([pspp -O format=csv dd.sps], [0],
551 [Table: Reading free-form data from INLINE.
560 my $sf = PSPP::Reader->open ("dd.sav");
562 my $dict = $sf->get_dict ();
564 my (@c) = $sf->get_next_case ();
566 my $var = $dict->get_var (0);
568 my $formatted = PSPP::format_value ($val, $var);
569 my $str = gmtime ($val - PSPP::PERL_EPOCH);
570 print "Formatted string is \"$formatted\"\n";
571 print "Perl representation is \"$str\"\n";
573 AT_CHECK([run_perl_module test.pl], [0],
574 [[Formatted string is "11-SEP-2001 08:20"
575 Perl representation is "Tue Sep 11 08:20:00 2001"
579 AT_SETUP([Perl opening nonexistent file])
580 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
586 my $sf = PSPP::Reader->open ("no-such-file.sav");
588 die "Returns undef on opening failure" if ref $sf;
589 print $PSPP::errstr, "\n";
591 AT_CHECK([run_perl_module test.pl], [0],
592 [[An error occurred while opening `no-such-file.sav': No such file or directory.
594 [[Name "PSPP::errstr" used only once: possible typo at test.pl line 8.
598 AT_SETUP([Perl missing values])
599 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
600 PERL_GENERATE_SYSFILE
606 my $sf = PSPP::Reader->open ("sample.sav");
608 my $dict = $sf->get_dict ();
610 my (@c) = $sf->get_next_case ();
612 my $stringvar = $dict->get_var (0);
613 my $numericvar = $dict->get_var (2);
616 die "Missing Value Negative String"
617 if PSPP::value_is_missing ($val, $stringvar);
621 die "Missing Value Negative Num"
622 if PSPP::value_is_missing ($val, $numericvar);
624 @c = $sf->get_next_case ();
625 @c = $sf->get_next_case ();
628 die "Missing Value Positive"
629 if !PSPP::value_is_missing ($val, $stringvar);
631 @c = $sf->get_next_case ();
633 die "Missing Value Positive SYS"
634 if !PSPP::value_is_missing ($val, $numericvar);
636 @c = $sf->get_next_case ();
638 die "Missing Value Positive Num"
639 if !PSPP::value_is_missing ($val, $numericvar);
641 AT_CHECK([run_perl_module test.pl])
644 AT_SETUP([Perl custom attributes])
645 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
646 PERL_GENERATE_SYSFILE
652 my $sf = PSPP::Reader->open ("sample.sav");
654 my $dict = $sf->get_dict ();
656 my $var = $dict->get_var_by_name ("numeric");
658 my $attr = $var->get_attributes ();
660 foreach my $k (sort (keys (%$attr)))
662 my $ll = $attr->{$k};
664 print map "$_\n", join ', ', @$ll;
667 AT_CHECK([run_perl_module test.pl], [0],
669 colour =>blue, pink, violet
670 nationality =>foreign
675 AT_SETUP([Perl Pspp.t])
677 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
678 # Skip this test if Perl's Text::Diff module is not installed.
679 AT_CHECK([perl -MText::Diff -e '' || exit 77])
680 AT_CHECK([run_perl_module "$abs_top_builddir/perl-module/t/Pspp.t"], [0],
683 ok 2 - Dictionary Creation
685 ok 4 - Trap illegal variable name
687 ok 6 - Accept legal variable name
689 ok 8 - Trap duplicate variable name
691 ok 10 - Accept valid format
693 ok 12 - Create sysfile object
694 ok 13 - Write system file
696 ok 15 - Appending Case with too many variables
698 ok 17 - Append Case 2
701 ok 20 - Dictionary Creation 2
702 ok 21 - Value label for short string
703 ok 22 - Value label for long string
704 ok 23 - Check output 2
705 ok 24 - Dictionary survives sysfile
706 ok 25 - Basic reader operation
707 ok 26 - Streaming of files
708 Formatted string is "11-SEP-2001 08:20"
709 ok 27 - format_value function
710 ok 28 - Perl representation of time
711 ok 29 - Returns undef on opening failure
712 ok 30 - Error string on open failure
713 ok 31 - Missing Value Negative String
714 ok 32 - Missing Value Negative Num
715 ok 33 - Missing Value Positive
716 ok 34 - Missing Value Positive SYS
717 ok 35 - Missing Value Positive Num
718 ok 36 - Custom Attributes