Add more language tests

Added tests for the conditional operator, operator precedence,
modules ("module" and "export" keywords, and the "::" operator), and
for the "copy" keyword.

Also improved tests of max/min values of int, count, and double constants.
This commit is contained in:
Daniel Thayer 2012-08-29 17:14:03 -05:00
parent 90281a2423
commit 621a90d248
14 changed files with 312 additions and 9 deletions

View file

@ -0,0 +1,7 @@
true condition (PASS)
false condition (PASS)
true condition (PASS)
false condition (PASS)
associativity (PASS)
associativity (PASS)
associativity (PASS)

View file

@ -0,0 +1,2 @@
direct assignment (PASS)
using copy (PASS)

View file

@ -14,3 +14,4 @@ division operator (PASS)
assignment operator (PASS)
assignment operator (PASS)
max count value = 4294967295 (PASS)
max count value = 9223372036854775807 (PASS)

View file

@ -22,4 +22,4 @@ relational operator (PASS)
relational operator (PASS)
relational operator (PASS)
division operator (PASS)
max double value = 1.7e+308 (PASS)
max double value = 1.7976931348623157e+308 (PASS)

View file

@ -18,4 +18,6 @@ assignment operator (PASS)
assignment operator (PASS)
max int value = 4294967295 (PASS)
min int value = -4294967295 (PASS)
max int value = 9223372036854775807 (PASS)
min int value = -9223372036854775807 (PASS)
type inference (PASS)

View file

@ -0,0 +1,4 @@
function (PASS)
global variable (PASS)
const (PASS)
event (PASS)

View file

@ -0,0 +1,31 @@
++ and * (PASS)
++ and * (PASS)
* and ++ (PASS)
* and % (PASS)
* and % (PASS)
* and % (PASS)
% and * (PASS)
% and * (PASS)
% and * (PASS)
+ and * (PASS)
+ and * (PASS)
+ and * (PASS)
< and + (PASS)
< and + (PASS)
+ and < (PASS)
+ and < (PASS)
+= and + (PASS)
+= and + (PASS)
+= and + (PASS)
&& and || (PASS)
&& and || (PASS)
&& and || (PASS)
|| and && (PASS)
|| and && (PASS)
|| and && (PASS)
|| and conditional operator (PASS)
|| and conditional operator (PASS)
|| and conditional operator (PASS)
conditional operator and || (PASS)
conditional operator and || (PASS)
conditional operator and || (PASS)

View file

@ -0,0 +1,66 @@
# @TEST-EXEC: bro %INPUT >out
# @TEST-EXEC: btest-diff out
function test_case(msg: string, expect: bool)
{
print fmt("%s (%s)", msg, expect ? "PASS" : "FAIL");
}
global ct: count;
function f1(): bool
{
ct += 1;
return T;
}
function f2(): bool
{
ct += 4;
return F;
}
event bro_init()
{
local a: count;
local b: count;
local res: count;
local res2: bool;
# Test that the correct operand is evaluated
a = b = 0;
res = T ? ++a : ++b;
test_case( "true condition", a == 1 && b == 0 && res == 1);
a = b = 0;
res = F ? ++a : ++b;
test_case( "false condition", a == 0 && b == 1 && res == 1);
# Test again using function calls as operands
ct = 0;
res2 = ct == 0 ? f1() : f2();
test_case( "true condition", ct == 1 && res2 == T);
ct = 0;
res2 = ct != 0 ? f1() : f2();
test_case( "false condition", ct == 4 && res2 == F);
# Test that the conditional operator is right-associative
ct = 0;
T ? f1() : T ? f1() : f2();
test_case( "associativity", ct == 1 );
ct = 0;
T ? f1() : (T ? f1() : f2());
test_case( "associativity", ct == 1 );
ct = 0;
(T ? f1() : T) ? f1() : f2();
test_case( "associativity", ct == 2 );
}

View file

