]> git.giacomolli.uk - onehouse/blob - protocol/envelope_test.go
Define wire addresses and envelopes
[onehouse] / protocol / envelope_test.go
1 package protocol
2
3 import (
4 "strings"
5 "testing"
6 "time"
7
8 "github.com/stretchr/testify/require"
9 )
10
11 func TestEnvelopeRoundTripPreservesMetadata(t *testing.T) {
12 now := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
13 metadata := Metadata{MessageID: messageID, SentAt: &now, ExpiresAt: &now, CorrelationID: commandID, CausationID: deviceID}
14 data, err := EncodeEnvelope(metadata, map[string]bool{"value": true})
15 require.NoError(t, err)
16
17 envelope, err := ParseEnvelope(data)
18 require.NoError(t, err)
19 require.Equal(t, Schema, envelope.Schema)
20 require.Equal(t, metadata, envelope.Metadata)
21 require.JSONEq(t, `{"value":true}`, string(envelope.Payload))
22 require.Equal(t, 5*time.Minute, MeasurementRepeatInterval)
23 require.Equal(t, 5*time.Minute, OnlineRepeatInterval)
24 require.Equal(t, 15*time.Minute, DeviceContactTimeout)
25 }
26
27 func TestEnvelopeRejectsInvalidWireData(t *testing.T) {
28 valid := `{"schema":1,"message_id":"` + messageID + `","payload":{}}`
29
30 testCases := []struct {
31 name string
32 data string
33 }{
34 {name: "rejects unsupported schema", data: strings.Replace(valid, `"schema":1`, `"schema":2`, 1)},
35 {name: "rejects unknown fields", data: strings.Replace(valid, `"payload":{}`, `"payload":{},"extra":true`, 1)},
36 {name: "rejects missing payload", data: `{"schema":1,"message_id":"` + messageID + `"}`},
37 {name: "rejects null payload", data: strings.Replace(valid, `"payload":{}`, `"payload":null`, 1)},
38 {name: "rejects non-object payload", data: strings.Replace(valid, `"payload":{}`, `"payload":[]`, 1)},
39 {name: "rejects missing identity", data: `{"schema":1,"payload":{}}`},
40 {name: "rejects invalid correlation", data: strings.Replace(valid, `"payload":{}`, `"payload":{},"correlation_id":"bad"`, 1)},
41 {name: "rejects invalid causation", data: strings.Replace(valid, `"payload":{}`, `"payload":{},"causation_id":"bad"`, 1)},
42 {name: "rejects non-UTC time", data: strings.Replace(valid, `"payload":{}`, `"payload":{},"sent_at":"2026-01-01T01:00:00+01:00"`, 1)},
43 {name: "rejects invalid expiry", data: strings.Replace(valid, `"payload":{}`, `"payload":{},"expires_at":"bad"`, 1)},
44 {name: "rejects trailing JSON", data: valid + `{}`},
45 }
46 for _, tc := range testCases {
47 t.Run(tc.name, func(t *testing.T) {
48 _, err := ParseEnvelope([]byte(tc.data))
49 require.Error(t, err)
50 })
51 }
52
53 _, err := EncodeEnvelope(Metadata{MessageID: "bad"}, map[string]bool{})
54 require.Error(t, err)
55
56 _, err = EncodeEnvelope(Metadata{MessageID: messageID}, make(chan int))
57 require.Error(t, err)
58
59 _, err = EncodeEnvelope(Metadata{MessageID: messageID}, []int{1})
60 require.Error(t, err)
61 }