+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/>.
m4_define([CHECK_EXPR_EVAL],
[AT_SETUP([expressions - $1])
+ AT_KEYWORDS([expression])
AT_DATA([evaluate.sps],
[set mxwarn 1000.
set mxerr 1000.
])])
AT_CAPTURE_FILE([evaluate.sps])
m4_pushdef([i], [3])
- AT_CHECK([pspp --testing-mode --error-file=- --no-output evaluate.sps],
- [m4_if(m4_bregexp([m4_foreach([check], [m4_shift($@)], [m4_argn(3, check)])], [error:]), [-1], [0], [1])],
+ AT_CHECK([pspp --testing-mode -O format=csv evaluate.sps],
+ [m4_if(m4_bregexp([m4_foreach([check], [m4_shift($@)], [m4_argn(3, check)])], [error:]), [-1], [0], [1])],
[stdout])
- # Use sed to transform "file:line.column:" into plain "file:line:",
- # because column numbers change between opt and noopt versions.
- AT_CHECK([[sed 's/\(evaluate.sps:[0-9]\{1,\}\)\.[0-9]\{1,\}:/\1:/' stdout]],
- [0],
- [m4_foreach([check], [m4_shift($@)],
+ AT_DATA([expout], [m4_foreach([check], [m4_shift($@)],
[m4_define([i], m4_incr(i))dnl
m4_if(m4_argn(3, check), [], [], [evaluate.sps:[]i[]: m4_argn(3, check)
])dnl
m4_if(m4_argn(3, check), [], [], [evaluate.sps:[]i[]: m4_argn(3, check)
])dnl
m4_argn(2, check)
-])], [])
+])])
+ AT_CHECK([[sed '
+# Transform "file:line.column:" into plain "file:line:",
+# because column numbers change between opt and noopt versions.
+s/\(evaluate.sps:[0-9]\{1,\}\)\.[0-9]\{1,\}:/\1:/
+
+# Remove leading or trailing quotes and un-double CSV quotes.
+s/^"//
+s/"$//
+s/""/"/g
+# "
+
+# Delete blank lines
+/^$/d' stdout]],
+ [0], [expout], [])
m4_popdef([i])
AT_CLEANUP])
[[trunc(1.9)], [1.00]],
[[trunc(-1.2)], [-1.00]],
[[trunc(-1.9)], [-1.00]],
+ [[trunc(5.06, .1)], [5.00]],
+ [[trunc(-5.06, .1)], [-5.00]],
+ [[trunc(1)], [1.00]],
+ [[trunc(1 - 2**-53)], [1.00]],
+ [[trunc(1 - 2**-52)], [1.00]],
+ [[trunc(1 - 2**-51)], [1.00]],
+ [[trunc(1 - 2**-45)], [0.00]],
+ [[trunc(1 - 2**-45, 1, 10)], [1.00]],
[[trunc('x')], [error],
- [error: DEBUG EVALUATE: Type mismatch invoking TRUNC(number) as trunc(string).]])
+ [error: DEBUG EVALUATE: Function invocation trunc(string) does not match any known function. Candidates are:
+TRUNC(number)
+TRUNC(number, number)
+TRUNC(number, number, number).]])
CHECK_EXPR_EVAL([acos arsin artan cos sin tan],
[[acos(.5) / 3.14159 * 180], [60.00]],
RANGE(number, number, number[, number, number]...)
RANGE(string, string, string[, string, string]...).]],
[[range(1, 2)], [error],
- [error: DEBUG EVALUATE: RANGE(number, number, number[, number, number]...) must have an even number of arguments in list.]],
+ [error: DEBUG EVALUATE: RANGE(number, number, number[, number, number]...) must have an odd number of arguments.]],
[[range(1, 2, 3, 4)], [error],
- [error: DEBUG EVALUATE: RANGE(number, number, number[, number, number]...) must have an even number of arguments in list.]],
+ [error: DEBUG EVALUATE: RANGE(number, number, number[, number, number]...) must have an odd number of arguments.]],
[[range(1, 2, 3, 4, 5, 6)], [error],
- [error: DEBUG EVALUATE: RANGE(number, number, number[, number, number]...) must have an even number of arguments in list.]],
+ [error: DEBUG EVALUATE: RANGE(number, number, number[, number, number]...) must have an odd number of arguments.]],
[[range('1', 2, 3)], [error],
[error: DEBUG EVALUATE: Function invocation range(string, number, number) does not match any known function. Candidates are:
RANGE(number, number, number[, number, number]...)
RANGE(number, number, number[, number, number]...)
RANGE(string, string, string[, string, string]...).]],
[[range('1', '2')], [error],
- [error: DEBUG EVALUATE: RANGE(string, string, string[, string, string]...) must have an even number of arguments in list.]],
+ [error: DEBUG EVALUATE: RANGE(string, string, string[, string, string]...) must have an odd number of arguments.]],
[[range('1', '2', '3', '4')], [error],
- [error: DEBUG EVALUATE: RANGE(string, string, string[, string, string]...) must have an even number of arguments in list.]],
+ [error: DEBUG EVALUATE: RANGE(string, string, string[, string, string]...) must have an odd number of arguments.]],
[[range('1', '2', '3', '4', '5', '6')], [error],
- [error: DEBUG EVALUATE: RANGE(string, string, string[, string, string]...) must have an even number of arguments in list.]],
+ [error: DEBUG EVALUATE: RANGE(string, string, string[, string, string]...) must have an odd number of arguments.]],
[[range(1, '2', '3')], [error],
[error: DEBUG EVALUATE: Function invocation range(number, string, string) does not match any known function. Candidates are:
RANGE(number, number, number[, number, number]...)
[[max(1, 2, 3, $sysmis)], [3.00]],
[[max.4(1, 2, 3, $sysmis)], [sysmis]],
[[max.4(1, 2, 3)], [error],
- [error: DEBUG EVALUATE: With MAX(number[, number]...), using minimum valid argument count of 4 does not make sense when passing only 3 arguments in list.]],
+ [error: DEBUG EVALUATE: For MAX(number[, number]...) with 3 arguments, at most 3 (not 4) may be required to be valid.]],
[[max("2", "3", "5", "1", "4")], ["5"]],
[[max("1", "2")], ["2"]],
[[min(1, 2, 3, $sysmis)], [1.00]],
[[min.4(1, 2, 3, $sysmis)], [sysmis]],
[[min.4(1, 2, 3)], [error],
- [error: DEBUG EVALUATE: With MIN(number[, number]...), using minimum valid argument count of 4 does not make sense when passing only 3 arguments in list.]],
+ [error: DEBUG EVALUATE: For MIN(number[, number]...) with 3 arguments, at most 3 (not 4) may be required to be valid.]],
[[min("2", "3", "5", "1", "4")], ["1"]],
[[min("1", "2")], ["1"]],
[[min("1")], ["1"]])
-CHECK_EXPR_EVAL([cfvar mean sd sum variance],
+CHECK_EXPR_EVAL([cfvar mean median sd sum variance],
[[cfvar(1, 2, 3, 4, 5)], [0.53]],
[[cfvar(1, $sysmis, 2, 3, $sysmis, 4, 5)], [0.53]],
[[cfvar(1, 2)], [0.47]],
[[cfvar(1, 2, 3, $sysmis)], [0.50]],
[[cfvar.4(1, 2, 3, $sysmis)], [sysmis]],
[[cfvar.4(1, 2, 3)], [error],
- [error: DEBUG EVALUATE: With CFVAR(number, number[, number]...), using minimum valid argument count of 4 does not make sense when passing only 3 arguments in list.]],
+ [error: DEBUG EVALUATE: For CFVAR(number, number[, number]...) with 3 arguments, at most 3 (not 4) may be required to be valid.]],
[[cfvar('x')], [error],
[error: DEBUG EVALUATE: Type mismatch invoking CFVAR(number, number[, number]...) as cfvar(string).]],
[[cfvar('x', 1, 2, 3)], [error],
[[mean(1, 2, 3, $sysmis)], [2.00]],
[[mean.4(1, 2, 3, $sysmis)], [sysmis]],
[[mean.4(1, 2, 3)], [error],
- [error: DEBUG EVALUATE: With MEAN(number[, number]...), using minimum valid argument count of 4 does not make sense when passing only 3 arguments in list.]],
-
+ [error: DEBUG EVALUATE: For MEAN(number[, number]...) with 3 arguments, at most 3 (not 4) may be required to be valid.]],
+
+ [[median(1, 2, 3, 4, 5)], [3.00]],
+ [[median(2, 3, 4, 5, 1)], [3.00]],
+ [[median(2, 3, 4, 1, 5)], [3.00]],
+ [[median(2, 1, 4, 5, 3)], [3.00]],
+ [[median(1, 2, 3, 4)], [2.50]],
+ [[median(2, 3, 1, 4)], [2.50]],
+ [[median(2, 3, 4, 1)], [2.50]],
+ [[median(2, 1, 4, 3)], [2.50]],
+ [[median(1, $sysmis, 3, 4, 5)], [3.50]],
+ [[median(2, 3, 4, 5, $sysmis, 1)], [3.00]],
+ [[median($sysmis, $sysmis, $sysmis, 2, 3, 4, 1, 5)], [3.00]],
+ [[median(1, 2, 3)], [2.00]],
+ [[median(1)], [1.00]],
+ [[median(1, 2)], [1.50]],
+ [[median(1, 2, $sysmis)], [1.50]],
+ [[median(1, $sysmis, $sysmis)], [1.00]],
+ [[median($sysmis, $sysmis, $sysmis)], [sysmis]],
+ [[median.3(1, 2, $sysmis)], [sysmis]],
+ [[median.2(1, $sysmis)], [sysmis]],
[[sd(1, 2, 3, 4, 5)], [1.58]],
[[sd(1, $sysmis, 2, 3, $sysmis, 4, 5)], [1.58]],
[[sd(1, 2, 3, $sysmis)], [1.00]],
[[sd.4(1, 2, 3, $sysmis)], [sysmis]],
[[sd.4(1, 2, 3)], [error],
- [error: DEBUG EVALUATE: With SD(number, number[, number]...), using minimum valid argument count of 4 does not make sense when passing only 3 arguments in list.]],
+ [error: DEBUG EVALUATE: For SD(number, number[, number]...) with 3 arguments, at most 3 (not 4) may be required to be valid.]],
[[sd('x')], [error],
[error: DEBUG EVALUATE: Type mismatch invoking SD(number, number[, number]...) as sd(string).]],
[[sd('x', 1, 2, 3)], [error],
[[sum(1, 2, 3, $sysmis)], [6.00]],
[[sum.4(1, 2, 3, $sysmis)], [sysmis]],
[[sum.4(1, 2, 3)], [error],
- [error: DEBUG EVALUATE: With SUM(number[, number]...), using minimum valid argument count of 4 does not make sense when passing only 3 arguments in list.]],
+ [error: DEBUG EVALUATE: For SUM(number[, number]...) with 3 arguments, at most 3 (not 4) may be required to be valid.]],
[[variance(1, 2, 3, 4, 5)], [2.50]],
[[variance(1, $sysmis, 2, 3, $sysmis, 4, 5)], [2.50]],
[[variance(1, 2, 3, $sysmis)], [1.00]],
[[variance.4(1, 2, 3, $sysmis)], [sysmis]],
[[variance.4(1, 2, 3)], [error],
- [error: DEBUG EVALUATE: With VARIANCE(number, number[, number]...), using minimum valid argument count of 4 does not make sense when passing only 3 arguments in list.]],
+ [error: DEBUG EVALUATE: For VARIANCE(number, number[, number]...) with 3 arguments, at most 3 (not 4) may be required to be valid.]],
[[variance('x')], [error],
[error: DEBUG EVALUATE: Type mismatch invoking VARIANCE(number, number[, number]...) as variance(string).]],
[[variance('x', 1, 2, 3)], [error],
[[lower(1)], [error],
[error: DEBUG EVALUATE: Type mismatch invoking LOWER(string) as lower(number).]])
-CHECK_EXPR_EVAL([lpad number ltrim lpad rtrim rpad string substr upcase],
+CHECK_EXPR_EVAL([replace],
+ [[replace('banana', 'an', 'AN')], ["bANANa"]],
+ [[replace('banana', 'an', 'a')], ["baaa"]],
+ [[replace('banana', 'an', '')], ["ba"]],
+ [[replace('banana', 'na', '')], ["ba"]],
+ [[replace('banana', 'ba', 'BA')], ["BAnana"]],
+ [[replace('banana', 'na', 'xyzzy')], ["baxyzzyxyzzy"]],
+ [[replace('banana', 'an', 'xyzzy', 1)], ["bxyzzyana"]],
+ [[replace('banana', 'an', 'xyzzy', 1.5)], ["bxyzzyana"]],
+ [[replace('banana', 'bananana', 'xyzzy')], ["banana"]],
+ [[replace('banana', '', 'xyzzy')], ["banana"]],
+ [[replace('banana', 'ba', '', 0)], ["banana"]],
+ [[replace('banana', 'ba', '', -1)], ["banana"]],
+ [[replace('banana', 'ba', '', $sysmis)], ["banana"]])
+
+CHECK_EXPR_EVAL([lpad number ltrim lpad rtrim rpad string strunc substr upcase],
[[lpad('abc', -1)], [""]],
[[lpad('abc', 0)], ["abc"]],
[[lpad('abc', 2)], ["abc"]],
[error: DEBUG EVALUATE: Type mismatch invoking STRING(number, num_output_format) as string(number, format).]],
[[string(123, e6.0)], ["1E+002"]],
+ [[strunc('a c ', 9)], ["a c"]],
+ [[strunc('a c ', 7)], ["a c"]],
+ [[strunc('a c ', 6)], ["a c"]],
+ [[strunc('a c ', 5)], ["a c"]],
+ [[strunc('a c ', 4)], ["a c"]],
+ [[strunc('a c ', 3)], ["a c"]],
+ [[strunc('a c ', 2)], ["a"]],
+ [[strunc('a c ', 1)], ["a"]],
+ [[strunc('a c ', 0)], [""]],
+ [[strunc('a c ', -1)], [""]],
+ [[strunc('a c ', $sysmis)], [""]],
+ [[strunc(' abc ', 9)], [" abc"]],
+ [[strunc(' abc ', 8)], [" abc"]],
+ [[strunc(' abc ', 7)], [" abc"]],
+ [[strunc(' abc ', 6)], [" abc"]],
+ [[strunc(' abc ', 5)], [" abc"]],
+ [[strunc(' abc ', 4)], [" ab"]],
+ [[strunc(' abc ', 3)], [" a"]],
+ [[strunc(' abc ', 2)], [""]],
+ [[strunc(' abc ', 1)], [""]],
+ [[strunc(' abc ', -1)], [""]],
+ [[strunc(' abc ', $sysmis)], [""]],
+
[[substr('abcdefgh', -5)], [""]],
[[substr('abcdefgh', 0)], [""]],
[[substr('abcdefgh', 1)], ["abcdefgh"]],
[[x ** 1], [5.00], [], [(X = 5.00)]],
[[x ** 2], [25.00], [], [(X = 5.00)]])
+CHECK_EXPR_EVAL([negative checks],
+ [[$nonexistent], [error], [error: DEBUG EVALUATE: Unknown system variable $nonexistent.]],
+ [[RANGE(1, 2)], [error], [error: DEBUG EVALUATE: RANGE(number, number, number[, number, number]...) must have an odd number of arguments.]],
+ [[CONCAT.1('a', 'b')], [error], [error: DEBUG EVALUATE: CONCAT(string[, string]...) function cannot accept suffix .1 to specify the minimum number of valid arguments.]],
+ [[foobar(x)], [error], [error: DEBUG EVALUATE: No function or vector named foobar.]],
+ [[CONCAT.1('a' b)], [error], [error: DEBUG EVALUATE: Syntax error at `b': expecting `,' or `)'.]],
+ [[NCDF.CHISQ(1, 2, 3)], [error], [error: DEBUG EVALUATE: NCDF.CHISQ(number, number, number) is not available in this version of PSPP.]])
+
AT_SETUP([LAG function])
AT_DATA([lag.sps], [dnl
data list /W 1.
AT_CHECK([cat pspp.csv], [0], [dnl
Table: Reading 1 record from INLINE.
Variable,Record,Columns,Format
-W,1,1- 1,F1.0
+W,1,1-1,F1.0
Table: Data List
W,X,Y,Z
AT_DATA([lag.sps], [dnl
DATA LIST LIST /x.
BEGIN DATA
-1
-2
+1
+2
END DATA.
DO IF (x <> LAG(x) ).
n,s,nlabel,slabel
.,,,
0,a,Very dissa,Wouldn't b
-1,b,Dissatisfi,Unhappy @&t@
-2,c,Neutral ,Bored @&t@
-3,d,Satisfied ,Satiated @&t@
-4,e,Very satis,Elated @&t@
+1,b,Dissatisfi,Unhappy
+2,c,Neutral,Bored
+3,d,Satisfied,Satiated
+4,e,Very satis,Elated
5,f,,
6,g,,
])
MISSING VALUES N1 TO N5 (3 THRU 5, 1).
BEGIN DATA.
12345
-6789
+6789
END DATA.
COMPUTE P1=N1.
MISSING VALUES N1 TO N5 (3 THRU 5, 1).
BEGIN DATA.
12345
-6789
+6789
END DATA.
VECTOR N=N1 TO N5.