github.com/hamba/avro/v2@v2.22.1-0.20240518180522-aff3955acf7d/protocol_test.go (about) 1 package avro_test 2 3 import ( 4 "testing" 5 6 "github.com/hamba/avro/v2" 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 ) 10 11 func TestMustParseProtocol(t *testing.T) { 12 proto := avro.MustParseProtocol(`{"protocol":"test", "namespace": "org.hamba.avro", "doc": "docs"}`) 13 14 assert.IsType(t, &avro.Protocol{}, proto) 15 } 16 17 func TestMustParseProtocol_PanicsOnError(t *testing.T) { 18 assert.Panics(t, func() { 19 avro.MustParseProtocol("123") 20 }) 21 } 22 23 func TestNewProtocol_ValidatesName(t *testing.T) { 24 _, err := avro.NewProtocol("0test", "", nil, nil) 25 26 assert.Error(t, err) 27 } 28 29 func TestNewMessage(t *testing.T) { 30 field, _ := avro.NewField("test", avro.NewPrimitiveSchema(avro.String, nil)) 31 fields := []*avro.Field{field} 32 req, _ := avro.NewRecordSchema("test", "", fields) 33 resp := avro.NewPrimitiveSchema(avro.String, nil) 34 types := []avro.Schema{avro.NewPrimitiveSchema(avro.String, nil)} 35 errs, _ := avro.NewUnionSchema(types) 36 37 msg := avro.NewMessage(req, resp, errs, false) 38 39 assert.Equal(t, req, msg.Request()) 40 assert.Equal(t, resp, msg.Response()) 41 assert.Equal(t, errs, msg.Errors()) 42 assert.False(t, msg.OneWay()) 43 } 44 45 func TestParseProtocol(t *testing.T) { 46 tests := []struct { 47 name string 48 schema string 49 wantErr assert.ErrorAssertionFunc 50 }{ 51 { 52 name: "Valid", 53 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "doc": "docs"}`, 54 wantErr: assert.NoError, 55 }, 56 { 57 name: "Invalid Json", 58 schema: `{`, 59 wantErr: assert.Error, 60 }, 61 { 62 name: "Invalid Name First Char", 63 schema: `{"protocol":"0test", "namespace": "org.hamba.avro"}`, 64 wantErr: assert.Error, 65 }, 66 { 67 name: "Invalid Name Other Char", 68 schema: `{"protocol":"test+", "namespace": "org.hamba.avro"}`, 69 wantErr: assert.Error, 70 }, 71 { 72 name: "Empty Name", 73 schema: `{"protocol":"", "namespace": "org.hamba.avro"}`, 74 wantErr: assert.Error, 75 }, 76 { 77 name: "No Name", 78 schema: `{"namespace": "org.hamba.avro"}`, 79 wantErr: assert.Error, 80 }, 81 { 82 name: "Invalid Namespace", 83 schema: `{"protocol":"test", "namespace": "org.hamba.avro+"}`, 84 wantErr: assert.Error, 85 }, 86 { 87 name: "Empty Namespace", 88 schema: `{"protocol":"test", "namespace": ""}`, 89 wantErr: assert.Error, 90 }, 91 { 92 name: "Invalid Type Schema", 93 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "types":["test"]}`, 94 wantErr: assert.Error, 95 }, 96 { 97 name: "Type Not Named Schema", 98 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "types":["string"]}`, 99 wantErr: assert.Error, 100 }, 101 { 102 name: "Message Not Object", 103 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "messages":{"test":["test"]}}`, 104 wantErr: assert.Error, 105 }, 106 { 107 name: "Message Request Invalid Request Json", 108 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "messages":{"test":{"request": "test"}}}`, 109 wantErr: assert.Error, 110 }, 111 { 112 name: "Message Request Invalid Field", 113 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "messages":{"test":{"request": [{"name": "foobar"}]}}}`, 114 wantErr: assert.Error, 115 }, 116 { 117 name: "Message Response Invalid Schema", 118 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "messages":{"test":{"request": [{"name": "foobar", "type": "string"}], "response": "test"}}}`, 119 wantErr: assert.Error, 120 }, 121 { 122 name: "Message Errors Invalid Schema", 123 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "messages":{"test":{"request": [{"name": "foobar", "type": "string"}], "errors": ["test"]}}}`, 124 wantErr: assert.Error, 125 }, 126 { 127 name: "Message Errors Record Not Error Schema", 128 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "messages":{"test":{"request": [{"name": "foobar", "type": "string"}], "errors": [{"type":"record", "name":"test", "fields":[{"name": "field", "type": "int"}]}]}}}`, 129 wantErr: assert.Error, 130 }, 131 { 132 name: "Message Errors Duplicate Schema", 133 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "messages":{"test":{"request": [{"name": "foobar", "type": "string"}], "errors": ["string"]}}}`, 134 wantErr: assert.Error, 135 }, 136 { 137 name: "Message One Way Invalid", 138 schema: `{"protocol":"test", "namespace": "org.hamba.avro", "messages":{"test":{"request": [{"name": "foobar", "type": "string"}], "errors": ["int"], "one-way": true}}}`, 139 wantErr: assert.Error, 140 }, 141 } 142 143 for _, test := range tests { 144 test := test 145 t.Run(test.name, func(t *testing.T) { 146 _, err := avro.ParseProtocol(test.schema) 147 148 test.wantErr(t, err) 149 }) 150 } 151 } 152 153 func TestParseProtocol_DeterminesOneWayMessage(t *testing.T) { 154 schema := `{"protocol":"test", "namespace": "org.hamba.avro", "messages":{"test":{"request": [{"name": "foobar", "type": "string"}]}}}` 155 156 proto, err := avro.ParseProtocol(schema) 157 158 require.NoError(t, err) 159 160 msg := proto.Message("test") 161 require.NotNil(t, msg) 162 assert.True(t, msg.OneWay()) 163 } 164 165 func TestParseProtocol_Docs(t *testing.T) { 166 schema := `{"protocol":"test", "doc": "foo", "messages":{"test":{"request": [{"name": "foobar", "type": "string"}], "doc": "bar"}}}` 167 168 proto, err := avro.ParseProtocol(schema) 169 require.NoError(t, err) 170 171 assert.Equal(t, "foo", proto.Doc()) 172 173 msg := proto.Message("test") 174 require.NotNil(t, msg) 175 assert.Equal(t, "bar", msg.Doc()) 176 } 177 178 func TestParseProtocolFile(t *testing.T) { 179 protocol, err := avro.ParseProtocolFile("testdata/echo.avpr") 180 181 want := `{"protocol":"Echo","namespace":"org.hamba.avro","types":[{"name":"org.hamba.avro.Ping","type":"record","fields":[{"name":"timestamp","type":"long"},{"name":"text","type":"string"}]},{"name":"org.hamba.avro.Pong","type":"record","fields":[{"name":"timestamp","type":"long"},{"name":"ping","type":"org.hamba.avro.Ping"}]},{"name":"org.hamba.avro.PongError","type":"error","fields":[{"name":"timestamp","type":"long"},{"name":"reason","type":"string"}]}],"messages":{"ping":{"request":[{"name":"ping","type":"org.hamba.avro.Ping"}],"response":"org.hamba.avro.Pong","errors":["org.hamba.avro.PongError"]}}}` 182 wantMD5 := "5bc594ae86fc8c209f553ce3bc4291a5" 183 require.NoError(t, err) 184 assert.Equal(t, want, protocol.String()) 185 assert.Equal(t, wantMD5, protocol.Hash()) 186 } 187 188 func TestParseProtocolFile_InvalidPath(t *testing.T) { 189 _, err := avro.ParseProtocolFile("test.avpr") 190 191 assert.Error(t, err) 192 } 193 194 func TestParseProtocol_Types(t *testing.T) { 195 protocol, err := avro.ParseProtocolFile("testdata/echo.avpr") 196 197 wantPing := `{"name":"org.hamba.avro.Ping","type":"record","fields":[{"name":"timestamp","type":"long"},{"name":"text","type":"string"}]}` 198 wantPong := `{"name":"org.hamba.avro.Pong","type":"record","fields":[{"name":"timestamp","type":"long"},{"name":"ping","type":"org.hamba.avro.Ping"}]}` 199 wantPongError := `{"name":"org.hamba.avro.PongError","type":"error","fields":[{"name":"timestamp","type":"long"},{"name":"reason","type":"string"}]}` 200 wantLen := 3 201 require.NoError(t, err) 202 assert.Equal(t, wantLen, len(protocol.Types())) 203 assert.Equal(t, wantPing, protocol.Types()[0].String()) 204 assert.Equal(t, wantPong, protocol.Types()[1].String()) 205 assert.Equal(t, wantPongError, protocol.Types()[2].String()) 206 }