@@ -41,13 +41,20 @@ def X_ = registerAll([
4141 ("multi_frames", test_multi_frames),
4242 ("single_val_per_frame", test_single_val_per_frame),
4343 ("cont", test_cont),
44- ("frame_metadata", test_frame_metadata)
44+ ("frame_metadata", test_frame_metadata),
45+ ("repeated_vals", test_repeated_vals),
46+ ("repeated_across_frames", test_repeated_across_frames),
47+ ("many_diverse_vals", test_many_diverse_vals),
48+ ("many_frames_diverse", test_many_frames_diverse),
49+ ("refs_mixed", test_refs_mixed),
50+ ("refs_shared_across_frames", test_refs_shared_across_frames),
51+ ("large_uniform_frames", test_large_uniform_frames)
4552]);
4653
4754def registerAll(tests: Array<(string, CompressionTester -> void)>) {
4855 for (t in tests) {
4956 for (s in strategies) {
50- var name = Strings.format2("compression:%s_ %s", s.0, t.0);
57+ var name = Strings.format2("compression:%s: %s", s.0, t.0);
5158 var adapter = s.1;
5259 UnitTests.registerT(name, "", CompressionTester.new(_, adapter), t.1);
5360 }
@@ -246,3 +253,143 @@ def test_frame_metadata(t: CompressionTester) {
246253 if (got[0].pc != 42) t.t.fail1("expected pc=42, got pc=%d", got[0].pc);
247254 t.assert_vals_eq([Value.I32(99)], got[0].vals);
248255}
256+
257+ // === Part 5: Repeated values ===
258+
259+ // Many identical values within a single frame.
260+ def test_repeated_vals(t: CompressionTester) {
261+ var vals = Array<Value>.new(100);
262+ for (i < vals.length) vals[i] = Value.I32(0xCAFEBABEu);
263+ t.assert_roundtrip_vals(vals);
264+
265+ // Repeat with i64.
266+ for (i < vals.length) vals[i] = Value.I64(0xDEADBEEF00000000uL);
267+ t.assert_roundtrip_vals(vals);
268+
269+ // Repeat with the same ref object.
270+ var obj = HeapObject.new(null, []);
271+ for (i < vals.length) vals[i] = Value.Ref(obj);
272+ t.assert_roundtrip_vals(vals);
273+ }
274+
275+ // Same repeating value pattern across multiple frames.
276+ def test_repeated_across_frames(t: CompressionTester) {
277+ var frames = Array<RelocatableFrame>.new(20);
278+ var shared_vals: Array<Value> = [Value.I32(42), Value.I64(42), Value.F32(42)];
279+ for (i < frames.length) frames[i] = t.make_frame(i, shared_vals);
280+ var got = t.roundtrip(frames);
281+ t.assert_frames_eq(frames, got);
282+ }
283+
284+ // === Part 6: Many diverse values ===
285+
286+ // Single frame with many values of varying types and magnitudes.
287+ def test_many_diverse_vals(t: CompressionTester) {
288+ var vals = Vector<Value>.new();
289+ for (i < 50) {
290+ vals.put(Value.I32(u32.view(i * 7)));
291+ vals.put(Value.I64(u64.view(i) * 0x100000001uL));
292+ vals.put(Value.F32(u32.view(i * 31)));
293+ vals.put(Value.F64(u64.view(i) * 0x123456789uL));
294+ }
295+ t.assert_roundtrip_vals(vals.extract());
296+ }
297+
298+ // Many frames, each with distinct values and varying sizes.
299+ def test_many_frames_diverse(t: CompressionTester) {
300+ var frames = Vector<RelocatableFrame>.new();
301+ for (i < 30) {
302+ var n_vals = (i % 5) + 1; // 1 to 5 values per frame
303+ var vals = Array<Value>.new(n_vals);
304+ for (j < n_vals) {
305+ var k = i * 5 + j;
306+ match (k % 4) {
307+ 0 => vals[j] = Value.I32(u32.view(k * 13));
308+ 1 => vals[j] = Value.I64(u64.view(k) * 0xABCDuL);
309+ 2 => vals[j] = Value.F32(u32.view(k * 97));
310+ _ => vals[j] = Value.F64(u64.view(k) * 0x1111111111uL);
311+ }
312+ }
313+ frames.put(t.make_frame(i * 3, vals));
314+ }
315+ var input = frames.extract();
316+ var got = t.roundtrip(input);
317+ t.assert_frames_eq(input, got);
318+ }
319+
320+ // === Part 7: Complex reference objects ===
321+
322+ // Multiple distinct reference types in a single frame.
323+ def test_refs_mixed(t: CompressionTester) {
324+ var heap_obj = HeapObject.new(null, []);
325+ var host_obj = HostObject.new();
326+ var host_fn = HostFunction.new("test_fn", SigCache.v_v, nop_host);
327+ var vals: Array<Value> = [
328+ Value.Ref(heap_obj),
329+ Value.Ref(host_obj),
330+ Value.Ref(host_fn),
331+ Value.Ref(null),
332+ Value.Ref(heap_obj), // same object again
333+ Value.Ref(host_obj) // same object again
334+ ];
335+ var frames = [t.make_frame(0, vals)];
336+ var got = t.roundtrip(frames);
337+ t.assert_length(1, got.length, "frames");
338+ t.assert_length(vals.length, got[0].vals.length, "values");
339+ // Verify identity for each ref.
340+ for (i < vals.length) {
341+ match (vals[i]) {
342+ Ref(expected) => match (got[0].vals[i]) {
343+ Ref(actual) => if (expected != actual) t.t.fail1("ref[%d]: identity not preserved", i);
344+ _ => t.t.fail1("ref[%d]: expected Ref", i);
345+ }
346+ _ => ;
347+ }
348+ }
349+ }
350+
351+ def nop_host(args: Range<Value>) -> HostResult { return HostResult.Value0; }
352+
353+ // Shared reference objects across multiple frames.
354+ def test_refs_shared_across_frames(t: CompressionTester) {
355+ var obj_a = HeapObject.new(null, [Value.I32(1)]);
356+ var obj_b = HostObject.new();
357+ var frames = [
358+ t.make_frame(0, [Value.Ref(obj_a), Value.I32(10)]),
359+ t.make_frame(1, [Value.Ref(obj_b), Value.Ref(obj_a)]),
360+ t.make_frame(2, [Value.Ref(obj_a), Value.Ref(obj_b), Value.Ref(null)])
361+ ];
362+ var got = t.roundtrip(frames);
363+ t.assert_frames_eq(frames, got);
364+ // Verify cross-frame identity: obj_a in frame 0 == obj_a in frame 1 and 2.
365+ var get_ref = get_ref_val;
366+ var a0 = get_ref(got[0].vals[0]);
367+ var a1 = get_ref(got[1].vals[1]);
368+ var a2 = get_ref(got[2].vals[0]);
369+ if (a0 != a1) t.t.fail("obj_a identity not preserved across frames 0 and 1");
370+ if (a0 != a2) t.t.fail("obj_a identity not preserved across frames 0 and 2");
371+ var b1 = get_ref(got[1].vals[0]);
372+ var b2 = get_ref(got[2].vals[1]);
373+ if (b1 != b2) t.t.fail("obj_b identity not preserved across frames 1 and 2");
374+ }
375+
376+ def get_ref_val(v: Value) -> Object {
377+ match (v) {
378+ Ref(obj) => return obj;
379+ _ => return null;
380+ }
381+ }
382+
383+ // Many frames with uniform large value counts.
384+ def test_large_uniform_frames(t: CompressionTester) {
385+ var n_frames = 20;
386+ var n_vals = 50;
387+ var frames = Array<RelocatableFrame>.new(n_frames);
388+ for (i < n_frames) {
389+ var vals = Array<Value>.new(n_vals);
390+ for (j < n_vals) vals[j] = Value.I64(u64.view(i * n_vals + j));
391+ frames[i] = t.make_frame(i, vals);
392+ }
393+ var got = t.roundtrip(frames);
394+ t.assert_frames_eq(frames, got);
395+ }
0 commit comments