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(); return mismatch_err();
std::string candidate(j.GetString(), j.GetStringLength()); 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() == '/' ) { if ( candidate.size() > 2 && candidate.front() == candidate.back() && candidate.back() == '/' ) {
// Remove the '/'s
candidate.erase(0, 1); candidate.erase(0, 1);
candidate.erase(candidate.size() - 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()); auto re = std::make_unique<RE_Matcher>(candidate.c_str());
if ( ! re->Compile() ) if ( ! re->Compile() )

View file

@ -76,18 +76,26 @@ table index membership (PASS)
table index non-membership (PASS) table index non-membership (PASS)
table index reduced size (PASS) table index reduced size (PASS)
table index iteration (PASS) table index iteration (PASS)
table index JSON roundtrip success (PASS)
table index JSON roundtrip correct (PASS)
vector index size (PASS) vector index size (PASS)
vector index membership (PASS) vector index membership (PASS)
vector index non-membership (PASS) vector index non-membership (PASS)
vector index reduced size (PASS) vector index reduced size (PASS)
vector index iteration (PASS) vector index iteration (PASS)
vector index JSON roundtrip success (PASS)
vector index JSON roundtrip correct (PASS)
set index size (PASS) set index size (PASS)
set index membership (PASS) set index membership (PASS)
set index non-membership (PASS) set index non-membership (PASS)
set index reduced size (PASS) set index reduced size (PASS)
set index iteration (PASS) set index iteration (PASS)
set index JSON roundtrip success (PASS)
set index JSON roundtrip correct (PASS)
pattern index size (PASS) pattern index size (PASS)
pattern index membership (PASS) pattern index membership (PASS)
pattern index non-membership (PASS) pattern index non-membership (PASS)
pattern index reduced size (PASS) pattern index reduced size (PASS)
pattern index iteration (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|); 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 # Initialization
local s1: set[table[string] of string] = { table(["k1"] = "v1") }; local s: tss_set = { table(["k1"] = "v1") };
# Adding a member # Adding a member
add s1[table(["k2"] = "v2")]; add s[table(["k2"] = "v2")];
# Various checks, including membership test # Various checks, including membership test
test_case( "table index size", |s1| == 2 ); test_case( "table index size", |s| == 2 );
test_case( "table index membership", table(["k2"] = "v2") in s1 ); test_case( "table index membership", table(["k2"] = "v2") in s );
test_case( "table index non-membership", table(["k2"] = "v3") !in s1 ); test_case( "table index non-membership", table(["k2"] = "v3") !in s );
# Member deletion # Member deletion
delete s1[table(["k1"] = "v1")]; delete s[table(["k1"] = "v1")];
test_case( "table index reduced size", |s1| == 1 ); test_case( "table index reduced size", |s| == 1 );
# Iteration # Iteration
for ( ti in s1 ) for ( ti in s )
{ {
test_case( "table index iteration", to_json(ti) == to_json(table(["k2"] = "v2")) ); test_case( "table index iteration", to_json(ti) == to_json(table(["k2"] = "v2")) );
break; 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 # 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")]; add s[vector("v3", "v4")];
test_case( "vector index size", |s2| == 2 ); test_case( "vector index size", |s| == 2 );
test_case( "vector index membership", vector("v3", "v4") in s2 ); test_case( "vector index membership", vector("v3", "v4") in s );
test_case( "vector index non-membership", vector("v4", "v5") !in s2 ); test_case( "vector index non-membership", vector("v4", "v5") !in s );
delete s2[vector("v1", "v2")]; delete s[vector("v1", "v2")];
test_case( "vector index reduced size", |s2| == 1 ); 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")) ); test_case( "vector index iteration", to_json(vi) == to_json(vector("v3", "v4")) );
break; 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")]; type ss_set: set[set[string]];
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 );
delete s3[set("s1", "s2")]; function complex_index_type_set()
test_case( "set index reduced size", |s3| == 1 ); {
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")) ); test_case( "set index iteration", to_json(si) == to_json(set("s3", "s4")) );
break; 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/]; type p_set: set[pattern];
test_case( "pattern index size", |s4| == 2 );
test_case( "pattern index membership", /pat2/ in s4 );
test_case( "pattern index non-membership", /pat3/ !in s4 );
delete s4[/pat1/]; function complex_index_type_pattern()
test_case( "pattern index reduced size", |s4| == 1 ); {
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/) ); test_case( "pattern index iteration", to_json(pi) == to_json(/pat2/) );
break; 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() event zeek_init()
{ {
basic_functionality(); basic_functionality();
complex_index_types(); complex_index_type_table();
complex_index_type_vector();
complex_index_type_set();
complex_index_type_pattern();
} }