+dnl PSPP - a program for statistical analysis.
+dnl Copyright (C) 2017 Free Software Foundation, Inc.
+dnl
+dnl This program is free software: you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation, either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
+dnl
AT_BANNER([SORT CASES])
m4_divert_push([PREPARE_TESTS])
[sort_cases_gen_data () {
- cat > gen-data.pl <<'EOF'
-use strict;
-use warnings;
-
-# Generate shuffled data.
-my (@data);
-for my $i (0...$ARGV[0] - 1) {
- push (@data, ($i) x $ARGV[1]);
-}
-fisher_yates_shuffle (\@data);
-
-# Output shuffled data.
-my (@shuffled) = map ([$data[$_], $_], 0...$#data);
-open (SHUFFLED, ">data.txt");
-print SHUFFLED "$data[$_] $_\n" foreach 0...$#data;
-
-# Output sorted data.
-my (@sorted) = sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @shuffled;
-open (SORTED, ">expout");
-printf SORTED " %8d %8d \n", $_->[0], $_->[1] foreach @sorted;
-
-# From perlfaq4.
-sub fisher_yates_shuffle {
- my $deck = shift; # $deck is a reference to an array
- my $i = @$deck;
- while ($i--) {
- my $j = int rand ($i+1);
- @$deck[$i,$j] = @$deck[$j,$i];
- }
-}
+ cat > gen-data.py <<'EOF'
+#! /usr/bin/python3
+
+import random
+import sys
+
+data = []
+for i in range(int(sys.argv[1])):
+ data += [i] * int(sys.argv[2])
+random.shuffle(data)
+
+data_txt = open('data.txt', 'w')
+for i, item in enumerate(data):
+ data_txt.write('%s %s\n' % (item, i))
+data_txt.close()
+
+shuffled = ((item, i) for i, item in enumerate(data))
+expout = open('expout', 'w')
+for item, i in sorted(shuffled):
+ expout.write(' %8d %8d \n' % (item, i))
+expout.close()
EOF
- $PERL gen-data.pl "$@"]
+ $PYTHON3 gen-data.py "$@"]
}
m4_divert_pop([PREPARE_TESTS])
-m4_define([SORT_CASES_TEST],
+m4_define([SORT_CASES_TEST],
[AT_SETUP([sort m4_eval([$1 * $2]) cases[]m4_if([$2], [1], [], [ ($1 unique)])[]m4_if([$3], [], [], [ with $3 buffers])])
- AT_KEYWORDS([SORT CASES])
+ AT_KEYWORDS([SORT CASES $4])
AT_CHECK([sort_cases_gen_data $1 $2 $3])
AT_CAPTURE_FILE([data.txt])
AT_CAPTURE_FILE([output.txt])
AT_CAPTURE_FILE([sort-cases.sps])
AT_DATA([sort-cases.sps], [dnl
DATA LIST LIST NOTABLE FILE='data.txt'/x y (F8).
-SORT BY x[]m4_if([$3], [], [], [/BUFFERS=$3]).
+SORT CASES BY x[]m4_if([$3], [], [], [/BUFFERS=$3]).
PRINT OUTFILE='output.txt'/x y.
EXECUTE.
])
SORT_CASES_TEST(100, 10, 5)
SORT_CASES_TEST(100, 10)
-SORT_CASES_TEST(1000, 5, 5)
-SORT_CASES_TEST(1000, 5, 50)
-SORT_CASES_TEST(1000, 5)
+SORT_CASES_TEST(1000, 5, 5, slow)
+SORT_CASES_TEST(1000, 5, 50, slow)
+SORT_CASES_TEST(1000, 5, [], slow)
+
+SORT_CASES_TEST(100, 100, 3, slow)
+SORT_CASES_TEST(100, 100, 5, slow)
+SORT_CASES_TEST(100, 100, [], slow)
+
+SORT_CASES_TEST(10000, 5, 500, slow)
-SORT_CASES_TEST(100, 100, 3)
-SORT_CASES_TEST(100, 100, 5)
-SORT_CASES_TEST(100, 100)
+SORT_CASES_TEST(50000, 1, [], slow)
+
+dnl Bug #33089 caused SORT CASES to delete filtered cases permanently.
+AT_SETUP([SORT CASES preserves filtered cases])
+AT_DATA([sort-cases.sps], [dnl
+DATA LIST FREE /x.
+BEGIN DATA.
+5 4 3 2 1 0
+END DATA.
+COMPUTE mod2 = MOD(x, 2).
+LIST.
+FILTER BY mod2.
+LIST.
+SORT CASES BY x.
+LIST.
+FILTER OFF.
+LIST.
+])
+AT_CHECK([pspp -O format=csv sort-cases.sps], [0], [dnl
+Table: Data List
+x,mod2
+5.00,1.00
+4.00,.00
+3.00,1.00
+2.00,.00
+1.00,1.00
+.00,.00
-SORT_CASES_TEST(10000, 5, 500)
+Table: Data List
+x,mod2
+5.00,1.00
+3.00,1.00
+1.00,1.00
-SORT_CASES_TEST(50000, 1)
+Table: Data List
+x,mod2
+1.00,1.00
+3.00,1.00
+5.00,1.00
+Table: Data List
+x,mod2
+.00,.00
+1.00,1.00
+2.00,.00
+3.00,1.00
+4.00,.00
+5.00,1.00
+])
+AT_CLEANUP
+
+AT_SETUP([SORT CASES syntax errors])
+AT_DATA([sort-cases.sps], [dnl
+DATA LIST LIST NOTABLE/x y z.
+SORT CASES BY **.
+SORT CASES BY x(**).
+SORT CASES BY x(D**).
+SORT CASES BY x(A) x(D) y(**).
+])
+AT_DATA([insert.sps], [dnl
+INSERT FILE='sort-cases.sps' ERROR=IGNORE.
+])
+AT_CHECK([pspp --testing-mode -O format=csv insert.sps], [1], [dnl
+"sort-cases.sps:2.15-2.16: error: SORT CASES: Syntax error expecting variable name.
+ 2 | SORT CASES BY **.
+ | ^~"
+
+"sort-cases.sps:3.17-3.18: error: SORT CASES: Syntax error expecting A or D.
+ 3 | SORT CASES BY x(**).
+ | ^~"
+
+"sort-cases.sps:4.18-4.19: error: SORT CASES: Syntax error expecting `)'.
+ 4 | SORT CASES BY x(D**).
+ | ^~"
+
+"sort-cases.sps:5.15-5.23: warning: SORT CASES: Variable x specified twice in sort criteria.
+ 5 | SORT CASES BY x(A) x(D) y(**).
+ | ^~~~~~~~~"
+
+"sort-cases.sps:5.27-5.28: error: SORT CASES: Syntax error expecting A or D.
+ 5 | SORT CASES BY x(A) x(D) y(**).
+ | ^~"
+])
+AT_CLEANUP
\ No newline at end of file