44	"encoding/binary" 
55	"encoding/json" 
66	"errors" 
7+ 	"math/big" 
78	"testing" 
89	"time" 
910
@@ -51,57 +52,93 @@ func TestGetValueSchemaType(t *testing.T) {
5152}
5253
5354var  (
54- 	testSchema1  =  `{"type": "record", "name": "cupcake", "fields": [{"name": "flavor", "type": "string"}, {"name": "created_date", "type": ["null",{"type": "long","logicalType": "timestamp-millis"}],"default": null}]}` 
55- 	testValue1   =  map [string ]interface {}{"flavor" : "chocolate" , "created_date" : float64 (time .Now ().UnixMilli ())}
56- 	invValue     =  map [string ]string {"xxx" : "chocolate" }
55+ 	now          =  time .Now ()
56+ 	testSchema1  =  `{ 
57+ 	"type": "record",  
58+ 	"name": "cupcake",  
59+ 	"fields": [ 
60+ 		{"name": "flavor", "type": "string"},  
61+ 		{"name": "weight", "type": {"type": "bytes", "logicalType": "decimal", "precision": 5, "scale": 2}},  
62+ 		{"name": "created_date", "type": ["null", {"type": "long", "logicalType": "timestamp-millis"}], "default": null} 
63+ 		] 
64+ 	}` 
65+ 	testValue1          =  map [string ]any {"flavor" : "chocolate" , "weight" : "100.24" , "created_date" : float64 (now .UnixMilli ())}
66+ 	testValue1AvroJSON  =  map [string ]any {"flavor" : "chocolate" , "weight" : big .NewRat (10024 , 100 ), "created_date" : goavro .Union ("long.timestamp-millis" , float64 (now .UnixMilli ()))}
67+ 	invValue            =  map [string ]string {"xxx" : "chocolate" }
5768)
5869
5970func  TestDeserializeValue (t  * testing.T ) {
60- 	registry  :=  srclient .CreateMockSchemaRegistryClient ("http://localhost:8081" )
61- 	schema , _  :=  registry .CreateSchema ("my-topic-value" , testSchema1 , srclient .Avro )
6271	handlerConfig  :=  SubscriptionHandlerConfig {
6372		IsBulkSubscribe : false ,
6473		ValueSchemaType : Avro ,
6574	}
66- 	k  :=  Kafka {
67- 		srClient :             registry ,
75+ 
76+ 	registryJSON  :=  srclient .CreateMockSchemaRegistryClient ("http://localhost:8081" )
77+ 	kJSON  :=  Kafka {
78+ 		srClient :             registryJSON ,
6879		schemaCachingEnabled : true ,
6980		logger :               logger .NewLogger ("kafka_test" ),
7081	}
82+ 	kJSON .srClient .CodecJsonEnabled (true )
83+ 	schemaJSON , _  :=  registryJSON .CreateSchema ("my-topic-value" , testSchema1 , srclient .Avro )
7184
72- 	schemaIDBytes  :=  make ([]byte , 4 )
73- 	binary .BigEndian .PutUint32 (schemaIDBytes , uint32 (schema .ID ())) //nolint:gosec 
74- 
75- 	valJSON , _  :=  json .Marshal (testValue1 )
85+ 	// set up for Standard JSON 
7686	codec , _  :=  goavro .NewCodecForStandardJSONFull (testSchema1 )
87+ 	valJSON , _  :=  json .Marshal (testValue1 )
7788	native , _ , _  :=  codec .NativeFromTextual (valJSON )
78- 	valueBytes , _  :=  codec .BinaryFromNative (nil , native )
89+ 	valueBytesFromJSON , _  :=  codec .BinaryFromNative (nil , native )
90+ 	recordValueFromJSON  :=  formatByteRecord (schemaJSON .ID (), valueBytesFromJSON )
7991
80- 	var  recordValue  []byte 
81- 	recordValue  =  append (recordValue , byte (0 ))
82- 	recordValue  =  append (recordValue , schemaIDBytes ... )
83- 	recordValue  =  append (recordValue , valueBytes ... )
92+ 	// setup for Avro JSON 
93+ 	registryAvroJSON  :=  srclient .CreateMockSchemaRegistryClient ("http://localhost:8081" )
94+ 	kAvroJSON  :=  Kafka {
95+ 		srClient :             registryAvroJSON ,
96+ 		schemaCachingEnabled : true ,
97+ 		logger :               logger .NewLogger ("kafka_test" ),
98+ 	}
99+ 	kAvroJSON .srClient .CodecJsonEnabled (false )
100+ 	schemaAvroJSON , _  :=  registryAvroJSON .CreateSchema ("my-topic-value" , testSchema1 , srclient .Avro )
101+ 
102+ 	codecAvroJSON , _  :=  goavro .NewCodec (testSchema1 )
103+ 	valueBytesFromAvroJSON , _  :=  codecAvroJSON .BinaryFromNative (nil , testValue1AvroJSON )
104+ 	valueAvroJSON , _  :=  codecAvroJSON .TextualFromNative (nil , testValue1AvroJSON )
105+ 	recordValueFromAvroJSON  :=  formatByteRecord (schemaAvroJSON .ID (), valueBytesFromAvroJSON )
84106
85107	t .Run ("Schema found, return value" , func (t  * testing.T ) {
86108		msg  :=  sarama.ConsumerMessage {
87109			Key :   []byte ("my_key" ),
88- 			Value : recordValue ,
110+ 			Value : recordValueFromJSON ,
89111			Topic : "my-topic" ,
90112		}
91- 		act , err  :=  k .DeserializeValue (& msg , handlerConfig )
113+ 		act , err  :=  kJSON .DeserializeValue (& msg , handlerConfig )
92114		var  actMap  map [string ]any 
93115		json .Unmarshal (act , & actMap )
94116		require .Equal (t , testValue1 , actMap )
95117		require .NoError (t , err )
96118	})
97119
120+ 	t .Run ("Schema found and useAvroJson, return value as Avro Json" , func (t  * testing.T ) {
121+ 		msg  :=  sarama.ConsumerMessage {
122+ 			Key :   []byte ("my_key" ),
123+ 			Value : recordValueFromAvroJSON ,
124+ 			Topic : "my-topic" ,
125+ 		}
126+ 
127+ 		actText , err  :=  kAvroJSON .DeserializeValue (& msg , handlerConfig )
128+ 		// test if flaky if comparing the textual version. Convert to native for comparison 
129+ 		exp , _ , _  :=  codecAvroJSON .NativeFromTextual (valueAvroJSON )
130+ 		act , _ , _  :=  codecAvroJSON .NativeFromTextual (actText )
131+ 		require .Equal (t , exp , act )
132+ 		require .NoError (t , err )
133+ 	})
134+ 
98135	t .Run ("Data null, return as JSON null" , func (t  * testing.T ) {
99136		msg  :=  sarama.ConsumerMessage {
100137			Key :   []byte ("my_key" ),
101138			Value : nil ,
102139			Topic : "my-topic" ,
103140		}
104- 		act , err  :=  k .DeserializeValue (& msg , handlerConfig )
141+ 		act , err  :=  kJSON .DeserializeValue (& msg , handlerConfig )
105142		require .Equal (t , []byte ("null" ), act )
106143		require .NoError (t , err )
107144	})
@@ -112,7 +149,7 @@ func TestDeserializeValue(t *testing.T) {
112149			Value : []byte ("xxxx" ),
113150			Topic : "my-topic" ,
114151		}
115- 		_ , err  :=  k .DeserializeValue (& msg , handlerConfig )
152+ 		_ , err  :=  kJSON .DeserializeValue (& msg , handlerConfig )
116153
117154		require .Error (t , err )
118155	})
@@ -123,23 +160,23 @@ func TestDeserializeValue(t *testing.T) {
123160			Value : []byte ("xxxxx" ),
124161			Topic : "my-topic" ,
125162		}
126- 		_ , err  :=  k .DeserializeValue (& msg , handlerConfig )
163+ 		_ , err  :=  kJSON .DeserializeValue (& msg , handlerConfig )
127164
128165		require .Error (t , err )
129166	})
130167
131168	t .Run ("Invalid data, return error" , func (t  * testing.T ) {
132169		var  invalidVal  []byte 
133170		invalidVal  =  append (invalidVal , byte (0 ))
134- 		invalidVal  =  append (invalidVal , schemaIDBytes ... )
171+ 		invalidVal  =  append (invalidVal , recordValueFromJSON [ 0 : 5 ] ... )
135172		invalidVal  =  append (invalidVal , []byte ("xxx" )... )
136173
137174		msg  :=  sarama.ConsumerMessage {
138175			Key :   []byte ("my_key" ),
139176			Value : invalidVal ,
140177			Topic : "my-topic" ,
141178		}
142- 		_ , err  :=  k .DeserializeValue (& msg , handlerConfig )
179+ 		_ , err  :=  kJSON .DeserializeValue (& msg , handlerConfig )
143180
144181		require .Error (t , err )
145182	})
@@ -151,14 +188,25 @@ func TestDeserializeValue(t *testing.T) {
151188		}
152189		msg  :=  sarama.ConsumerMessage {
153190			Key :   []byte ("my_key" ),
154- 			Value : recordValue ,
191+ 			Value : recordValueFromJSON ,
155192			Topic : "my-topic" ,
156193		}
157194		_ , err  :=  kInv .DeserializeValue (& msg , handlerConfig )
158195		require .Error (t , err , "schema registry details not set" )
159196	})
160197}
161198
199+ func  formatByteRecord (schemaID  int , valueBytes  []byte ) []byte  {
200+ 	schemaIDBytes  :=  make ([]byte , 4 )
201+ 	binary .BigEndian .PutUint32 (schemaIDBytes , uint32 (schemaID )) //nolint:gosec 
202+ 
203+ 	var  recordValue  []byte 
204+ 	recordValue  =  append (recordValue , byte (0 ))
205+ 	recordValue  =  append (recordValue , schemaIDBytes ... )
206+ 	recordValue  =  append (recordValue , valueBytes ... )
207+ 	return  recordValue 
208+ }
209+ 
162210func  assertValueSerialized (t  * testing.T , act  []byte , valJSON  []byte , schema  * srclient.Schema ) {
163211	require .NotEqual (t , act , valJSON )
164212
@@ -174,81 +222,101 @@ func assertValueSerialized(t *testing.T, act []byte, valJSON []byte, schema *src
174222}
175223
176224func  TestSerializeValueCachingDisabled (t  * testing.T ) {
177- 	registry  :=  srclient .CreateMockSchemaRegistryClient ("http://localhost:8081" )
178- 	schema , _  :=  registry .CreateSchema ("my-topic-value" , testSchema1 , srclient .Avro )
225+ 	registryJSON  :=  srclient .CreateMockSchemaRegistryClient ("http://localhost:8081" )
226+ 	registryJSON .CodecJsonEnabled (true )
227+ 	schemaJSON , _  :=  registryJSON .CreateSchema ("my-topic-value" , testSchema1 , srclient .Avro )
179228
180- 	k  :=  Kafka {
181- 		srClient :             registry ,
229+ 	schemaIDBytes  :=  make ([]byte , 4 )
230+ 	binary .BigEndian .PutUint32 (schemaIDBytes , uint32 (schemaJSON .ID ())) //nolint:gosec 
231+ 
232+ 	// set up for Avro JSON 
233+ 	registryAvroJSON  :=  srclient .CreateMockSchemaRegistryClient ("http://localhost:8081" )
234+ 	registryAvroJSON .CodecJsonEnabled (false )
235+ 	codecAvroJSON , _  :=  goavro .NewCodec (testSchema1 )
236+ 	schemaAvroJSON , _  :=  registryAvroJSON .CreateSchema ("my-topic-value" , testSchema1 , srclient .Avro )
237+ 	schemaAvroJSONIDBytes  :=  make ([]byte , 4 )
238+ 	binary .BigEndian .PutUint32 (schemaAvroJSONIDBytes , uint32 (schemaAvroJSON .ID ())) //nolint:gosec 
239+ 	valueBytesFromAvroJSON , _  :=  codecAvroJSON .BinaryFromNative (nil , testValue1AvroJSON )
240+ 	valueAvroJSON , _  :=  codecAvroJSON .TextualFromNative (nil , testValue1AvroJSON )
241+ 	var  recordValueFromAvroJSON  []byte 
242+ 	recordValueFromAvroJSON  =  append (recordValueFromAvroJSON , byte (0 ))
243+ 	recordValueFromAvroJSON  =  append (recordValueFromAvroJSON , schemaAvroJSONIDBytes ... )
244+ 	recordValueFromAvroJSON  =  append (recordValueFromAvroJSON , valueBytesFromAvroJSON ... )
245+ 
246+ 	kJSON  :=  Kafka {
247+ 		srClient :             registryJSON ,
248+ 		schemaCachingEnabled : false ,
249+ 		logger :               logger .NewLogger ("kafka_test" ),
250+ 	}
251+ 
252+ 	kAvroJSON  :=  Kafka {
253+ 		srClient :             registryAvroJSON ,
182254		schemaCachingEnabled : false ,
183255		logger :               logger .NewLogger ("kafka_test" ),
184256	}
185257
186258	t .Run ("valueSchemaType not set, leave value as is" , func (t  * testing.T ) {
187259		valJSON , _  :=  json .Marshal (testValue1 )
188- 
189- 		act , err  :=  k .SerializeValue ("my-topic" , valJSON , map [string ]string {})
190- 
260+ 		act , err  :=  kJSON .SerializeValue ("my-topic" , valJSON , map [string ]string {})
191261		require .JSONEq (t , string (valJSON ), string (act ))
192262		require .NoError (t , err )
193263	})
194264
195265	t .Run ("valueSchemaType set to None, leave value as is" , func (t  * testing.T ) {
196266		valJSON , _  :=  json .Marshal (testValue1 )
197- 
198- 		act , err  :=  k .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "None" })
199- 
267+ 		act , err  :=  kJSON .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "None" })
200268		require .JSONEq (t , string (valJSON ), string (act ))
201269		require .NoError (t , err )
202270	})
203271
204272	t .Run ("valueSchemaType set to None, leave value as is" , func (t  * testing.T ) {
205273		valJSON , _  :=  json .Marshal (testValue1 )
206- 
207- 		act , err  :=  k .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "NONE" })
208- 
274+ 		act , err  :=  kJSON .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "NONE" })
209275		require .JSONEq (t , string (valJSON ), string (act ))
210276		require .NoError (t , err )
211277	})
212278
213279	t .Run ("valueSchemaType invalid, return error" , func (t  * testing.T ) {
214280		valJSON , _  :=  json .Marshal (testValue1 )
215- 
216- 		_ , err  :=  k .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "xx" })
217- 
281+ 		_ , err  :=  kJSON .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "xx" })
218282		require .Error (t , err , "error parsing schema type. 'xx' is not a supported value" )
219283	})
220284
221285	t .Run ("schema found, serialize value as Avro binary" , func (t  * testing.T ) {
222286		valJSON , _  :=  json .Marshal (testValue1 )
223- 		act , err  :=  k .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "Avro" })
224- 		assertValueSerialized (t , act , valJSON , schema )
287+ 		act , err  :=  kJSON .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "Avro" })
288+ 		assertValueSerialized (t , act , valJSON , schemaJSON )
225289		require .NoError (t , err )
226290	})
227291
228- 	t .Run ("value published 'null', no error" , func (t  * testing.T ) {
229- 		act , err  :=  k .SerializeValue ("my-topic" , []byte ("null" ), map [string ]string {"valueSchemaType" : "Avro" })
292+ 	t .Run ("schema found, useAvroJson=true, serialize value as Avro binary" , func (t  * testing.T ) {
293+ 		act , err  :=  kAvroJSON .SerializeValue ("my-topic" , valueAvroJSON , map [string ]string {"valueSchemaType" : "Avro" })
294+ 		require .Equal (t , act [:5 ], recordValueFromAvroJSON [:5 ])
295+ 		require .NoError (t , err )
296+ 	})
230297
298+ 	t .Run ("value published 'null', no error" , func (t  * testing.T ) {
299+ 		act , err  :=  kJSON .SerializeValue ("my-topic" , []byte ("null" ), map [string ]string {"valueSchemaType" : "Avro" })
231300		require .Nil (t , act )
232301		require .NoError (t , err )
233302	})
234303
235304	t .Run ("value published nil, no error" , func (t  * testing.T ) {
236- 		act , err  :=  k .SerializeValue ("my-topic" , nil , map [string ]string {"valueSchemaType" : "Avro" })
237- 
305+ 		act , err  :=  kJSON .SerializeValue ("my-topic" , nil , map [string ]string {"valueSchemaType" : "Avro" })
238306		require .Nil (t , act )
239307		require .NoError (t , err )
240308	})
241309
242310	t .Run ("invalid data, return error" , func (t  * testing.T ) {
243311		valJSON , _  :=  json .Marshal (invValue )
244- 		_ , err  :=  k .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "Avro" })
245- 
312+ 		_ , err  :=  kJSON .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "Avro" })
246313		require .Error (t , err , "cannot decode textual record \" cupcake\" : cannot decode textual map: cannot determine codec: \" xxx\" " )
247314	})
248315}
249316
250317func  TestSerializeValueCachingEnabled (t  * testing.T ) {
251318	registry  :=  srclient .CreateMockSchemaRegistryClient ("http://localhost:8081" )
319+ 	registry .CodecJsonEnabled (true )
252320	schema , _  :=  registry .CreateSchema ("my-topic-value" , testSchema1 , srclient .Avro )
253321
254322	k  :=  Kafka {
@@ -278,6 +346,7 @@ func TestLatestSchemaCaching(t *testing.T) {
278346	ctrl  :=  gomock .NewController (t )
279347	defer  ctrl .Finish ()
280348	registry  :=  srclient .CreateMockSchemaRegistryClient ("http://locahost:8081" )
349+ 	registry .CodecJsonEnabled (true )
281350	m  :=  mock_srclient .NewMockISchemaRegistryClient (ctrl )
282351	schema , _  :=  registry .CreateSchema ("my-topic-value" , testSchema1 , srclient .Avro )
283352
@@ -339,9 +408,7 @@ func TestLatestSchemaCaching(t *testing.T) {
339408		}
340409
341410		m .EXPECT ().GetLatestSchema (gomock .Eq ("my-topic-value" )).Return (schema , nil ).Times (2 )
342- 
343411		valJSON , _  :=  json .Marshal (testValue1 )
344- 
345412		act , err  :=  k .SerializeValue ("my-topic" , valJSON , map [string ]string {"valueSchemaType" : "Avro" })
346413
347414		assertValueSerialized (t , act , valJSON , schema )
0 commit comments