@@ -265,6 +265,14 @@ func TestVarOptItemsSketchCppCompat(t *testing.T) {
265265}
266266
267267func TestVarOptItemsSketchSerialization (t * testing.T ) {
268+ t .Run ("nil sketch encode" , func (t * testing.T ) {
269+ var buf bytes.Buffer
270+ encoder := NewVarOptItemsSketchEncoder [int64 ](& buf , common.ItemSketchLongSerDe {})
271+
272+ err := encoder .Encode (nil )
273+ require .ErrorContains (t , err , "cannot encode nil VarOptItemsSketch" )
274+ })
275+
268276 t .Run ("bad serialization version" , func (t * testing.T ) {
269277 sketch := createUnweightedVarOptItemsSketch (t , 16 , 16 )
270278 data := encodeVarOptItemsSketch (t , sketch , common.ItemSketchLongSerDe {})
@@ -331,6 +339,14 @@ func TestVarOptItemsSketchSerialization(t *testing.T) {
331339 _ , err := Decode [int64 ](data , common.ItemSketchLongSerDe {})
332340 require .ErrorContains (t , err , "invalid state in warmup mode: expected r==0, got r=4294967168" )
333341 })
342+
343+ t .Run ("warmup preamble in full mode" , func (t * testing.T ) {
344+ data := encodeVarOptItemsSketch (t , createUnweightedVarOptItemsSketch (t , 32 , 33 ), common.ItemSketchLongSerDe {})
345+ data [0 ] = (data [0 ] & 0xc0 ) | preambleLongsWarmup
346+
347+ _ , err := Decode [int64 ](data , common.ItemSketchLongSerDe {})
348+ require .ErrorContains (t , err , "invalid preamble longs: expected full because n>k, got 3" )
349+ })
334350 })
335351
336352 t .Run ("empty sketch" , func (t * testing.T ) {
@@ -361,7 +377,41 @@ func TestVarOptItemsSketchSerialization(t *testing.T) {
361377 require .ErrorContains (t , err , "invalid preamble longs: expected warmup or full, got 1" )
362378 })
363379
364- t .Run ("corrupt serialized weight" , func (t * testing.T ) {
380+ t .Run ("invalid full mode H plus R count" , func (t * testing.T ) {
381+ data := encodeVarOptItemsSketch (t , createUnweightedVarOptItemsSketch (t , 32 , 33 ), common.ItemSketchLongSerDe {})
382+ binary .LittleEndian .PutUint32 (data [20 :], 0 )
383+
384+ _ , err := Decode [int64 ](data , common.ItemSketchLongSerDe {})
385+ require .ErrorContains (t , err , "invalid state in full mode: expected h+r==k" )
386+ })
387+
388+ t .Run ("corrupt serialized R weight" , func (t * testing.T ) {
389+ t .Run ("zero" , func (t * testing.T ) {
390+ data := encodeVarOptItemsSketch (t , createUnweightedVarOptItemsSketch (t , 32 , 33 ), common.ItemSketchLongSerDe {})
391+ binary .LittleEndian .PutUint64 (data [24 :], math .Float64bits (0 ))
392+
393+ _ , err := Decode [int64 ](data , common.ItemSketchLongSerDe {})
394+ require .ErrorContains (t , err , "data is corrupt in full mode: invalid R region weight" )
395+ })
396+
397+ t .Run ("negative" , func (t * testing.T ) {
398+ data := encodeVarOptItemsSketch (t , createUnweightedVarOptItemsSketch (t , 32 , 33 ), common.ItemSketchLongSerDe {})
399+ binary .LittleEndian .PutUint64 (data [24 :], math .Float64bits (- 1.5 ))
400+
401+ _ , err := Decode [int64 ](data , common.ItemSketchLongSerDe {})
402+ require .ErrorContains (t , err , "data is corrupt in full mode: invalid R region weight" )
403+ })
404+
405+ t .Run ("nan" , func (t * testing.T ) {
406+ data := encodeVarOptItemsSketch (t , createUnweightedVarOptItemsSketch (t , 32 , 33 ), common.ItemSketchLongSerDe {})
407+ binary .LittleEndian .PutUint64 (data [24 :], math .Float64bits (math .NaN ()))
408+
409+ _ , err := Decode [int64 ](data , common.ItemSketchLongSerDe {})
410+ require .ErrorContains (t , err , "data is corrupt in full mode: invalid R region weight" )
411+ })
412+ })
413+
414+ t .Run ("corrupt serialized H weight" , func (t * testing.T ) {
365415 sketch := createUnweightedVarOptItemsSketch (t , 100 , 20 )
366416 data := encodeVarOptItemsSketch (t , sketch , common.ItemSketchLongSerDe {})
367417 preambleBytes := int (data [0 ]& 0x3f ) << 3
0 commit comments