# @TEST-DOC: Iterating over tables with record keys would previously evaluate &default during each iteration. Ensure this isn't happening. Regression test for #3267.
# @TEST-EXEC: zeek -b %INPUT >output
# @TEST-EXEC: btest-diff output

global seq = 0;
function my_seq(): count {
	print seq, "my_seq() invoked";
	return ++seq;
}

type R: record {
	id: count &default=my_seq();
};

global tbl: table[R] of count;

print seq, "populating table, expecting 4 my_seq() invocations";

tbl[R()] = 1;
tbl[R()] = 2;
tbl[R()] = 3;
tbl[R()] = 4;

print seq, "iterating table, expecting no my_seq() invocations";
for ( [r], c in tbl )
	print seq, "it", r, c;

print seq, "done";

# @TEST-START-NEXT
#
# This acts subtly different - my_seq() is called maybe for the [r] local
# in the for loop?!
global seq = 0;
function my_seq(): count {
	print seq, "my_seq() invoked";
	return ++seq;
}

type R: record {
	id: count &default=my_seq();
};

global tbl: table[R] of count;

 event zeek_init()
	{
	print seq, "populating table, expecting 4 my_seq() invocations";

	tbl[R()] = 1;
	tbl[R()] = 2;
	tbl[R()] = 3;
	tbl[R()] = 4;

	print seq, "iterating table, expecting no my_seq() invocations";
	for ( [r], c in tbl )
		print seq, "it", r, c;

	print seq, "done";
	}

print seq, "done parsing";

# @TEST-START-NEXT
#
# table[R] of R
global seq = 0;
function my_seq(): count {
	print seq, "my_seq() invoked";
	return ++seq;
}

type R: record {
	id: count &default=my_seq();
};

global tbl: table[R] of R;

 event zeek_init()
	{
	print seq, "populating table, expecting 8 my_seq() invocations";

	# The following structure is used to avoid order-of-evaluation
	# ambiguity. If we use "tbl[R()] = R()" statements then script
	# optimization might create different table indices/values than
	# interpreted execution.
	local v = R();
	tbl[R()] = v;
	v = R();
	tbl[R()] = v;
	v = R();
	tbl[R()] = v;
	v = R();
	tbl[R()] = v;

	print seq, "iterating table, expecting no my_seq() invocations";
	for ( [r1], r2 in tbl )
		print seq, "it", r1, r2;

	print seq, "done";
	}

print seq, "done parsing";
