package protobufs import ( "bytes" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestHypergraphConfiguration_Serialization(t *testing.T) { tests := []struct { name string config *HypergraphConfiguration }{ { name: "complete configuration", config: &HypergraphConfiguration{ ReadPublicKey: make([]byte, 57), // Ed448 key WritePublicKey: make([]byte, 57), // Ed448 key }, }, { name: "empty keys", config: &HypergraphConfiguration{ ReadPublicKey: []byte{}, WritePublicKey: []byte{}, }, }, { name: "different keys", config: &HypergraphConfiguration{ ReadPublicKey: append([]byte{0x01}, make([]byte, 56)...), WritePublicKey: append([]byte{0x02}, make([]byte, 56)...), }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Test serialization data, err := tt.config.ToCanonicalBytes() require.NoError(t, err) require.NotNil(t, data) // Test deserialization config2 := &HypergraphConfiguration{} err = config2.FromCanonicalBytes(data) require.NoError(t, err) // Compare assert.Equal(t, tt.config.ReadPublicKey, config2.ReadPublicKey) assert.Equal(t, tt.config.WritePublicKey, config2.WritePublicKey) }) } } func TestHypergraphDeploy_Serialization(t *testing.T) { tests := []struct { name string deploy *HypergraphDeploy }{ { name: "complete deploy", deploy: &HypergraphDeploy{ Config: &HypergraphConfiguration{ ReadPublicKey: make([]byte, 57), WritePublicKey: make([]byte, 57), }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Test serialization data, err := tt.deploy.ToCanonicalBytes() require.NoError(t, err) require.NotNil(t, data) // Test deserialization deploy2 := &HypergraphDeploy{} err = deploy2.FromCanonicalBytes(data) require.NoError(t, err) // Compare require.NotNil(t, deploy2.Config) assert.Equal(t, tt.deploy.Config.ReadPublicKey, deploy2.Config.ReadPublicKey) assert.Equal(t, tt.deploy.Config.WritePublicKey, deploy2.Config.WritePublicKey) }) } } func TestVertexAdd_Serialization(t *testing.T) { tests := []struct { name string vertex *VertexAdd }{ { name: "complete vertex", vertex: &VertexAdd{ Domain: make([]byte, 32), DataAddress: make([]byte, 32), Data: []byte("test vector commitment tree data"), Signature: make([]byte, 114), // Ed448 signature }, }, { name: "minimal vertex", vertex: &VertexAdd{ Domain: make([]byte, 32), DataAddress: make([]byte, 32), Data: []byte{0x01}, Signature: []byte{}, }, }, { name: "large data", vertex: &VertexAdd{ Domain: make([]byte, 32), DataAddress: make([]byte, 32), Data: make([]byte, 1024), // Large data blob Signature: make([]byte, 114), }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Test serialization data, err := tt.vertex.ToCanonicalBytes() require.NoError(t, err) require.NotNil(t, data) // Test deserialization vertex2 := &VertexAdd{} err = vertex2.FromCanonicalBytes(data) require.NoError(t, err) // Compare assert.Equal(t, tt.vertex.Domain, vertex2.Domain) assert.Equal(t, tt.vertex.DataAddress, vertex2.DataAddress) assert.Equal(t, tt.vertex.Data, vertex2.Data) assert.Equal(t, tt.vertex.Signature, vertex2.Signature) }) } } func TestVertexRemove_Serialization(t *testing.T) { tests := []struct { name string vertex *VertexRemove }{ { name: "complete vertex remove", vertex: &VertexRemove{ Domain: make([]byte, 32), DataAddress: make([]byte, 32), Signature: make([]byte, 114), }, }, { name: "empty signature", vertex: &VertexRemove{ Domain: make([]byte, 32), DataAddress: make([]byte, 32), Signature: []byte{}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Test serialization data, err := tt.vertex.ToCanonicalBytes() require.NoError(t, err) require.NotNil(t, data) // Test deserialization vertex2 := &VertexRemove{} err = vertex2.FromCanonicalBytes(data) require.NoError(t, err) // Compare assert.Equal(t, tt.vertex.Domain, vertex2.Domain) assert.Equal(t, tt.vertex.DataAddress, vertex2.DataAddress) assert.Equal(t, tt.vertex.Signature, vertex2.Signature) }) } } func TestHyperedgeAdd_Serialization(t *testing.T) { tests := []struct { name string hyperedge *HyperedgeAdd }{ { name: "complete hyperedge", hyperedge: &HyperedgeAdd{ Domain: make([]byte, 32), Value: []byte("hyperedge value data"), Signature: make([]byte, 114), }, }, { name: "minimal hyperedge", hyperedge: &HyperedgeAdd{ Domain: make([]byte, 32), Value: []byte{0x01}, Signature: []byte{}, }, }, { name: "large value", hyperedge: &HyperedgeAdd{ Domain: make([]byte, 32), Value: make([]byte, 2048), Signature: make([]byte, 114), }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Test serialization data, err := tt.hyperedge.ToCanonicalBytes() require.NoError(t, err) require.NotNil(t, data) // Test deserialization hyperedge2 := &HyperedgeAdd{} err = hyperedge2.FromCanonicalBytes(data) require.NoError(t, err) // Compare assert.Equal(t, tt.hyperedge.Domain, hyperedge2.Domain) assert.Equal(t, tt.hyperedge.Value, hyperedge2.Value) assert.Equal(t, tt.hyperedge.Signature, hyperedge2.Signature) }) } } func TestHyperedgeRemove_Serialization(t *testing.T) { tests := []struct { name string hyperedge *HyperedgeRemove }{ { name: "complete hyperedge remove", hyperedge: &HyperedgeRemove{ Domain: make([]byte, 32), Value: []byte("hyperedge value to remove"), Signature: make([]byte, 114), }, }, { name: "minimal value", hyperedge: &HyperedgeRemove{ Domain: make([]byte, 32), Value: []byte{0x01}, Signature: []byte{}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Test serialization data, err := tt.hyperedge.ToCanonicalBytes() require.NoError(t, err) require.NotNil(t, data) // Test deserialization hyperedge2 := &HyperedgeRemove{} err = hyperedge2.FromCanonicalBytes(data) require.NoError(t, err) // Compare assert.Equal(t, tt.hyperedge.Domain, hyperedge2.Domain) assert.Equal(t, tt.hyperedge.Value, hyperedge2.Value) assert.Equal(t, tt.hyperedge.Signature, hyperedge2.Signature) }) } } func TestHypergraphTypes_Validation(t *testing.T) { t.Run("HypergraphConfiguration validation", func(t *testing.T) { // Valid configuration config := &HypergraphConfiguration{ ReadPublicKey: make([]byte, 57), WritePublicKey: make([]byte, 57), } assert.NoError(t, config.Validate()) // Invalid read key length config.ReadPublicKey = make([]byte, 56) assert.Error(t, config.Validate()) // Invalid write key length config.ReadPublicKey = make([]byte, 57) config.WritePublicKey = make([]byte, 58) assert.Error(t, config.Validate()) // Nil configuration var nilConfig *HypergraphConfiguration assert.Error(t, nilConfig.Validate()) }) t.Run("HypergraphDeploy validation", func(t *testing.T) { // Valid deploy deploy := &HypergraphDeploy{ Config: &HypergraphConfiguration{ ReadPublicKey: make([]byte, 57), WritePublicKey: make([]byte, 57), }, } assert.NoError(t, deploy.Validate()) // Nil config deploy.Config = nil assert.Error(t, deploy.Validate()) // Invalid config deploy.Config = &HypergraphConfiguration{ ReadPublicKey: make([]byte, 56), WritePublicKey: make([]byte, 57), } assert.Error(t, deploy.Validate()) }) t.Run("VertexAdd validation", func(t *testing.T) { // Valid vertex vertex := &VertexAdd{ Domain: make([]byte, 32), DataAddress: make([]byte, 32), Data: []byte("test"), Signature: make([]byte, 114), } assert.NoError(t, vertex.Validate()) // Invalid domain length vertex.Domain = make([]byte, 31) assert.Error(t, vertex.Validate()) // Invalid data address length vertex.Domain = make([]byte, 32) vertex.DataAddress = make([]byte, 33) assert.Error(t, vertex.Validate()) // Empty data vertex.DataAddress = make([]byte, 32) vertex.Data = []byte{} assert.Error(t, vertex.Validate()) // Empty signature vertex.Data = []byte("test") vertex.Signature = []byte{} assert.Error(t, vertex.Validate()) }) t.Run("VertexRemove validation", func(t *testing.T) { // Valid vertex remove vertex := &VertexRemove{ Domain: make([]byte, 32), DataAddress: make([]byte, 32), Signature: make([]byte, 114), } assert.NoError(t, vertex.Validate()) // Invalid domain length vertex.Domain = make([]byte, 31) assert.Error(t, vertex.Validate()) // Empty signature vertex.Domain = make([]byte, 32) vertex.Signature = []byte{} assert.Error(t, vertex.Validate()) }) t.Run("HyperedgeAdd validation", func(t *testing.T) { // Valid hyperedge hyperedge := &HyperedgeAdd{ Domain: make([]byte, 32), Value: []byte("test"), Signature: make([]byte, 114), } assert.NoError(t, hyperedge.Validate()) // Invalid domain length hyperedge.Domain = make([]byte, 31) assert.Error(t, hyperedge.Validate()) // Empty value hyperedge.Domain = make([]byte, 32) hyperedge.Value = []byte{} assert.Error(t, hyperedge.Validate()) // Empty signature hyperedge.Value = []byte("test") hyperedge.Signature = []byte{} assert.Error(t, hyperedge.Validate()) }) t.Run("HyperedgeRemove validation", func(t *testing.T) { // Valid hyperedge remove hyperedge := &HyperedgeRemove{ Domain: make([]byte, 32), Value: []byte("test"), Signature: make([]byte, 114), } assert.NoError(t, hyperedge.Validate()) // Invalid domain length hyperedge.Domain = make([]byte, 31) assert.Error(t, hyperedge.Validate()) // Empty value hyperedge.Domain = make([]byte, 32) hyperedge.Value = []byte{} assert.Error(t, hyperedge.Validate()) }) } func TestHypergraphSerialization_RoundTrip(t *testing.T) { // Test that serialize -> deserialize -> serialize produces the same bytes config := &HypergraphConfiguration{ ReadPublicKey: randomBytes(t, 57), WritePublicKey: randomBytes(t, 57), } // First serialization data1, err := config.ToCanonicalBytes() require.NoError(t, err) // Deserialize config2 := &HypergraphConfiguration{} err = config2.FromCanonicalBytes(data1) require.NoError(t, err) // Second serialization data2, err := config2.ToCanonicalBytes() require.NoError(t, err) // Should be identical assert.Equal(t, data1, data2) } func TestHypergraphUpdate_Serialization(t *testing.T) { tests := []struct { name string update *HypergraphUpdate }{ { name: "complete hypergraph update", update: &HypergraphUpdate{ Config: &HypergraphConfiguration{ ReadPublicKey: make([]byte, 57), WritePublicKey: make([]byte, 57), }, RdfSchema: []byte("@prefix ex: . ex:Thing a ex:Class ."), PublicKeySignatureBls48581: &BLS48581AggregateSignature{ Signature: make([]byte, 74), // BLS48-581 aggregate signature size PublicKey: &BLS48581G2PublicKey{ KeyValue: make([]byte, 585), // BLS48-581 G2 public key size }, Bitmask: make([]byte, 32), }, }, }, { name: "update with config only", update: &HypergraphUpdate{ Config: &HypergraphConfiguration{ ReadPublicKey: append([]byte{0xAA}, make([]byte, 56)...), WritePublicKey: append([]byte{0xBB}, make([]byte, 56)...), }, RdfSchema: []byte{}, PublicKeySignatureBls48581: &BLS48581AggregateSignature{ Signature: append([]byte{0xCC}, make([]byte, 73)...), PublicKey: &BLS48581G2PublicKey{ KeyValue: append([]byte{0xDD}, make([]byte, 584)...), }, Bitmask: append([]byte{0xEE}, make([]byte, 31)...), }, }, }, { name: "update with schema only", update: &HypergraphUpdate{ Config: nil, RdfSchema: []byte("@prefix rdfs: ."), PublicKeySignatureBls48581: &BLS48581AggregateSignature{ Signature: make([]byte, 74), PublicKey: &BLS48581G2PublicKey{ KeyValue: make([]byte, 585), }, Bitmask: make([]byte, 32), }, }, }, { name: "minimal update", update: &HypergraphUpdate{ Config: nil, RdfSchema: []byte{}, PublicKeySignatureBls48581: nil, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Test serialization data, err := tt.update.ToCanonicalBytes() require.NoError(t, err) require.NotNil(t, data) // Test deserialization update2 := &HypergraphUpdate{} err = update2.FromCanonicalBytes(data) require.NoError(t, err) // Compare basic fields assert.Equal(t, true, bytes.Equal(tt.update.RdfSchema, update2.RdfSchema)) // Compare Config if present if tt.update.Config != nil { assert.NotNil(t, update2.Config) assert.Equal(t, tt.update.Config.ReadPublicKey, update2.Config.ReadPublicKey) assert.Equal(t, tt.update.Config.WritePublicKey, update2.Config.WritePublicKey) } else { assert.Nil(t, update2.Config) } // Compare signature if present if tt.update.PublicKeySignatureBls48581 != nil { assert.NotNil(t, update2.PublicKeySignatureBls48581) assert.Equal(t, tt.update.PublicKeySignatureBls48581.Signature, update2.PublicKeySignatureBls48581.Signature) assert.Equal(t, tt.update.PublicKeySignatureBls48581.Bitmask, update2.PublicKeySignatureBls48581.Bitmask) if tt.update.PublicKeySignatureBls48581.PublicKey != nil { assert.NotNil(t, update2.PublicKeySignatureBls48581.PublicKey) assert.Equal(t, tt.update.PublicKeySignatureBls48581.PublicKey.KeyValue, update2.PublicKeySignatureBls48581.PublicKey.KeyValue) } else { assert.Nil(t, update2.PublicKeySignatureBls48581.PublicKey) } } else { assert.Nil(t, update2.PublicKeySignatureBls48581) } }) } }