Support JSON roundtripping via to_json()/from_json() for patterns

This needed a small tweak in the deserialization, since each roundtrip
would otherwise pad the prior pattern with an extra /^?(...)$?/.

This expands the language.set test to also verify serializing/unserializing for
sets, similarly to tables in the previous commit.
This commit is contained in:
Christian Kreibich 2024-06-28 17:27:47 -07:00
parent 92c1098e97
commit 0179a5e75c
3 changed files with 86 additions and 35 deletions

View file

@ -996,11 +996,17 @@ static std::variant<ValPtr, std::string> BuildVal(const rapidjson::Value& j, con
return mismatch_err();
std::string candidate(j.GetString(), j.GetStringLength());
// Remove any surrounding '/'s, not needed when creating an RE_matcher.
if ( candidate.size() > 2 && candidate.front() == candidate.back() && candidate.back() == '/' ) {
// Remove the '/'s
candidate.erase(0, 1);
candidate.erase(candidate.size() - 1);
}
// Remove any surrounding "^?(" and ")$?", automatically added below.
if ( candidate.size() > 6 && candidate.substr(0, 3) == "^?(" &&
candidate.substr(candidate.size() - 3, 3) == ")$?" ) {
candidate.erase(0, 3);
candidate.erase(candidate.size() - 3);
}
auto re = std::make_unique<RE_Matcher>(candidate.c_str());
if ( ! re->Compile() )

View file

@ -76,18 +76,26 @@ table index membership (PASS)
table index non-membership (PASS)
table index reduced size (PASS)
table index iteration (PASS)
table index JSON roundtrip success (PASS)
table index JSON roundtrip correct (PASS)
vector index size (PASS)
vector index membership (PASS)
vector index non-membership (PASS)
vector index reduced size (PASS)
vector index iteration (PASS)
vector index JSON roundtrip success (PASS)
vector index JSON roundtrip correct (PASS)
set index size (PASS)
set index membership (PASS)
set index non-membership (PASS)
set index reduced size (PASS)
set index iteration (PASS)
set index JSON roundtrip success (PASS)
set index JSON roundtrip correct (PASS)
pattern index size (PASS)
pattern index membership (PASS)
pattern index non-membership (PASS)
pattern index reduced size (PASS)
pattern index iteration (PASS)
pattern index JSON roundtrip success (PASS)
pattern index JSON roundtrip correct (PASS)

View file

@ -186,82 +186,119 @@ function basic_functionality()
test_case( "magnitude", |a_and_b| == |a_or_b|);
}
function complex_index_types()
type tss_set: set[table[string] of string];
function complex_index_type_table()
{
# Initialization
local s1: set[table[string] of string] = { table(["k1"] = "v1") };
local s: tss_set = { table(["k1"] = "v1") };
# Adding a member
add s1[table(["k2"] = "v2")];
add s[table(["k2"] = "v2")];
# Various checks, including membership test
test_case( "table index size", |s1| == 2 );
test_case( "table index membership", table(["k2"] = "v2") in s1 );
test_case( "table index non-membership", table(["k2"] = "v3") !in s1 );
test_case( "table index size", |s| == 2 );
test_case( "table index membership", table(["k2"] = "v2") in s );
test_case( "table index non-membership", table(["k2"] = "v3") !in s );
# Member deletion
delete s1[table(["k1"] = "v1")];
test_case( "table index reduced size", |s1| == 1 );
delete s[table(["k1"] = "v1")];
test_case( "table index reduced size", |s| == 1 );
# Iteration
for ( ti in s1 )
for ( ti in s )
{
test_case( "table index iteration", to_json(ti) == to_json(table(["k2"] = "v2")) );
break;
}
# JSON serialize/unserialize
local fjr = from_json(to_json(s), tss_set);
test_case( "table index JSON roundtrip success", fjr$valid );
test_case( "table index JSON roundtrip correct", to_json(s) == to_json(fjr$v) );
}
type vs_set: set[vector of string];
function complex_index_type_vector()
{
# As above, for other index types
local s2: set[vector of string] = { vector("v1", "v2") };
local s: vs_set = { vector("v1", "v2") };
add s2[vector("v3", "v4")];
test_case( "vector index size", |s2| == 2 );
test_case( "vector index membership", vector("v3", "v4") in s2 );
test_case( "vector index non-membership", vector("v4", "v5") !in s2 );
add s[vector("v3", "v4")];
test_case( "vector index size", |s| == 2 );
test_case( "vector index membership", vector("v3", "v4") in s );
test_case( "vector index non-membership", vector("v4", "v5") !in s );
delete s2[vector("v1", "v2")];
test_case( "vector index reduced size", |s2| == 1 );
delete s[vector("v1", "v2")];
test_case( "vector index reduced size", |s| == 1 );
for ( vi in s2 )
for ( vi in s )
{
test_case( "vector index iteration", to_json(vi) == to_json(vector("v3", "v4")) );
break;
}
local s3: set[set[string]] = { set("s1", "s2") };
local fjr = from_json(to_json(s), vs_set);
test_case( "vector index JSON roundtrip success", fjr$valid );
test_case( "vector index JSON roundtrip correct", to_json(s) == to_json(fjr$v) );
}
add s3[set("s3", "s4")];
test_case( "set index size", |s3| == 2 );
test_case( "set index membership", set("s3", "s4") in s3 );
test_case( "set index non-membership", set("s4", "s5") !in s3 );
type ss_set: set[set[string]];
delete s3[set("s1", "s2")];
test_case( "set index reduced size", |s3| == 1 );
function complex_index_type_set()
{
local s: ss_set = { set("s1", "s2") };
for ( si in s3 )
add s[set("s3", "s4")];
test_case( "set index size", |s| == 2 );
test_case( "set index membership", set("s3", "s4") in s );
test_case( "set index non-membership", set("s4", "s5") !in s );
delete s[set("s1", "s2")];
test_case( "set index reduced size", |s| == 1 );
for ( si in s )
{
test_case( "set index iteration", to_json(si) == to_json(set("s3", "s4")) );
break;
}
local s4: set[pattern] = { /pat1/ };
local fjr = from_json(to_json(s), ss_set);
test_case( "set index JSON roundtrip success", fjr$valid );
test_case( "set index JSON roundtrip correct", to_json(s) == to_json(fjr$v) );
}
add s4[/pat2/];
test_case( "pattern index size", |s4| == 2 );
test_case( "pattern index membership", /pat2/ in s4 );
test_case( "pattern index non-membership", /pat3/ !in s4 );
type p_set: set[pattern];
delete s4[/pat1/];
test_case( "pattern index reduced size", |s4| == 1 );
function complex_index_type_pattern()
{
local s: p_set = { /pat1/ };
for ( pi in s4 )
add s[/pat2/];
test_case( "pattern index size", |s| == 2 );
test_case( "pattern index membership", /pat2/ in s );
test_case( "pattern index non-membership", /pat3/ !in s );
delete s[/pat1/];
test_case( "pattern index reduced size", |s| == 1 );
for ( pi in s )
{
test_case( "pattern index iteration", to_json(pi) == to_json(/pat2/) );
break;
}
local fjr = from_json(to_json(s), p_set);
test_case( "pattern index JSON roundtrip success", fjr$valid );
test_case( "pattern index JSON roundtrip correct", to_json(s) == to_json(fjr$v) );
}
event zeek_init()
{
basic_functionality();
complex_index_types();
complex_index_type_table();
complex_index_type_vector();
complex_index_type_set();
complex_index_type_pattern();
}