package frame import ( "bytes" "testing" ) func TestMarshalUnmarshalRoundTrip(t *testing.T) { orig := Frame{ Type: PUB, Subject: "room.general", Sender: "abc123", MsgID: "01J000000000000000000000", Epoch: 3, Nonce: []byte{1, 2, 3, 4}, Payload: []byte("ciphertext-bytes"), Blob: &BlobRef{Hash: "deadbeef", Nonce: []byte{9, 8, 7}, Size: 42}, Sig: []byte{0xaa, 0xbb}, } b, err := orig.Marshal() if err != nil { t.Fatalf("Marshal: %v", err) } got, err := Unmarshal(b) if err != nil { t.Fatalf("Unmarshal: %v", err) } if got.Type != orig.Type || got.Subject != orig.Subject || got.Sender != orig.Sender || got.MsgID != orig.MsgID || got.Epoch != orig.Epoch { t.Fatalf("envelope mismatch: got %+v want %+v", got, orig) } if !bytes.Equal(got.Nonce, orig.Nonce) || !bytes.Equal(got.Payload, orig.Payload) || !bytes.Equal(got.Sig, orig.Sig) { t.Fatalf("byte fields mismatch") } if got.Blob == nil || got.Blob.Hash != orig.Blob.Hash || got.Blob.Size != orig.Blob.Size || !bytes.Equal(got.Blob.Nonce, orig.Blob.Nonce) { t.Fatalf("blob ref mismatch: %+v", got.Blob) } } func TestEndpointIDDeterministic(t *testing.T) { pub := []byte("some-ed25519-public-key-bytes-32") a := EndpointID(pub) b := EndpointID(pub) if a != b { t.Fatalf("EndpointID not deterministic: %q != %q", a, b) } if a == "" { t.Fatalf("EndpointID returned empty string") } // Different inputs must produce different ids. if EndpointID([]byte("other-key")) == a { t.Fatalf("EndpointID collision for different inputs") } } func TestSigningBytesExcludesSig(t *testing.T) { withSig := Frame{Type: PUB, Subject: "s", Sender: "x", MsgID: "id", Epoch: 1, Payload: []byte("p"), Sig: []byte{1, 2, 3}} noSig := withSig noSig.Sig = nil if !bytes.Equal(withSig.SigningBytes(), noSig.SigningBytes()) { t.Fatalf("SigningBytes should be identical regardless of Sig field") } // And SigningBytes must not be affected by mutating Sig afterward (value receiver). sb := withSig.SigningBytes() if bytes.Contains(sb, []byte{1, 2, 3}) { t.Fatalf("SigningBytes leaked the Sig bytes") } }