@ -0,0 +1,30 @@
# @TEST-EXEC: bro %INPUT >out
# @TEST-EXEC: btest-diff out
function test_case(msg: string, expect: bool)
{
print fmt("%s (%s)", msg, expect ? "PASS" : "FAIL");
}
event bro_init()
{
# "b" is not a copy of "a"
local a: set[string] = set("this", "test");
local b: set[string] = a;
delete a["this"];
test_case( "direct assignment", |b| == 1 && "this" !in b );
# "d" is a copy of "c"
local c: set[string] = set("this", "test");
local d: set[string] = copy(c);
delete c["this"];
test_case( "using copy", |d| == 2 && "this" in d);
}

View file

@ -11,10 +11,11 @@ event bro_init()
{
local c1: count = 0;
local c2: count = 5;
local c3: count = 0xff;
local c3: count = 0xFF;
local c4: count = 255;
local c5: count = 4294967295; # maximum allowed value
local c6: counter = 5;
local c6: count = 0x7fffffffffffffff; # maximum allowed value
local c7: counter = 5;
test_case( "inequality operator", c1 != c2 );
test_case( "relational operator", c1 < c2 );
@ -22,7 +23,7 @@ event bro_init()
test_case( "relational operator", c2 > c1 );
test_case( "relational operator", c2 >= c1 );
test_case( "hexadecimal", c3 == c4 );
test_case( "counter alias", c2 == c6 );
test_case( "counter alias", c2 == c7 );
test_case( "absolute value", |c1| == 0 );
test_case( "absolute value", |c2| == 5 );
test_case( "pre-increment operator", ++c2 == 6 );
@ -35,6 +36,8 @@ event bro_init()
test_case( "assignment operator", c2 == 6 );
local str1 = fmt("max count value = %d", c5);
test_case( str1, str1 == "max count value = 4294967295" );
local str2 = fmt("max count value = %d", c6);
test_case( str2, str2 == "max count value = 9223372036854775807" );
# type inference
local x = 1;

View file

@ -27,7 +27,7 @@ event bro_init()
local d16: double = .03E2;
local d17: double = 3.0001;
local d18: double = -3.0001;
local d19: double = 1.7e308; # almost maximum allowed value
local d19: double = 1.7976931348623157e308; # maximum allowed value
test_case( "double representations", d1 == d2 );
test_case( "double representations", d1 == d3 );
@ -55,8 +55,8 @@ event bro_init()
test_case( "relational operator", d17 >= d3 );
test_case( "relational operator", d17 > d3 );
test_case( "division operator", d3/2 == 1.5 );
local str1 = fmt("max double value = %.1e", d19);
test_case( str1, str1 == "max double value = 1.7e+308" );
local str1 = fmt("max double value = %.16e", d19);
test_case( str1, str1 == "max double value = 1.7976931348623157e+308" );
# type inference
local x = 7.0;

View file

@ -19,8 +19,10 @@ event bro_init()
local i8: int = 0xC;
local i9: int = -0xC;
local i10: int = -12;
local i11: int = 4294967295;
local i12: int = -4294967295;
local i11: int = 4294967295; # max. allowed value
local i12: int = -4294967295; # min. allowed value
local i13: int = 0x7fffffffffffffff; # max. allowed value
local i14: int = -0x7fffffffffffffff; # min. allowed value
test_case( "optional '+' sign", i1 == i2 );
test_case( "negative vs. positive", i1 != i3 );
@ -46,6 +48,10 @@ event bro_init()
test_case( str1, str1 == "max int value = 4294967295" );
local str2 = fmt("min int value = %d", i12);
test_case( str2, str2 == "min int value = -4294967295" );
local str3 = fmt("max int value = %d", i13);
test_case( str3, str3 == "max int value = 9223372036854775807" );
local str4 = fmt("min int value = %d", i14);
test_case( str4, str4 == "min int value = -9223372036854775807" );
# type inference
local x = +3;

View file

@ -0,0 +1,41 @@
# @TEST-EXEC: bro %INPUT secondtestfile >out
# @TEST-EXEC: btest-diff out
# In this source file, we define a module and export some objects
module thisisatest;
export {
global test_case: function(msg: string, expect: bool);
global testevent: event(msg: string);
global num: count = 123;
const daysperyear: count = 365;
}
function test_case(msg: string, expect: bool)
{
print fmt("%s (%s)", msg, expect ? "PASS" : "FAIL");
}
event testevent(msg: string)
{
test_case( "event", T );
}
# @TEST-START-FILE secondtestfile
# In this source file, we try to access each exported object from the module
event bro_init()
{
thisisatest::test_case( "function", T );
thisisatest::test_case( "global variable", thisisatest::num == 123 );
thisisatest::test_case( "const", thisisatest::daysperyear == 365 );
event thisisatest::testevent( "foo" );
}
# @TEST-END-FILE

View file

@ -0,0 +1,110 @@
# @TEST-EXEC: bro %INPUT >out
# @TEST-EXEC: btest-diff out
function test_case(msg: string, expect: bool)
{
print fmt("%s (%s)", msg, expect ? "PASS" : "FAIL");
}
# This is an incomplete set of tests to demonstrate the order of precedence
# of bro script operators
event bro_init()
{
local n1: int;
local n2: int;
local n3: int;
# Tests that show "++" has higher precedence than "*"
n1 = n2 = 5;
n1 = ++n1 * 3;
n2 = (++n2) * 3;
test_case( "++ and *", n1 == 18 );
test_case( "++ and *", n2 == 18 );
n1 = 5;
n1 = 3 * ++n1;
test_case( "* and ++", n1 == 18 );
# Tests that show "*" has same precedence as "%"
n1 = 3 * 5 % 2;
n2 = (3 * 5) % 2;
n3 = 3 * (5 % 2);
test_case( "* and %", n1 == 1 );
test_case( "* and %", n2 == 1 );
test_case( "* and %", n3 == 3 );
n1 = 7 % 3 * 2;
n2 = (7 % 3) * 2;
n3 = 7 % (3 * 2);
test_case( "% and *", n1 == 2 );
test_case( "% and *", n2 == 2 );
test_case( "% and *", n3 == 1 );
# Tests that show "*" has higher precedence than "+"
n1 = 1 + 2 * 3;
n2 = 1 + (2 * 3);
n3 = (1 + 2) * 3;
test_case( "+ and *", n1 == 7 );
test_case( "+ and *", n2 == 7 );
test_case( "+ and *", n3 == 9 );
# Tests that show "+" has higher precedence than "<"
test_case( "< and +", 5 < 3 + 7 );
test_case( "< and +", 5 < (3 + 7) );
test_case( "+ and <", 7 + 3 > 5 );
test_case( "+ and <", (7 + 3) > 5 );
# Tests that show "+" has higher precedence than "+="
n1 = n2 = n3 = 0;
n1 += 1 + 2;
n2 += (1 + 2);
(n3 += 1) + 2;
test_case( "+= and +", n1 == 3 );
test_case( "+= and +", n2 == 3 );
test_case( "+= and +", n3 == 1 );
local r1: bool;
local r2: bool;
local r3: bool;
# Tests that show "&&" has higher precedence than "||"
r1 = F && F || T;
r2 = (F && F) || T;
r3 = F && (F || T);
test_case( "&& and ||", r1 );
test_case( "&& and ||", r2 );
test_case( "&& and ||", !r3 );
r1 = T || F && F;
r2 = T || (F && F);
r3 = (T || F) && F;
test_case( "|| and &&", r1 );
test_case( "|| and &&", r2 );
test_case( "|| and &&", !r3 );
# Tests that show "||" has higher precedence than conditional operator
r1 = T || T ? F : F;
r2 = (T || T) ? F : F;
r3 = T || (T ? F : F);
test_case( "|| and conditional operator", !r1 );
test_case( "|| and conditional operator", !r2 );
test_case( "|| and conditional operator", r3 );
r1 = T ? F : F || T;
r2 = T ? F : (F || T);
r3 = (T ? F : F) || T;
test_case( "conditional operator and ||", !r1 );
test_case( "conditional operator and ||", !r2 );
test_case( "conditional operator and ||", r3 );
}