|
| 1 | +package sqlitecloud |
| 2 | + |
| 3 | +import ( |
| 4 | + "testing" |
| 5 | +) |
| 6 | + |
| 7 | +func TestProtocolBufferFromValue(t *testing.T) { |
| 8 | + tests := []struct { |
| 9 | + name string |
| 10 | + value interface{} |
| 11 | + wantLen int // expected number of []byte buffers returned |
| 12 | + wantType byte |
| 13 | + }{ |
| 14 | + // Basic types |
| 15 | + {"nil", nil, 1, CMD_NULL}, |
| 16 | + {"string", "hello", 1, CMD_ZEROSTRING}, |
| 17 | + {"int", int(42), 1, CMD_INT}, |
| 18 | + {"int8", int8(8), 1, CMD_INT}, |
| 19 | + {"int16", int16(16), 1, CMD_INT}, |
| 20 | + {"int32", int32(32), 1, CMD_INT}, |
| 21 | + {"int64", int64(64), 1, CMD_INT}, |
| 22 | + {"float32", float32(3.14), 1, CMD_FLOAT}, |
| 23 | + {"float64", float64(2.71), 1, CMD_FLOAT}, |
| 24 | + {"[]byte", []byte("blob"), 2, CMD_BLOB}, // header + data |
| 25 | + |
| 26 | + // Unsigned integers |
| 27 | + {"uint", uint(1), 1, CMD_INT}, |
| 28 | + {"uint8", uint8(1), 1, CMD_INT}, |
| 29 | + {"uint16", uint16(1), 1, CMD_INT}, |
| 30 | + {"uint32", uint32(1), 1, CMD_INT}, |
| 31 | + {"uint64", uint64(1), 1, CMD_INT}, |
| 32 | + |
| 33 | + // Pointer types (dereferenced) |
| 34 | + {"*int", intPtr(42), 1, CMD_INT}, |
| 35 | + {"*string", strPtr("hello"), 1, CMD_ZEROSTRING}, |
| 36 | + {"*int nil", (*int)(nil), 1, CMD_NULL}, |
| 37 | + {"*string nil", (*string)(nil), 1, CMD_NULL}, |
| 38 | + |
| 39 | + // Unsupported types still return empty buffers |
| 40 | + {"bool", true, 0, 0}, |
| 41 | + } |
| 42 | + |
| 43 | + for _, tt := range tests { |
| 44 | + t.Run(tt.name, func(t *testing.T) { |
| 45 | + buffers := protocolBufferFromValue(tt.value) |
| 46 | + if len(buffers) != tt.wantLen { |
| 47 | + t.Errorf("protocolBufferFromValue(%T(%v)): got %d buffers, want %d", tt.value, tt.value, len(buffers), tt.wantLen) |
| 48 | + } |
| 49 | + if tt.wantLen > 0 && len(buffers) > 0 { |
| 50 | + if buffers[0][0] != tt.wantType { |
| 51 | + t.Errorf("protocolBufferFromValue(%T(%v)): got type %c, want %c", tt.value, tt.value, buffers[0][0], tt.wantType) |
| 52 | + } |
| 53 | + } |
| 54 | + }) |
| 55 | + } |
| 56 | +} |
| 57 | + |
| 58 | +func TestProtocolBufferFromValueMixedArray(t *testing.T) { |
| 59 | + // Simulates the loop in sendArray: builds buffers from a mixed values slice |
| 60 | + // and checks that the number of buffer groups matches the number of values. |
| 61 | + pInt := intPtr(99) |
| 62 | + values := []interface{}{ |
| 63 | + "hello", // string -> 1 buffer |
| 64 | + int(42), // int -> 1 buffer |
| 65 | + nil, // nil -> 1 buffer |
| 66 | + pInt, // *int -> 1 buffer (dereferenced to int) |
| 67 | + float64(3), // float64 -> 1 buffer |
| 68 | + uint(7), // uint -> 1 buffer |
| 69 | + []byte("x"), // []byte -> 2 buffers (header+data) |
| 70 | + } |
| 71 | + |
| 72 | + // Count how many values produce at least one buffer |
| 73 | + buffersPerValue := make([]int, len(values)) |
| 74 | + totalBuffers := 0 |
| 75 | + missingValues := 0 |
| 76 | + |
| 77 | + for i, v := range values { |
| 78 | + bufs := protocolBufferFromValue(v) |
| 79 | + buffersPerValue[i] = len(bufs) |
| 80 | + totalBuffers += len(bufs) |
| 81 | + if len(bufs) == 0 { |
| 82 | + missingValues++ |
| 83 | + t.Errorf("value[%d] (%T = %v) produced 0 buffers — will be silently dropped", i, v, v) |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + if missingValues > 0 { |
| 88 | + t.Errorf("%d out of %d values produced no buffers and will be missing from the protocol message", missingValues, len(values)) |
| 89 | + } |
| 90 | + |
| 91 | + // Reproduce the exact loop from sendArray |
| 92 | + buffers := [][]byte{} |
| 93 | + for _, v := range values { |
| 94 | + buffers = append(buffers, protocolBufferFromValue(v)...) |
| 95 | + } |
| 96 | + |
| 97 | + t.Logf("values count: %d, total buffers: %d, buffers per value: %v", len(values), len(buffers), buffersPerValue) |
| 98 | + |
| 99 | + // Every value must produce at least 1 buffer ([]byte produces 2) |
| 100 | + expectedMinBuffers := len(values) |
| 101 | + if len(buffers) < expectedMinBuffers { |
| 102 | + t.Errorf("buffers array has %d elements, expected at least %d (one per value). %d values were silently dropped.", |
| 103 | + len(buffers), expectedMinBuffers, missingValues) |
| 104 | + } |
| 105 | +} |
| 106 | + |
| 107 | +// helpers |
| 108 | +func intPtr(v int) *int { return &v } |
| 109 | +func strPtr(v string) *string { return &v } |
0 commit comments