From b796525445274d651fb6c10a13f451d7e3524347 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 31 Aug 2018 23:03:08 +0200 Subject: [PATCH] More kernel tests --- tst/testinstall/coder.tst | 293 +++++++++++++++++++++++++++++++ tst/testinstall/integer.tst | 14 +- tst/testinstall/interpreter.tst | 120 +++++++++++-- tst/testinstall/kernel/exprs.tst | 38 ++++ tst/testinstall/kernel/read.tst | 5 + 5 files changed, 451 insertions(+), 19 deletions(-) create mode 100644 tst/testinstall/coder.tst diff --git a/tst/testinstall/coder.tst b/tst/testinstall/coder.tst new file mode 100644 index 00000000000..3bf20a4a20d --- /dev/null +++ b/tst/testinstall/coder.tst @@ -0,0 +1,293 @@ +# +# Tests for the GAP coder logic. +# +# For now this mostly focuses on testing edge cases and error +# handling in the coder. +# +# The files coder.tst and interpreter.tst closely mirror each other. +# +gap> START_TEST("coder.tst"); + +# +# function call with options +# +gap> f:=x->ValueOption("a");; +gap> ({}-> f(1) )(); +fail +gap> ({}-> f(1 : a) )(); +true +gap> ({}-> f(1 : ("a") ) )(); +true +gap> ({}-> f(1 : a := 23) )(); +23 +gap> ({}-> f(1 : ("a") := 23 ) )(); +23 + +# +# records +# +gap> function() +> local r; +> r := rec(a:=1); +> Display(r); +> r.a := 1; +> Display(r.a); +> Display(IsBound(r.a)); +> Unbind(r.a); +> return r; +> end(); +rec( + a := 1 ) +1 +true +rec( ) + +# +gap> function() +> local r; +> r := rec(a:=1); +> Display(r); +> r!.a := 1; +> Display(r!.a); +> Display(IsBound(r!.a)); +> Unbind(r!.a); +> return r; +> end(); +rec( + a := 1 ) +1 +true +rec( ) + +# +gap> function() +> local r; +> r := rec(("a"):=1); +> Display(r); +> r.("a") := 1; +> Display(r.("a")); +> Display(IsBound(r.("a"))); +> Unbind(r.("a")); +> return r; +> end(); +rec( + a := 1 ) +1 +true +rec( ) + +# +gap> function() +> local r; +> r := rec(("a"):=1); +> Display(r); +> r!.("a") := 1; +> Display(r!.("a")); +> Display(IsBound(r!.("a"))); +> Unbind(r!.("a")); +> return r; +> end(); +rec( + a := 1 ) +1 +true +rec( ) + +# +# component objects (atomic by default in HPC-GAP) +# +gap> r := Objectify(NewType(NewFamily("MockFamily"), IsComponentObjectRep), rec());; + +# +gap> function() +> r!.a := 1; +> Display(r!.a); +> Display(IsBound(r!.a)); +> Unbind(r!.a); +> Display(IsBound(r!.a)); +> end(); +1 +true +false + +# +gap> function() +> r!.("a") := 1; +> Display(r!.("a")); +> Display(IsBound(r!.("a"))); +> Unbind(r!.("a")); +> Display(IsBound(r!.("a"))); +> end(); +1 +true +false + +# +# lists +# +gap> function() +> local l; +> l:=[1,2,3]; +> Display(l); +> l[1] := 42; +> Display(l[1]); +> Display(IsBound(l[1])); +> Unbind(l[1]); +> Display(l); +> l{[1,3]} := [42, 23]; +> Display(l); +> Display(l{[3,1]}); +> end(); +[ 1, 2, 3 ] +42 +true +[ , 2, 3 ] +[ 42, 2, 23 ] +[ 23, 42 ] +gap> function() +> local l; +> l:=[1,2,3]; +> IsBound(l{[1,3]}); +> end; +Syntax error: statement expected in stream:4 + IsBound(l{[1,3]}); + ^^^^^^^ +gap> function() +> local l; +> l:=[1,2,3]; +> Unbind(l{[1,3]}); +> end; +Syntax error: Illegal operand for 'Unbind' in stream:4 + Unbind(l{[1,3]}); + ^ + +# +gap> f:=function() +> local l; +> l:=[1,2,3]; +> Display(l); +> l![1] := 42; +> Display(l![1]); +> Display(IsBound(l![1])); +> Unbind(l![1]); +> Display(l); +> end;; +gap> Display(f); +function ( ) + local l; + l := [ 1, 2, 3 ]; + Display( l ); + l![1] := 42; + Display( l![1] ); + Display( IsBound( l![1] ) ); + Unbind( l![1] ); + Display( l ); + return; +end +gap> f(); +[ 1, 2, 3 ] +42 +true +[ , 2, 3 ] + +# +gap> l := [1,2,3];; +gap> function() l![fail] := 42; end(); +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) +gap> function() return l![fail]; end(); +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> function() return IsBound(l![fail]); end(); +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> function() Unbind(l![fail]); end(); +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) + +# +# posobj +# +gap> l := Objectify(NewType(NewFamily("MockFamily"), IsPositionalObjectRep),[]);; + +# +gap> l![1] := 42; +42 +gap> l![1]; +42 +gap> IsBound(l![1]); +true +gap> Unbind(l![1]); +gap> IsBound(l![1]); +false + +# +gap> function() +> l![1] := 42; +> Display(l![1]); +> Display(IsBound(l![1])); +> Unbind(l![1]); +> Display(IsBound(l![1])); +> end(); +42 +true +false + +# +gap> function() l![fail] := 42; end(); +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) +gap> function() return l![fail]; end(); +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> function() return IsBound(l![fail]); end(); +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> function() Unbind(l![fail]); end(); +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) + +# +# atomic posobj (HPC-GAP) +# +gap> l := Objectify(NewType(NewFamily("MockFamily"), IsAtomicPositionalObjectRep),[23]);; + +# +gap> l![1] := 42; +42 +gap> l![1]; +42 +gap> IsBound(l![1]); +true +gap> Unbind(l![1]); +gap> IsBound(l![1]); +false + +# +gap> function() +> l![1] := 42; +> Display(l![1]); +> Display(IsBound(l![1])); +> Unbind(l![1]); +> Display(IsBound(l![1])); +> end(); +42 +true +false + +# +gap> function() l![fail] := 42; end(); +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) +gap> function() return l![fail]; end(); +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> function() return IsBound(l![fail]); end(); +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> function() Unbind(l![fail]); end(); +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) + +# +gap> STOP_TEST("coder.tst", 1); diff --git a/tst/testinstall/integer.tst b/tst/testinstall/integer.tst index 0dcb54b0411..d09b03134f6 100644 --- a/tst/testinstall/integer.tst +++ b/tst/testinstall/integer.tst @@ -39,16 +39,24 @@ gap> last = List([1..10], n->PrimeDivisors(-n)); true # -gap> n:=(2^31-1)*(2^61-1);; +gap> n:=(2^31-1)*(2^61-1);; # product of two "small" primes gap> PartialFactorization(n); [ 2147483647, 2305843009213693951 ] gap> FactorsInt(n); [ 2147483647, 2305843009213693951 ] -gap> PartialFactorization(2^155-19); +gap> n:=2^155-19;; # not a prime; GAP fails to fully factorize it, though FactInt finds all 4 factors +gap> PartialFactorization(n); [ 167, 273484587823896504154881143846609846492502347 ] -gap> n:=(2^2203-1)*(2^2281-1);; +gap> n:=(2^2203-1)*(2^2281-1);; # product of two "large" primes +gap> PartialFactorization(n) = [ n ]; +true +gap> n:=2^255-19;; # this is a "large" prime for which GAP only knows it is probably prime gap> PartialFactorization(n) = [ n ]; true +gap> FactorsInt(n) = [ n ]; +#I FactorsInt: used the following factor(s) which are probably primes: +#I 57896044618658097711785492504343953926634992332820282019728792003956564819949 +true # gap> Filtered([-4..20], IsPrimePowerInt); diff --git a/tst/testinstall/interpreter.tst b/tst/testinstall/interpreter.tst index c3becf85929..c85cae1bf21 100644 --- a/tst/testinstall/interpreter.tst +++ b/tst/testinstall/interpreter.tst @@ -4,6 +4,9 @@ # For now this mostly focuses on testing edge cases and error # handling in the interpreter. # +# The files coder.tst and interpreter.tst closely mirror each other. +# +gap> START_TEST("interpreter.tst"); # # non boolean expression as condition @@ -74,7 +77,7 @@ rec( ) # gap> r!.a := 1; 1 -gap> r!.("a"); +gap> r!.a; 1 gap> IsBound(r!.a); true @@ -105,7 +108,30 @@ gap> r; rec( ) # -# lists and posobj +# component objects (atomic by default in HPC-GAP) +# +gap> r := Objectify(NewType(NewFamily("MockFamily"), IsComponentObjectRep), rec());; + +# +gap> r!.a := 1; +1 +gap> r!.a; +1 +gap> IsBound(r!.a); +true +gap> Unbind(r!.a); + +# +gap> r!.("a") := 1; +1 +gap> r!.("a"); +1 +gap> IsBound(r!.("a")); +true +gap> Unbind(r!.("a")); + +# +# lists # gap> l:=[1,2,3]; [ 1, 2, 3 ] @@ -132,6 +158,20 @@ gap> Unbind(l![1]); gap> l; [ , 2, 3 ] +# +gap> l![fail] := 42; +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) +gap> l![fail]; +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> IsBound(l![fail]); +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> Unbind(l![fail]); +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) + # gap> l{[1,3]} := [42, 23]; [ 42, 23 ] @@ -149,17 +189,65 @@ gap> l; [ 42, 2, 23 ] # -gap> l!{[1,3]} := [42, 23]; -[ 42, 23 ] -gap> l!{[3,1]}; -[ 23, 42 ] -gap> IsBound(l!{[1,3]}); -Syntax error: Illegal operand for 'IsBound' in stream:1 -IsBound(l!{[1,3]}); - ^ -gap> Unbind(l!{[1,3]}); -Syntax error: Illegal operand for 'Unbind' in stream:1 -Unbind(l!{[1,3]}); - ^ -gap> l; -[ 42, 2, 23 ] +# posobj +# +gap> l := Objectify(NewType(NewFamily("MockFamily"), IsPositionalObjectRep),[]);; + +# +gap> l![1] := 42; +42 +gap> l![1]; +42 +gap> IsBound(l![1]); +true +gap> Unbind(l![1]); +gap> IsBound(l![1]); +false + +# +gap> l![fail] := 42; +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) +gap> l![fail]; +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> IsBound(l![fail]); +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> Unbind(l![fail]); +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) + +# +# atomic posobj (HPC-GAP) +# +gap> l := Objectify(NewType(NewFamily("MockFamily"), IsAtomicPositionalObjectRep),[23]);; + +# +gap> l![1] := 42; +42 +gap> l![1]; +42 +gap> IsBound(l![1]); +true +gap> Unbind(l![1]); +gap> IsBound(l![1]); +false + +# +gap> l![fail] := 42; +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) +gap> l![fail]; +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> IsBound(l![fail]); +Error, PosObj Element: must be a positive integer (not a boolean or\ + fail) +gap> Unbind(l![fail]); +Error, PosObj Assignment: must be a positive integer (not a boolean\ + or fail) + +# +# +gap> STOP_TEST("interpreter.tst", 1); diff --git a/tst/testinstall/kernel/exprs.tst b/tst/testinstall/kernel/exprs.tst index a80748ff94a..b13dd306051 100644 --- a/tst/testinstall/kernel/exprs.tst +++ b/tst/testinstall/kernel/exprs.tst @@ -26,5 +26,43 @@ Error, Permutation: cycles must be disjoint and duplicate-free gap> f(1,2,1,2); Error, Permutation: cycles must be disjoint and duplicate-free +# EvalRangeExpr +gap> f:={a,b,c} -> [a,b..c];; +gap> f(1,2,3); +[ 1 .. 3 ] +gap> f(1,3,5); +[ 1, 3 .. 5 ] +gap> f(1,1,1); +Error, Range: must not be equal to (1) +gap> f(1,3,4); +Error, Range: - (3) must be divisible by (2) + +# EvalRecExpr +gap> f:={a,b} -> rec( (a) := b );; +gap> f(1,2); +rec( 1 := 2 ) +gap> f(fail,2); +Error, Record: '.()' must be a string or an integer + +# PrintBinop +gap> Display(x-> (-2)^x); +function ( x ) + return (-2) ^ x; +end +gap> Display( x -> 2 * f( 3 + 4 )); +function ( x ) + return 2 * f( (3 + 4) ); +end + +# PrintTildeExpr, EvalTildeExpr +gap> l := [x -> ~];; +gap> f := l[1];; +gap> Display(f); +function ( x ) + return ~; +end +gap> f(1); +Error, '~' does not have a value here + # gap> STOP_TEST("kernel/exprs.tst", 1); diff --git a/tst/testinstall/kernel/read.tst b/tst/testinstall/kernel/read.tst index 089e076d5c0..3cdce2356bc 100644 --- a/tst/testinstall/kernel/read.tst +++ b/tst/testinstall/kernel/read.tst @@ -64,6 +64,11 @@ Syntax error: Identifier expected in stream:1 rec("a":=1); ^^^ +# +# ReadAtomic +# +gap> f := atomic function() end;; + # # ReadEvalCommand #