From 47b6d473f30fcdc9fe4fe32437a4675fb0a165cf Mon Sep 17 00:00:00 2001 From: jonny rhea <5555162+jrhea@users.noreply.github.com> Date: Mon, 16 Mar 2026 10:45:24 -0500 Subject: [PATCH] beacon/engine: add marshal_bap_list tests --- beacon/engine/marshal_bap_list_test.go | 227 +++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 beacon/engine/marshal_bap_list_test.go diff --git a/beacon/engine/marshal_bap_list_test.go b/beacon/engine/marshal_bap_list_test.go new file mode 100644 index 0000000000..48d3cc65bb --- /dev/null +++ b/beacon/engine/marshal_bap_list_test.go @@ -0,0 +1,227 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package engine + +import ( + "bytes" + "encoding/json" + "reflect" + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" +) + +// canonicalBlobAndProofV1 is a reference type for BlobAndProofV1 that uses +// standard json.Marshal (no custom MarshalJSON). +type canonicalBlobAndProofV1 struct { + Blob hexutil.Bytes `json:"blob"` + Proof hexutil.Bytes `json:"proof"` +} + +// canonicalBlobAndProofV2 is a reference type for BlobAndProofV2 that uses +// standard json.Marshal (no custom MarshalJSON). +type canonicalBlobAndProofV2 struct { + Blob hexutil.Bytes `json:"blob"` + CellProofs []hexutil.Bytes `json:"proofs"` +} + +func toCanonicalBlobAndProofListV1(list BlobAndProofListV1) []*canonicalBlobAndProofV1 { + canonical := make([]*canonicalBlobAndProofV1, len(list)) + for i, item := range list { + if item == nil { + continue + } + canonical[i] = &canonicalBlobAndProofV1{ + Blob: item.Blob, + Proof: item.Proof, + } + } + return canonical +} + +func toCanonicalBlobAndProofListV2(list BlobAndProofListV2) []*canonicalBlobAndProofV2 { + canonical := make([]*canonicalBlobAndProofV2, len(list)) + for i, item := range list { + if item == nil { + continue + } + canonical[i] = &canonicalBlobAndProofV2{ + Blob: item.Blob, + CellProofs: item.CellProofs, + } + } + return canonical +} + +func TestBlobAndProofListV1MarshalJSON(t *testing.T) { + tests := []struct { + name string + list BlobAndProofListV1 + }{ + { + name: "multiple items", + list: BlobAndProofListV1{ + { + Blob: hexutil.Bytes{0x01, 0x02}, + Proof: hexutil.Bytes{0x03, 0x04}, + }, + { + Blob: hexutil.Bytes{}, + Proof: hexutil.Bytes{0x05}, + }, + }, + }, + { + name: "nil item", + list: BlobAndProofListV1{ + nil, + { + Blob: hexutil.Bytes{0xaa}, + Proof: hexutil.Bytes{0xbb}, + }, + }, + }, + { + name: "empty list", + list: BlobAndProofListV1{}, + }, + { + name: "nil list", + list: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.list.MarshalJSON() + if err != nil { + t.Fatalf("MarshalJSON error: %v", err) + } + want, err := json.Marshal(toCanonicalBlobAndProofListV1(tt.list)) + if err != nil { + t.Fatalf("canonical marshal error: %v", err) + } + if !bytes.Equal(compactJSON(got), compactJSON(want)) { + t.Errorf("JSON mismatch\ngot: %s\nwant: %s", got, want) + } + }) + } +} + +func TestBlobAndProofListV2MarshalJSON(t *testing.T) { + tests := []struct { + name string + list BlobAndProofListV2 + }{ + { + name: "multiple items", + list: BlobAndProofListV2{ + { + Blob: hexutil.Bytes{0x01, 0x02}, + CellProofs: []hexutil.Bytes{{0x03, 0x04}, {0x05}}, + }, + { + Blob: hexutil.Bytes{}, + CellProofs: []hexutil.Bytes{}, + }, + }, + }, + { + name: "nil item", + list: BlobAndProofListV2{ + nil, + { + Blob: hexutil.Bytes{0xaa}, + CellProofs: []hexutil.Bytes{{0xbb}}, + }, + }, + }, + { + name: "nil proofs slice", + list: BlobAndProofListV2{ + { + Blob: hexutil.Bytes{0xcc}, + CellProofs: nil, + }, + }, + }, + { + name: "empty list", + list: BlobAndProofListV2{}, + }, + { + name: "nil list", + list: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.list.MarshalJSON() + if err != nil { + t.Fatalf("MarshalJSON error: %v", err) + } + want, err := json.Marshal(toCanonicalBlobAndProofListV2(tt.list)) + if err != nil { + t.Fatalf("canonical marshal error: %v", err) + } + if !bytes.Equal(compactJSON(got), compactJSON(want)) { + t.Errorf("JSON mismatch\ngot: %s\nwant: %s", got, want) + } + }) + } +} + +func TestBlobAndProofFieldCoverage(t *testing.T) { + tests := []struct { + name string + typ reflect.Type + expected []string + }{ + { + name: "BlobAndProofV1", + typ: reflect.TypeOf(BlobAndProofV1{}), + expected: []string{ + "Blob", + "Proof", + }, + }, + { + name: "BlobAndProofV2", + typ: reflect.TypeOf(BlobAndProofV2{}), + expected: []string{ + "Blob", + "CellProofs", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.typ.NumField() != len(tt.expected) { + t.Fatalf("%s has %d fields, expected %d; update marshal_bap_list.go", + tt.name, tt.typ.NumField(), len(tt.expected)) + } + for i, name := range tt.expected { + if tt.typ.Field(i).Name != name { + t.Errorf("field %d: got %q, want %q; update marshal_bap_list.go", + i, tt.typ.Field(i).Name, name) + } + } + }) + } +}