mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00

The fatal error is actually triggered at runtime, so it's a bit dangerous for users, but not sure there's many use-cases to compare vectors of patterns. Closes #4084
251 lines
7.6 KiB
Text
251 lines
7.6 KiB
Text
# @TEST-EXEC: zeek -b %INPUT >out
|
|
# @TEST-EXEC: btest-diff out
|
|
# @TEST-EXEC: btest-diff .stderr
|
|
|
|
function test_case(msg: string, expect: bool)
|
|
{
|
|
print fmt("%s (%s)", msg, expect ? "PASS" : "FAIL");
|
|
}
|
|
|
|
|
|
# Note: only global vectors can be initialized with curly braces
|
|
global vg1: vector of string = { "curly", "braces" };
|
|
|
|
type R: record {
|
|
a: bool &default=T;
|
|
};
|
|
|
|
|
|
event zeek_init()
|
|
{
|
|
local v1: vector of string = vector( "test", "example" );
|
|
local v2: vector of string = vector();
|
|
local v3: vector of string;
|
|
local v4 = vector( "type inference" );
|
|
local v5 = vector( 1, 2, 3 );
|
|
local v6 = vector( 10, 20, 30 );
|
|
local v7 = v5 + v6;
|
|
local v8 = v6 - v5;
|
|
local v9 = v5 * v6;
|
|
local v10 = v6 / v5;
|
|
local v11 = v6 % v5;
|
|
local v12 = vector( T, F, T );
|
|
local v13 = vector( F, F, T );
|
|
local v14 = v12 && v13;
|
|
local v15 = v12 || v13;
|
|
local v18 = v12 ? v5 : v6;
|
|
|
|
# Type inference tests
|
|
|
|
test_case( "type inference", type_name(v4) == "vector of string" );
|
|
test_case( "type inference", type_name(v5) == "vector of count" );
|
|
test_case( "type inference", type_name(v12) == "vector of bool" );
|
|
|
|
# Test the size of each vector
|
|
|
|
test_case( "cardinality", |v1| == 2 );
|
|
test_case( "cardinality", |v2| == 0 );
|
|
test_case( "cardinality", |v3| == 0 );
|
|
test_case( "cardinality", |v4| == 1 );
|
|
test_case( "cardinality", |v5| == 3 );
|
|
test_case( "cardinality", |v6| == 3 );
|
|
test_case( "cardinality", |v7| == 3 );
|
|
test_case( "cardinality", |v8| == 3 );
|
|
test_case( "cardinality", |v9| == 3 );
|
|
test_case( "cardinality", |v10| == 3 );
|
|
test_case( "cardinality", |v11| == 3 );
|
|
test_case( "cardinality", |v12| == 3 );
|
|
test_case( "cardinality", |v13| == 3 );
|
|
test_case( "cardinality", |v14| == 3 );
|
|
test_case( "cardinality", |v15| == 3 );
|
|
test_case( "cardinality", |vg1| == 2 );
|
|
|
|
# Test that vectors use zero-based indexing
|
|
|
|
test_case( "zero-based indexing", v1[0] == "test" && v5[0] == 1 );
|
|
|
|
# Test iterating over each vector
|
|
|
|
local ct: count;
|
|
ct = 0;
|
|
for ( c in v1 )
|
|
{
|
|
if ( type_name(c) != "count" )
|
|
print "Error: wrong index type";
|
|
if ( type_name(v1[c]) != "string" )
|
|
print "Error: wrong vector type";
|
|
++ct;
|
|
}
|
|
test_case( "iterate over vector", ct == 2 );
|
|
|
|
ct = 0;
|
|
for ( c in v2 )
|
|
{
|
|
++ct;
|
|
}
|
|
test_case( "iterate over vector", ct == 0 );
|
|
|
|
ct = 0;
|
|
for ( c in vg1 )
|
|
{
|
|
++ct;
|
|
}
|
|
test_case( "iterate over vector", ct == 2 );
|
|
|
|
# Test adding elements to each vector
|
|
|
|
v1[2] = "added";
|
|
test_case( "add element", |v1| == 3 );
|
|
test_case( "access element", v1[2] == "added" );
|
|
|
|
v2[0] = "another";
|
|
test_case( "add element", |v2| == 1 );
|
|
v2[1] = "test";
|
|
test_case( "add element", |v2| == 2 );
|
|
test_case( "access element", v2[0] == "another" );
|
|
test_case( "access element", v2[1] == "test" );
|
|
|
|
v3[0] = "foo";
|
|
test_case( "add element", |v3| == 1 );
|
|
test_case( "access element", v3[0] == "foo" );
|
|
|
|
v4[1] = "local";
|
|
test_case( "add element", |v4| == 2 );
|
|
test_case( "access element", v4[1] == "local" );
|
|
|
|
v5[3] = 77;
|
|
test_case( "add element", |v5| == 4 );
|
|
test_case( "access element", v5[3] == 77 );
|
|
|
|
v5[10] = 10;
|
|
test_case( "add above a hole", |v5| == 11 );
|
|
test_case( "in operator for non-hole", 3 in v5 );
|
|
test_case( "in operator for hole", 4 !in v5 );
|
|
test_case( "in operator for edge", |v5|-1 in v5 );
|
|
test_case( "in operator for out of range", 44 !in v5 );
|
|
|
|
vg1[2] = "global";
|
|
test_case( "add element", |vg1| == 3 );
|
|
test_case( "access element", vg1[2] == "global" );
|
|
|
|
# Test overwriting elements of each vector
|
|
|
|
v1[0] = "new1";
|
|
test_case( "overwrite element", |v1| == 3 );
|
|
test_case( "access element", v1[0] == "new1" );
|
|
|
|
v2[1] = "new2";
|
|
test_case( "overwrite element", |v2| == 2 );
|
|
test_case( "access element", v2[0] == "another" );
|
|
test_case( "access element", v2[1] == "new2" );
|
|
|
|
v3[0] = "new3";
|
|
test_case( "overwrite element", |v3| == 1 );
|
|
test_case( "access element", v3[0] == "new3" );
|
|
|
|
v4[0] = "new4";
|
|
test_case( "overwrite element", |v4| == 2 );
|
|
test_case( "access element", v4[0] == "new4" );
|
|
|
|
v5[0] = 0;
|
|
test_case( "overwrite element", |v5| == 11 );
|
|
test_case( "access element", v5[0] == 0 );
|
|
|
|
vg1[1] = "new5";
|
|
test_case( "overwrite element", |vg1| == 3 );
|
|
test_case( "access element", vg1[1] == "new5" );
|
|
|
|
# Test +,-,*,/,% of two vectors
|
|
|
|
test_case( "+ operator", v7[0] == 11 && v7[1] == 22 && v7[2] == 33 );
|
|
test_case( "- operator", v8[0] == 9 && v8[1] == 18 && v8[2] == 27 );
|
|
test_case( "* operator", v9[0] == 10 && v9[1] == 40 && v9[2] == 90 );
|
|
test_case( "/ operator", v10[0] == 10 && v10[1] == 10 && v10[2] == 10 );
|
|
test_case( "% operator", v11[0] == 0 && v11[1] == 0 && v11[2] == 0 );
|
|
|
|
local vs1: vector of string = vector( "foo", "bar" );
|
|
local vs2: vector of string = vector( "xxx", "yyy" );
|
|
local vs3: vector of string = vector( "xxx", "bar" );
|
|
|
|
local vss = vs1 + vs2;
|
|
test_case( "+ operator [string]", vss[0] == "fooxxx" && vss[1] == "baryyy" );
|
|
|
|
local vss3 = (vs1 == vs3);
|
|
test_case( "== operator [string]", vss3[0] == F && vss3[1] == T );
|
|
|
|
# Test &&,|| of two vectors
|
|
|
|
test_case( "&& operator", v14[0] == F && v14[1] == F && v14[2] == T );
|
|
test_case( "|| operator", v15[0] == T && v15[1] == F && v15[2] == T );
|
|
|
|
# Test += operator.
|
|
local v16 = v6;
|
|
v16 += 40;
|
|
test_case( "+= operator", all_set(v16 == vector( 10, 20, 30, 40 )) );
|
|
|
|
# Slicing tests.
|
|
local v17 = vector( 1, 2, 3, 4, 5 );
|
|
test_case( "slicing", all_set(v17[0:2] == vector( 1, 2 )) );
|
|
test_case( "slicing", all_set(v17[-3:-1] == vector( 3, 4 )) );
|
|
test_case( "slicing", all_set(v17[:2] == vector( 1, 2 )) );
|
|
test_case( "slicing", all_set(v17[2:] == vector( 3, 4, 5 )) );
|
|
test_case( "slicing", all_set(v17[:] == v17) );
|
|
v17[0:1] = vector(6);
|
|
test_case( "slicing assignment", all_set(v17 == vector(6, 2, 3, 4, 5)) );
|
|
v17[2:4] = vector(7, 8);
|
|
test_case( "slicing assignment", all_set(v17 == vector(6, 2, 7, 8, 5)) );
|
|
v17[2:4] = vector(9, 10, 11);
|
|
test_case( "slicing assignment grow", all_set(v17 == vector(6, 2, 9, 10, 11, 5)) );
|
|
v17[2:5] = vector(9);
|
|
test_case( "slicing assignment shrink", all_set(v17 == vector(6, 2, 9, 5)) );
|
|
|
|
# Test boolean ? operator.
|
|
test_case( "? operator", all_set(v18 == vector(1, 20, 3)) );
|
|
|
|
# Test copying of a vector with holes, as this used to crash.
|
|
local v19 = copy(v5);
|
|
test_case( "copy of a vector with holes", |v5| == |v19| );
|
|
# Even after removing some elements at the end, any trailing holes should
|
|
# be preserved after copying;
|
|
v5[6:] = vector();
|
|
local v20 = copy(v5);
|
|
print "copy of a vector with trailing holes", v5, v20;
|
|
|
|
local v21 = vector(R(), R());
|
|
v21[4] = R();
|
|
print "hole in vector of managed types", |v21|, v21;
|
|
v21[3:] = vector();
|
|
print "hole in vector of managed types after replacing slice", |v21|, v21;
|
|
|
|
# Test << and >> operators.
|
|
local four_ones = vector(1, 1, 1, 1);
|
|
local v22 = v6 << four_ones;
|
|
local v23 = v6 >> four_ones;
|
|
test_case( "left shift", all_set(v22 == vector(20, 40, 60, 80)) );
|
|
test_case( "right shift", all_set(v23 == vector(5, 10, 15, 20)) );
|
|
|
|
# negative indices
|
|
local v24 = vector( 1, 2, 3, 4, 5 );
|
|
test_case( "negative index", v24[-1] == 5 );
|
|
test_case( "negative index", v24[-3] == 3 );
|
|
|
|
# For a vector-of-vectors, += of an empty vector should append it as
|
|
# a single element, not all of its elements (= nothing gets appended).
|
|
local v25: vector of vector of count;
|
|
v25 += vector();
|
|
test_case( "+= of empty vector", |v25| == 1 );
|
|
|
|
# OTOH, for a vector-of-non-vectors, it should result in appending
|
|
# nothing.
|
|
local v26: vector of set[count];
|
|
v26 += vector();
|
|
test_case( "+= of empty vector", |v26| == 0 );
|
|
|
|
# Pattern vectors
|
|
local pv1 = vector(/a/, /b/);
|
|
local pv2 = vector(/a/, /c/);
|
|
local pv_eq = pv1 == pv2;
|
|
local pv_ne = pv1 != pv2;
|
|
test_case( fmt("pv1 == pv2 -> %s", pv_eq), (pv_eq[0] == T) && (pv_eq[1] == F) );
|
|
test_case( fmt("pv1 != pv2 -> %s", pv_ne), (pv_ne[0] == F) && (pv_ne[1] == T) );
|
|
}
|