Checkpoint - all non-opaque-types can be cloned.

This commit is contained in:
Johanna Amann 2019-05-21 15:06:39 -07:00
parent d13c939233
commit 2efbe76920
2 changed files with 180 additions and 8 deletions

View file

@ -1216,6 +1216,7 @@ Val* PatternVal::DoClone(CloneState* state)
{
// TODO: Double-check
auto re = new RE_Matcher(val.re_val->PatternText(), val.re_val->AnywherePatternText());
re->Compile();
return new PatternVal(re);
}
@ -2557,7 +2558,14 @@ Val* TableVal::DoClone(CloneState* state)
while ( (val = tbl->NextEntry(key, cookie)) )
{
Val* idx = RecoverIndex(key);
TableEntryVal* nval = val ? new TableEntryVal(*val) : nullptr;
TableEntryVal* nval = nullptr;
if ( val )
{
if ( val->Value() )
nval = new TableEntryVal(val->Value()->Clone());
else
nval = new TableEntryVal(nullptr);
}
tv->AsNonConstTable()->Insert(key, nval);
if ( subnets )
@ -3175,17 +3183,22 @@ void RecordVal::DescribeReST(ODesc* d) const
Val* RecordVal::DoClone(CloneState* state)
{
// TODO: We leave origin unset, ok?
// We set origin to 0 here.
// Origin only seems to be used for exactly one purpose - to find the connection record that is associated
// with a record. As we cannot guarantee that it will ber zeroed out at the approproate time (as it seems to be
// guaranteed for the original record) we don't touch it.
::Ref(record_type);
auto rv = new RecordVal(record_type);
rv->origin = nullptr;
rv->val.val_list_val = new val_list(val.val_list_val->length());
loop_over_list(*val.val_list_val, i)
{
Val* v = (*val.val_list_val)[i]->Clone(state);
Val* v = (*val.val_list_val)[i] ? (*val.val_list_val)[i]->Clone(state) : nullptr;
rv->val.val_list_val->append(v);
}
return nullptr;
return rv;
}
IMPLEMENT_SERIAL(RecordVal, SER_RECORD_VAL);

View file

@ -1,6 +1,56 @@
# @TEST-EXEC: bro -b %INPUT >out
# @TEST-EXEC: zeek -b %INPUT >out
# @TEST-EXEC: btest-diff out
type MyEnum: enum { ENUMME };
type InnerTestRecord: record {
a: string;
};
type TestRecord: record {
s1: string;
s2: string;
i1: InnerTestRecord;
i2: InnerTestRecord &optional;
donotset: InnerTestRecord &optional;
def: count &default=5;
};
function join_count_set(ss: set[count], j: string): string
{
local output="";
local i=0;
for ( s in ss )
{
if ( i > 0 )
output = cat(output, j);
output = cat(output, s);
++i;
}
return output;
}
function do_format(i: any): any
{
local tpe = type_name(i);
switch ( tpe )
{
case "set[count]":
return join_count_set(i, ",");
case "table[string] of string":
local cast: table[string] of string = i;
local vout: vector of string = vector();
for ( el in cast )
{
vout += cat(el, "=", cast[el]);
}
return join_string_vec(vout, ";");
}
return i;
}
function check(o1: any, o2: any, equal: bool, expect_same: bool)
{
local expect_msg = (equal ? "ok" : "FAIL0");
@ -12,16 +62,125 @@ function check(o1: any, o2: any, equal: bool, expect_same: bool)
if ( ! expect_same && same )
expect_msg = "FAIL2";
print fmt("orig=%s (%s) clone=%s (%s) equal=%s same_object=%s (%s)", o1, type_name(o1), o2, type_name(o2), equal, same, expect_msg);
print fmt("orig=%s (%s) clone=%s (%s) equal=%s same_object=%s (%s)", do_format(o1), type_name(o1), do_format(o2), type_name(o2), equal, same, expect_msg);
}
function check_vector_equal(a: vector of count, b: vector of count): bool
{
if ( |a| != |b| )
return F;
for ( i in a )
{
if ( a[i] != b[i] )
return F;
}
return T;
}
function check_string_table_equal(a: table[string] of string, b: table[string] of string): bool
{
if ( |a| != |b| )
return F;
for ( i in a )
{
if ( a[i] != b[i] )
return F;
}
return T;
}
function compare_otr(a: TestRecord, b: TestRecord): bool
{
if ( a$s1 != b$s1 )
return F;
if ( a$s2 != b$s2 )
return F;
if ( a$i1$a != b$i1$a )
return F;
if ( a$i2$a != b$i2$a )
return F;
if ( same_object(a$i1, b$i1) )
return F;
if ( same_object(a$i2, b$i2) )
return F;
# check that we restroe that i1 & i2 point to same object
if ( ! same_object(a$i1, a$i2) )
return F;
if ( ! same_object(b$i1, b$i2) )
return F;
if ( a$def != b$def )
return F;
return T;
}
event zeek_init()
{
local i1 = -42;
local i2 = copy(i1);
check(i1, i2, i1 == i2, T);
local c1 : count = 42;
local c2 = copy(c1);
check(c1, c2, c1 == c2, T);
local a1 = 127.0.0.1;
local a2 = copy(a1);
check(a1, a2, a1 == a2, T);
local p1 = 42/tcp;
local p2 = copy(p1);
check(p1, p2, p1 == p2, T);
local sn1 = 127.0.0.1/24;
local sn2 = copy(sn1);
check(sn1, sn2, sn1 == sn2, T);
local s1 = "Foo";
local s2 = copy(s1);
check(s1, s2, s1 == s2, F);
local pat1 = /.*PATTERN.*/;
local pat2 = copy(pat1);
# patterns cannot be directoy compared
if ( same_object(pat1, pat2) )
print "FAIL P1";
if ( ! ( pat1 == "PATTERN" ) )
print "FAIL P2";
if ( ! ( pat2 == "PATTERN" ) )
print "FAIL P3";
if ( pat2 == "PATERN" )
print "FAIL P4";
print fmt("orig=%s (%s) clone=%s (%s) same_object=%s", pat1, type_name(pat1), pat2, type_name(pat2), same_object(pat1, pat2));
local set1 = [1, 2, 3, 4, 5];
local set2 = copy(set1);
check(set1, set2, set1 == set2, F);
local v1 = vector(1, 2, 3, 4, 5);
local v2 = copy(v1);
check(v1, v2, check_vector_equal(v1, v2), F);
local t1 : table[string] of string = table();
t1["a"] = "va";
t1["b"] = "vb";
local t2 = copy(t1);
check(t1, t2, check_string_table_equal(t1, t2), F);
local e1 = ENUMME;
local e2 = copy(ENUMME);
check(e1, e2, e1 == e2, T);
local itr = InnerTestRecord($a="a");
local otr1 = TestRecord($s1="s1", $s2="s2", $i1=itr, $i2=itr);
local otr2 = copy(otr1);
check(otr1, otr2, compare_otr(otr1, otr2), F);
}