d0f8d73a648b9a2fd1c73d7af2fa39733f27fd33
[pspp] / tests / perl-module.at
1 dnl PSPP - a program for statistical analysis.
2 dnl Copyright (C) 2017 Free Software Foundation, Inc.
3 dnl 
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.
8 dnl 
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.
13 dnl 
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/>.
16 dnl AT_BANNER([Perl module tests])
17
18 dnl This command can be used to run with the PSPP Perl module after it has been
19 dnl built (with "make") but before it has been installed.  The -I options are
20 dnl equivalent to "use ExtUtils::testlib;" inside the Perl program, but it does
21 dnl not need to be run with the perl-module build directory as the current
22 dnl working directory.
23 dnl
24 dnl XXX "libtool --mode=execute" is probably better than setting
25 dnl LD_LIBRARY_PATH.
26 m4_define([RUN_PERL_MODULE],
27   [LD_LIBRARY_PATH=$abs_top_builddir/src/.libs \
28    DYLD_LIBRARY_PATH=$abs_top_builddir/src/.libs \
29    $PERL -I$abs_top_builddir/perl-module/blib/arch \
30          -I$abs_top_builddir/perl-module/blib/lib])
31
32 AT_SETUP([Perl create system file])
33 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
34 AT_DATA([test.pl],
35   [use warnings;
36    use strict;
37    use PSPP;
38
39    my $d = PSPP::Dict->new();
40    die "dictionary creation" if !ref $d;
41    die if $d->get_var_cnt () != 0;
42
43    $d->set_label ("My Dictionary");
44    $d->set_documents ("These Documents");
45
46    # Tests for variable creation
47
48    my $var0 = PSPP::Var->new ($d, "le");
49    die "trap illegal variable name" if ref $var0;
50    die if $d->get_var_cnt () != 0;
51
52    $var0 = PSPP::Var->new ($d, "legal");
53    die "accept legal variable name" if !ref $var0;
54    die if $d->get_var_cnt () != 1;
55
56    my $var1 = PSPP::Var->new ($d, "money", 
57                               (fmt=>PSPP::Fmt::DOLLAR,
58                                width=>4, decimals=>2) );
59    die "cappet valid format" if !ref $var1;
60    die if $d->get_var_cnt () != 2;
61
62    $d->set_weight ($var1);
63
64    my $sysfile = PSPP::Sysfile->new ('testfile.sav', $d);
65    die "create sysfile object" if !ref $sysfile;
66
67    $sysfile->close ();
68 ])
69 AT_CHECK([RUN_PERL_MODULE test.pl])
70 AT_DATA([dump-dict.sps],
71   [GET FILE='testfile.sav'.
72 DISPLAY FILE LABEL.
73 DISPLAY DOCUMENTS.
74 DISPLAY DICTIONARY.
75 SHOW WEIGHT.
76 ])
77 AT_CHECK([pspp -O format=csv dump-dict.sps], [0],
78   [File label: My Dictionary
79
80 Documents in the active dataset:
81
82 These Documents
83
84 Variable,Description,Position
85 legal,Format: F9.2,1
86 money,Format: DOLLAR6.2,2
87
88 dump-dict.sps:5: note: SHOW: WEIGHT is money.
89 ])
90 AT_CLEANUP
91
92 AT_SETUP([Perl writing cases to system files])
93 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
94 AT_DATA([test.pl],
95   [[use warnings;
96     use strict;
97     use PSPP;
98
99     my $d = PSPP::Dict->new();
100     PSPP::Var->new ($d, "id",
101                     (
102                      fmt=>PSPP::Fmt::F, 
103                      width=>2, 
104                      decimals=>0
105                      )
106                     );
107
108     PSPP::Var->new ($d, "name",
109                            (
110                             fmt=>PSPP::Fmt::A, 
111                             width=>20, 
112                             )
113                            );
114
115     $d->set_documents ("This should not appear");
116     $d->clear_documents ();
117     $d->add_document ("This is a document line");
118
119     $d->set_label ("This is the file label");
120
121     # Check that we can write cases to system files.
122     my $sysfile = PSPP::Sysfile->new ("testfile.sav", $d);
123     my $res = $sysfile->append_case ( [34, "frederick"]);
124     die "append case" if !$res;
125
126     $res = $sysfile->append_case ( [34, "frederick", "extra"]);
127     die "append case with too many variables" if $res;
128     $sysfile->close ();
129
130     # Check that sysfiles are closed properly automaticallly in the destructor.
131     my $sysfile2 = PSPP::Sysfile->new ("testfile2.sav", $d);
132     $res = $sysfile2->append_case ( [21, "wheelbarrow"]);
133     die "append case 2" if !$res;
134
135     $res = $sysfile->append_case ( [34, "frederick", "extra"]);
136     die "append case with too many variables" if $res;
137
138     # Don't close.  We want to test that the destructor does that.
139 ]])
140 AT_CHECK([RUN_PERL_MODULE test.pl])
141 AT_DATA([dump-dicts.sps],
142   [GET FILE='testfile.sav'.
143 DISPLAY DICTIONARY.
144 DISPLAY FILE LABEL.
145 DISPLAY DOCUMENTS.
146 LIST.
147
148 GET FILE='testfile2.sav'.
149 DISPLAY DICTIONARY.
150 DISPLAY FILE LABEL.
151 DISPLAY DOCUMENTS.
152 LIST.
153 ])
154 AT_CHECK([pspp -O format=csv dump-dicts.sps], [0],
155   [Variable,Description,Position
156 id,Format: F2.0,1
157 name,Format: A20,2
158
159 File label: This is the file label
160
161 Documents in the active dataset:
162
163 This is a document line
164
165 Table: Data List
166 id,name
167 34,frederick           @&t@
168
169 Variable,Description,Position
170 id,Format: F2.0,1
171 name,Format: A20,2
172
173 File label: This is the file label
174
175 Documents in the active dataset:
176
177 This is a document line
178
179 Table: Data List
180 id,name
181 21,wheelbarrow         @&t@
182 ])
183 AT_CLEANUP
184
185 AT_SETUP([Perl write variable parameters])
186 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
187 AT_DATA([test.pl],
188   [[use warnings;
189     use strict;
190     use PSPP;
191
192     my $dict = PSPP::Dict->new();
193     die "dictionary creation" if !ref $dict;
194
195     my $int = PSPP::Var->new ($dict, "integer", 
196                               (width=>8, decimals=>0) );
197
198     $int->set_label ("My Integer");
199
200     $int->add_value_label (99, "Silly");
201     $int->clear_value_labels ();
202     $int->add_value_label (0, "Zero");
203     $int->add_value_label (1, "Unity");
204     $int->add_value_label (2, "Duality");
205
206     my $str = PSPP::Var->new ($dict, "string", 
207                               (fmt=>PSPP::Fmt::A, width=>8) );
208
209
210     $str->set_label ("My String");
211     $str->add_value_label ("xx", "foo");
212     $str->add_value_label ("yy", "bar");
213
214     $str->set_missing_values ("this", "that");
215
216     my $longstr = PSPP::Var->new ($dict, "longstring", 
217                               (fmt=>PSPP::Fmt::A, width=>9) );
218
219
220     $longstr->set_label ("My Long String");
221     my $re = $longstr->add_value_label ("xxx", "xfoo");
222
223     $int->set_missing_values (9, 99);
224
225     my $sysfile = PSPP::Sysfile->new ("testfile.sav", $dict);
226
227
228     $sysfile->close ();
229 ]])
230 AT_CHECK([RUN_PERL_MODULE test.pl])
231 AT_DATA([dump-dict.sps],
232   [GET FILE='testfile.sav'.
233 DISPLAY DICTIONARY.
234 ])
235 AT_CHECK([pspp -O format=csv dump-dict.sps], [0],
236   [Variable,Description,Position
237 integer,"Label: My Integer
238 Format: F8.0
239 Missing Values: 9; 99
240
241 Value,Label
242 0,Zero
243 1,Unity
244 2,Duality",1
245 string,"Label: My String
246 Format: A8
247 Missing Values: ""this    ""; ""that    ""
248
249 Value,Label
250 xx      ,foo
251 yy      ,bar",2
252 longstring,"Label: My Long String
253 Format: A9
254
255 Value,Label
256 xxx      ,xfoo",3
257 ])
258 AT_CLEANUP
259
260 AT_SETUP([Perl dictionary survives system file])
261 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
262 AT_DATA([test.pl],
263   [[use warnings;
264 use strict;
265 use PSPP;
266
267 my $sysfile ;
268
269     {
270         my $d = PSPP::Dict->new();
271
272         PSPP::Var->new ($d, "id",
273                         (
274                          fmt=>PSPP::Fmt::F, 
275                          width=>2, 
276                          decimals=>0
277                          )
278                         );
279
280         $sysfile = PSPP::Sysfile->new ("testfile.sav", $d);
281     }
282
283     my $res = $sysfile->append_case ([3]);
284     print "Dictionary survives sysfile\n" if $res;
285 ]])
286 AT_CHECK([RUN_PERL_MODULE test.pl], [0],
287   [Dictionary survives sysfile
288 ])
289 AT_CLEANUP
290
291 m4_define([PERL_GENERATE_SYSFILE],
292   [AT_DATA([sample.sps],
293     [[data list notable list /string (a8) longstring (a12) numeric (f10) date (date11) dollar (dollar8.2) datetime (datetime17)
294 begin data.
295 1111 One   1 1/1/1 1   1/1/1+01:01
296 2222 Two   2 2/2/2 2   2/2/2+02:02
297 3333 Three 3 3/3/3 3   3/3/3+03:03
298 .    .     . .     .   .
299 5555 Five  5 5/5/5 5   5/5/5+05:05
300 end data.
301
302
303 variable labels string 'A Short String Variable'
304   /longstring 'A Long String Variable'
305   /numeric 'A Numeric Variable'
306   /date 'A Date Variable'
307   /dollar 'A Dollar Variable'
308   /datetime 'A Datetime Variable'.
309
310
311 missing values numeric (9, 5, 999).
312
313 missing values string ("3333").
314
315 add value labels
316   /string '1111' 'ones' '2222' 'twos' '3333' 'threes'
317   /numeric 1 'Unity' 2 'Duality' 3 'Thripality'.
318
319 variable attribute
320     variables = numeric
321     attribute=colour[1]('blue') colour[2]('pink') colour[3]('violet')
322     attribute=size('large') nationality('foreign').
323
324
325 save outfile='sample.sav'.
326 ]])
327    AT_CHECK([pspp -O format=csv sample.sps])])
328
329 AT_SETUP([Perl read system file])
330 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
331 PERL_GENERATE_SYSFILE
332 AT_DATA([test.pl],
333   [[use warnings;
334     use strict;
335     use PSPP;
336
337     my $sf = PSPP::Reader->open ("sample.sav");
338
339     my $dict = $sf->get_dict ();
340
341     for (my $v = 0 ; $v < $dict->get_var_cnt() ; $v++)
342     {
343        my $var = $dict->get_var ($v);
344        my $name = $var->get_name ();
345        my $label = $var->get_label ();
346
347        print "Variable $v is \"$name\", label is \"$label\"\n";
348
349        my $vl = $var->get_value_labels ();
350
351        print "Value Labels:\n";
352        print "$_ => $vl->{$_}\n" for sort (keys %$vl);
353     }
354
355     while (my @c = $sf->get_next_case () )
356     {
357        for (my $v = 0; $v < $dict->get_var_cnt(); $v++)
358        {
359            print "val$v: \"$c[$v]\"\n";
360        }
361        print "\n";
362     }
363 ]])
364 AT_CHECK([RUN_PERL_MODULE test.pl], [0],
365   [Variable 0 is "string", label is "A Short String Variable"
366 Value Labels:
367 1111     => ones
368 2222     => twos
369 3333     => threes
370 Variable 1 is "longstring", label is "A Long String Variable"
371 Value Labels:
372 Variable 2 is "numeric", label is "A Numeric Variable"
373 Value Labels:
374 1 => Unity
375 2 => Duality
376 3 => Thripality
377 Variable 3 is "date", label is "A Date Variable"
378 Value Labels:
379 Variable 4 is "dollar", label is "A Dollar Variable"
380 Value Labels:
381 Variable 5 is "datetime", label is "A Datetime Variable"
382 Value Labels:
383 val0: "1111    "
384 val1: "One         "
385 val2: "1"
386 val3: "13197686400"
387 val4: "1"
388 val5: "13197690060"
389
390 val0: "2222    "
391 val1: "Two         "
392 val2: "2"
393 val3: "13231987200"
394 val4: "2"
395 val5: "13231994520"
396
397 val0: "3333    "
398 val1: "Three       "
399 val2: "3"
400 val3: "13266028800"
401 val4: "3"
402 val5: "13266039780"
403
404 val0: ".       "
405 val1: ".           "
406 val2: ""
407 val3: ""
408 val4: ""
409 val5: ""
410
411 val0: "5555    "
412 val1: "Five        "
413 val2: "5"
414 val3: "13334630400"
415 val4: "5"
416 val5: "13334648700"
417
418 ])
419 AT_CLEANUP
420
421 AT_SETUP([Perl copying system files])
422 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
423 PERL_GENERATE_SYSFILE
424 AT_DATA([test.pl],
425   [[use warnings;
426     use strict;
427     use PSPP;
428
429     my $input = PSPP::Reader->open ("sample.sav");
430
431     my $dict = $input->get_dict ();
432
433     my $output = PSPP::Sysfile->new ("copy.sav", $dict);
434
435     while (my (@c) = $input->get_next_case () )
436     {
437       $output->append_case (\@c);
438     }
439
440     $output->close ();
441 ]])
442 AT_CHECK([RUN_PERL_MODULE test.pl])
443 AT_DATA([dump-dicts.sps],
444   [GET FILE='sample.sav'.
445 DISPLAY DICTIONARY.
446 LIST.
447
448 GET FILE='copy.sav'.
449 DISPLAY DICTIONARY.
450 LIST.
451 ])
452 AT_CHECK([pspp -O format=csv dump-dicts.sps], [0],
453   [[Variable,Description,Position
454 string,"Label: A Short String Variable
455 Format: A8
456 Missing Values: ""3333    ""
457
458 Value,Label
459 1111    ,ones
460 2222    ,twos
461 3333    ,threes",1
462 longstring,"Label: A Long String Variable
463 Format: A12",2
464 numeric,"Label: A Numeric Variable
465 Format: F10.0
466 Missing Values: 9; 5; 999
467
468 Value,Label
469 1,Unity
470 2,Duality
471 3,Thripality
472
473 Attribute,Value
474 colour[1],blue
475 colour[2],pink
476 colour[3],violet
477 nationality,foreign
478 size,large",3
479 date,"Label: A Date Variable
480 Format: DATE11",4
481 dollar,"Label: A Dollar Variable
482 Format: DOLLAR11.2",5
483 datetime,"Label: A Datetime Variable
484 Format: DATETIME17.0",6
485
486 Table: Data List
487 string,longstring,numeric,date,dollar,datetime
488 1111    ,One         ,1,01-JAN-2001,$1.00,01-JAN-2001 01:01
489 2222    ,Two         ,2,02-FEB-2002,$2.00,02-FEB-2002 02:02
490 3333    ,Three       ,3,03-MAR-2003,$3.00,03-MAR-2003 03:03
491 .       ,.           ,.,.,.  ,.
492 5555    ,Five        ,5,05-MAY-2005,$5.00,05-MAY-2005 05:05
493
494 Variable,Description,Position
495 string,"Label: A Short String Variable
496 Format: A8
497 Missing Values: ""3333    ""
498
499 Value,Label
500 1111    ,ones
501 2222    ,twos
502 3333    ,threes",1
503 longstring,"Label: A Long String Variable
504 Format: A12",2
505 numeric,"Label: A Numeric Variable
506 Format: F10.0
507 Missing Values: 9; 5; 999
508
509 Value,Label
510 1,Unity
511 2,Duality
512 3,Thripality
513
514 Attribute,Value
515 colour[1],blue
516 colour[2],pink
517 colour[3],violet
518 nationality,foreign
519 size,large",3
520 date,"Label: A Date Variable
521 Format: DATE11",4
522 dollar,"Label: A Dollar Variable
523 Format: DOLLAR11.2",5
524 datetime,"Label: A Datetime Variable
525 Format: DATETIME17.0",6
526
527 Table: Data List
528 string,longstring,numeric,date,dollar,datetime
529 1111    ,One         ,1,01-JAN-2001,$1.00,01-JAN-2001 01:01
530 2222    ,Two         ,2,02-FEB-2002,$2.00,02-FEB-2002 02:02
531 3333    ,Three       ,3,03-MAR-2003,$3.00,03-MAR-2003 03:03
532 .       ,.           ,.,.,.  ,.
533 5555    ,Five        ,5,05-MAY-2005,$5.00,05-MAY-2005 05:05
534 ]])
535 AT_CLEANUP
536
537 AT_SETUP([Perl value formatting])
538 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
539 AT_DATA([dd.sps],
540   [DATA LIST LIST /d (DATETIME17).
541 BEGIN DATA.
542 11/9/2001+08:20
543 END DATA.
544
545 SAVE OUTFILE='dd.sav'.
546 ])
547 AT_CHECK([pspp -O format=csv dd.sps], [0],
548   [Table: Reading free-form data from INLINE.
549 Variable,Format
550 d,DATETIME17.0
551 ])
552 AT_DATA([test.pl],
553   [[use warnings;
554     use strict;
555     use PSPP;
556
557     my $sf = PSPP::Reader->open ("dd.sav");
558
559     my $dict = $sf->get_dict ();
560
561     my (@c) = $sf->get_next_case ();
562
563     my $var = $dict->get_var (0);
564     my $val = $c[0];
565     my $formatted = PSPP::format_value ($val, $var);
566     my $str = gmtime ($val - PSPP::PERL_EPOCH);
567     print "Formatted string is \"$formatted\"\n";
568     print "Perl representation is \"$str\"\n";
569 ]])
570 AT_CHECK([RUN_PERL_MODULE test.pl], [0],
571   [[Formatted string is "11-SEP-2001 08:20"
572 Perl representation is "Tue Sep 11 08:20:00 2001"
573 ]])
574 AT_CLEANUP
575
576 AT_SETUP([Perl opening nonexistent file])
577 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
578 AT_DATA([test.pl],
579   [[use warnings;
580     use strict;
581     use PSPP;
582
583     my $sf = PSPP::Reader->open ("no-such-file.sav");
584
585     die "Returns undef on opening failure" if ref $sf;
586     print $PSPP::errstr, "\n";
587 ]])
588 AT_CHECK([RUN_PERL_MODULE test.pl], [0],
589   [[An error occurred while opening `no-such-file.sav': No such file or directory.
590 ]],
591   [[Name "PSPP::errstr" used only once: possible typo at test.pl line 8.
592 ]])
593 AT_CLEANUP
594
595 AT_SETUP([Perl missing values])
596 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
597 PERL_GENERATE_SYSFILE
598 AT_DATA([test.pl],
599   [[use warnings;
600     use strict;
601     use PSPP;
602
603     my $sf = PSPP::Reader->open ("sample.sav");
604
605     my $dict = $sf->get_dict ();
606
607     my (@c) = $sf->get_next_case ();
608
609     my $stringvar = $dict->get_var (0);
610     my $numericvar = $dict->get_var (2);
611     my $val = $c[0];
612
613     die "Missing Value Negative String"
614         if PSPP::value_is_missing ($val, $stringvar);
615
616     $val = $c[2];
617
618     die "Missing Value Negative Num"
619         if PSPP::value_is_missing ($val, $numericvar);
620
621     @c = $sf->get_next_case (); 
622     @c = $sf->get_next_case (); 
623
624     $val = $c[0];
625     die "Missing Value Positive"
626         if !PSPP::value_is_missing ($val, $stringvar);
627
628     @c = $sf->get_next_case (); 
629     $val = $c[2];
630     die "Missing Value Positive SYS"
631         if !PSPP::value_is_missing ($val, $numericvar);
632
633     @c = $sf->get_next_case (); 
634     $val = $c[2];
635     die "Missing Value Positive Num"
636         if !PSPP::value_is_missing ($val, $numericvar);
637 ]])
638 AT_CHECK([RUN_PERL_MODULE test.pl])
639 AT_CLEANUP
640
641 AT_SETUP([Perl custom attributes])
642 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
643 PERL_GENERATE_SYSFILE
644 AT_DATA([test.pl],
645   [[use warnings;
646     use strict;
647     use PSPP;
648
649     my $sf = PSPP::Reader->open ("sample.sav");
650
651     my $dict = $sf->get_dict ();
652
653     my $var = $dict->get_var_by_name ("numeric");
654
655     my $attr = $var->get_attributes ();
656
657     foreach my $k (sort (keys (%$attr)))
658     {
659         my $ll = $attr->{$k};
660         print "$k =>";
661         print map "$_\n", join ', ', @$ll;
662     }
663 ]])
664 AT_CHECK([RUN_PERL_MODULE test.pl], [0],
665   [[$@Role =>0
666 colour =>blue, pink, violet
667 nationality =>foreign
668 size =>large
669 ]])
670 AT_CLEANUP
671
672 AT_SETUP([Perl Pspp.t])
673 AT_SKIP_IF([test "$WITH_PERL_MODULE" = no])
674 # Skip this test if Perl's Text::Diff module is not installed.
675 AT_CHECK([perl -MText::Diff -e '' || exit 77])
676 AT_CHECK([RUN_PERL_MODULE $abs_top_builddir/perl-module/t/Pspp.t], [0],
677   [[1..37
678 ok 1 - use PSPP;
679 ok 2 - Dictionary Creation
680 ok 3
681 ok 4 - Trap illegal variable name
682 ok 5
683 ok 6 - Accept legal variable name
684 ok 7
685 ok 8 - Trap duplicate variable name
686 ok 9
687 ok 10 - Accept valid format
688 ok 11
689 ok 12 - Create sysfile object
690 ok 13 - Write system file
691 ok 14 - Append Case
692 ok 15 - Appending Case with too many variables
693 ok 16 - existance
694 ok 17 - Append Case 2
695 ok 18 - existance2
696 ok 19 - Check output
697 ok 20 - Dictionary Creation 2
698 ok 21 - Value label for short string
699 ok 22 - Value label for long string
700 ok 23 - Check output 2
701 ok 24 - Dictionary survives sysfile
702 ok 25 - Basic reader operation
703 ok 26 - Streaming of files
704 Formatted string is "11-SEP-2001 08:20"
705 ok 27 - format_value function
706 ok 28 - Perl representation of time
707 ok 29 - Returns undef on opening failure
708 ok 30 - Error string on open failure
709 ok 31 - Missing Value Negative String
710 ok 32 - Missing Value Negative Num
711 ok 33 - Missing Value Positive
712 ok 34 - Missing Value Positive SYS
713 ok 35 - Missing Value Positive Num
714 ok 36 - Custom Attributes
715 ok 37 - Case count
716 ]],[ignore])
717 AT_CLEANUP