Skip to content

Commit 1aaaf16

Browse files
committed
Added unit tests for encoding package under dbnode along with new mocks
1 parent d1b37a5 commit 1aaaf16

15 files changed

+1801
-4
lines changed
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package encoding
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
"github.com/m3db/m3/src/x/pool"
9+
)
10+
11+
func TestEncoderPool(t *testing.T) {
12+
pOpts := pool.NewObjectPoolOptions().SetSize(1)
13+
p := NewEncoderPool(pOpts)
14+
p.Init(NewNullEncoder)
15+
16+
encoder := p.Get()
17+
assert.NotNil(t, encoder)
18+
19+
p.Put(encoder)
20+
}

src/dbnode/encoding/encoding_test.go

+25
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package encoding
2222

2323
import (
2424
"math"
25+
"math/bits"
2526
"testing"
2627

2728
"github.com/stretchr/testify/require"
@@ -35,3 +36,27 @@ func TestNumSig(t *testing.T) {
3536
require.Equal(t, uint8(64), NumSig(uint64(math.MaxUint64)))
3637
require.Equal(t, uint8(64), NumSig(uint64(math.MaxUint64-1)))
3738
}
39+
40+
func TestLeadingAndTrailingZeros(t *testing.T) {
41+
tests := []struct {
42+
name string
43+
input uint64
44+
expectedLZ int
45+
expectedTZ int
46+
}{
47+
{"Zero case", 0, 64, 0},
48+
{"All ones", ^uint64(0), 0, 0},
49+
{"Single bit (LSB)", 1, 63, 0},
50+
{"Single bit (MSB)", 1 << 63, 0, 63},
51+
{"Multiple bits", 0b0000110000000000, 52, 10},
52+
{"Random number", 0xF0F00000000000F, bits.LeadingZeros64(0xF0F00000000000F), bits.TrailingZeros64(0xF0F00000000000F)},
53+
}
54+
55+
for _, tt := range tests {
56+
t.Run(tt.name, func(t *testing.T) {
57+
leading, trailing := LeadingAndTrailingZeros(tt.input)
58+
require.Equal(t, tt.expectedLZ, leading)
59+
require.Equal(t, tt.expectedTZ, trailing)
60+
})
61+
}
62+
}
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package encoding
2+
3+
import (
4+
"testing"
5+
6+
"github.com/golang/mock/gomock"
7+
"github.com/stretchr/testify/assert"
8+
9+
"github.com/m3db/m3/src/dbnode/namespace"
10+
"github.com/m3db/m3/src/dbnode/x/xio"
11+
"github.com/m3db/m3/src/x/pool"
12+
)
13+
14+
// Mocked allocation function
15+
func mockReaderIteratorAllocate(_ xio.Reader64, _ namespace.SchemaDescr) ReaderIterator {
16+
ctrl := gomock.NewController(nil)
17+
defer ctrl.Finish()
18+
return NewMockReaderIterator(ctrl)
19+
}
20+
21+
func TestReaderIteratorPool(t *testing.T) {
22+
opts := pool.NewObjectPoolOptions()
23+
pool := NewReaderIteratorPool(opts)
24+
25+
// Initialize pool with mock allocator
26+
pool.Init(mockReaderIteratorAllocate)
27+
28+
// Get a reader iterator from the pool
29+
iter := pool.Get()
30+
assert.NotNil(t, iter)
31+
32+
// Return the iterator to the pool
33+
pool.Put(iter)
34+
}
35+
36+
func TestMultiReaderIteratorPool(t *testing.T) {
37+
opts := pool.NewObjectPoolOptions()
38+
pool := NewMultiReaderIteratorPool(opts)
39+
40+
// Initialize pool with mock allocator
41+
pool.Init(mockReaderIteratorAllocate)
42+
43+
// Get a multi-reader iterator from the pool
44+
iter := pool.Get()
45+
assert.NotNil(t, iter)
46+
47+
// Return the iterator to the pool
48+
pool.Put(iter)
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package encoding
2+
3+
import (
4+
"testing"
5+
6+
"github.com/golang/mock/gomock"
7+
"github.com/stretchr/testify/assert"
8+
9+
"github.com/m3db/m3/src/x/pool"
10+
)
11+
12+
func TestMultiReaderIteratorArrayPool(t *testing.T) {
13+
ctrl := gomock.NewController(t)
14+
defer ctrl.Finish()
15+
16+
// Define pool bucket sizes
17+
buckets := []pool.Bucket{
18+
{Capacity: 2, Count: pool.Size(-1)},
19+
{Capacity: 4, Count: pool.Size(2)},
20+
{Capacity: 8, Count: pool.Size(3)},
21+
}
22+
23+
// Create the pool
24+
pool := NewMultiReaderIteratorArrayPool(buckets)
25+
pool.Init()
26+
27+
// Test Get() - requesting a capacity within bucket limits
28+
arr := pool.Get(4)
29+
assert.Equal(t, 0, len(arr))
30+
assert.Equal(t, 4, cap(arr)) // Should match bucket capacity
31+
32+
// Test Put() - returning an array to the pool
33+
arr = append(arr, nil) // Simulate use
34+
pool.Put(arr)
35+
36+
// Test Get() - retrieving the same array
37+
reusedArr := pool.Get(4)
38+
assert.Equal(t, 0, len(reusedArr))
39+
assert.Equal(t, 4, cap(reusedArr)) // Should be the same bucket
40+
41+
// Test Get() with an oversized request
42+
largeArr := pool.Get(16)
43+
assert.Equal(t, 0, len(largeArr))
44+
assert.Equal(t, 16, cap(largeArr)) // Should allocate new since it's out of range
45+
46+
// Test Put() with an oversized array (should not be stored)
47+
pool.Put(largeArr)
48+
}

src/dbnode/encoding/null_test.go

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package encoding
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
"github.com/m3db/m3/src/dbnode/ts"
9+
"github.com/m3db/m3/src/x/context"
10+
xtime "github.com/m3db/m3/src/x/time"
11+
)
12+
13+
func TestNullEncoder(t *testing.T) {
14+
encoder := NewNullEncoder()
15+
16+
// Test Encode (should return nil)
17+
err := encoder.Encode(ts.Datapoint{}, xtime.Unit(0), nil)
18+
assert.NoError(t, err)
19+
20+
// Test Stream (should return nil, false)
21+
stream, ok := encoder.Stream(context.NewBackground())
22+
assert.Nil(t, stream)
23+
assert.False(t, ok)
24+
25+
// Test NumEncoded (should be 0)
26+
assert.Equal(t, 0, encoder.NumEncoded())
27+
28+
// Test LastEncoded (should return an error)
29+
_, err = encoder.LastEncoded()
30+
assert.Error(t, err)
31+
32+
// Test LastAnnotationChecksum (should return an error)
33+
_, err = encoder.LastAnnotationChecksum()
34+
assert.Error(t, err)
35+
36+
// Test Empty (should return true)
37+
assert.True(t, encoder.Empty())
38+
39+
// Test Len (should return 0)
40+
assert.Equal(t, 0, encoder.Len())
41+
42+
// Test Discard (should return an empty segment)
43+
segment := encoder.Discard()
44+
assert.Equal(t, ts.Segment{}, segment)
45+
}
46+
47+
func TestNullReaderIterator(t *testing.T) {
48+
iterator := NewNullReaderIterator()
49+
50+
// Test Current (should return default values)
51+
dp, unit, annotation := iterator.Current()
52+
assert.Equal(t, ts.Datapoint{}, dp)
53+
assert.Equal(t, xtime.Unit(0), unit)
54+
assert.Nil(t, annotation)
55+
56+
// Test Next (should return false)
57+
assert.False(t, iterator.Next())
58+
59+
// Test Err (should return an error)
60+
assert.Error(t, iterator.Err())
61+
62+
// Test Close (should not panic)
63+
iterator.Close()
64+
}

src/dbnode/encoding/options_test.go

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package encoding
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
8+
"github.com/m3db/m3/src/x/instrument"
9+
"github.com/m3db/m3/src/x/pool"
10+
xtime "github.com/m3db/m3/src/x/time"
11+
)
12+
13+
func TestOptionsSettersAndGetters(t *testing.T) {
14+
opts := NewOptions()
15+
16+
// Prepare dummy values
17+
newTimeUnit := xtime.Minute
18+
newLRUSize := 10
19+
newM3TSZSize := 64
20+
newProtoSize := 256
21+
newMetrics := NewMetrics(instrument.NewOptions().MetricsScope())
22+
23+
// Create and init a dummy bytes pool
24+
bytesPool := pool.NewCheckedBytesPool(
25+
[]pool.Bucket{{
26+
Capacity: 1024,
27+
Count: 10,
28+
}}, nil, func(s []pool.Bucket) pool.BytesPool {
29+
return pool.NewBytesPool(s, nil)
30+
})
31+
bytesPool.Init()
32+
33+
// Apply all setters
34+
opts2 := opts.
35+
SetDefaultTimeUnit(newTimeUnit).
36+
SetByteFieldDictionaryLRUSize(newLRUSize).
37+
SetIStreamReaderSizeM3TSZ(newM3TSZSize).
38+
SetIStreamReaderSizeProto(newProtoSize).
39+
SetMetrics(newMetrics).
40+
SetBytesPool(bytesPool)
41+
42+
// Validate getters return the new values
43+
require.Equal(t, newTimeUnit, opts2.DefaultTimeUnit())
44+
require.Equal(t, newLRUSize, opts2.ByteFieldDictionaryLRUSize())
45+
require.Equal(t, newM3TSZSize, opts2.IStreamReaderSizeM3TSZ())
46+
require.Equal(t, newProtoSize, opts2.IStreamReaderSizeProto())
47+
require.Equal(t, newMetrics, opts2.Metrics())
48+
require.Equal(t, bytesPool, opts2.BytesPool())
49+
50+
// Original should remain unchanged (immutability check)
51+
require.Equal(t, defaultDefaultTimeUnit, opts.DefaultTimeUnit())
52+
require.Equal(t, defaultByteFieldDictLRUSize, opts.ByteFieldDictionaryLRUSize())
53+
}
54+
55+
func TestOptionsDefaults(t *testing.T) {
56+
opts := NewOptions()
57+
58+
require.Equal(t, defaultDefaultTimeUnit, opts.DefaultTimeUnit())
59+
require.Equal(t, defaultByteFieldDictLRUSize, opts.ByteFieldDictionaryLRUSize())
60+
require.Equal(t, defaultIStreamReaderSizeM3TSZ, opts.IStreamReaderSizeM3TSZ())
61+
require.Equal(t, defaultIStreamReaderSizeProto, opts.IStreamReaderSizeProto())
62+
require.NotNil(t, opts.TimeEncodingSchemes())
63+
require.Equal(t, defaultMarkerEncodingScheme, opts.MarkerEncodingScheme())
64+
require.NotNil(t, opts.Metrics())
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package proto
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/jhump/protoreflect/desc"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestParseProtoSchema(t *testing.T) {
12+
// Create a temporary proto file for testing
13+
protoContent := `syntax = "proto3";
14+
15+
message TestMessage {
16+
string name = 1;
17+
int32 age = 2;
18+
}`
19+
20+
protoFile := "test.proto"
21+
err := os.WriteFile(protoFile, []byte(protoContent), 0644)
22+
assert.NoError(t, err)
23+
defer func(name string) {
24+
_ = os.Remove(name)
25+
}(protoFile) // Clean up after the test
26+
27+
tests := []struct {
28+
name string
29+
filePath string
30+
messageName string
31+
expectErr bool
32+
expectedType *desc.MessageDescriptor
33+
}{
34+
{
35+
name: "Valid proto file and message",
36+
filePath: protoFile,
37+
messageName: "TestMessage",
38+
expectErr: false,
39+
},
40+
{
41+
name: "Invalid proto file path",
42+
filePath: "non_existent.proto",
43+
messageName: "TestMessage",
44+
expectErr: true,
45+
},
46+
{
47+
name: "Message not found",
48+
filePath: protoFile,
49+
messageName: "UnknownMessage",
50+
expectErr: true,
51+
},
52+
}
53+
54+
for _, tt := range tests {
55+
t.Run(tt.name, func(t *testing.T) {
56+
result, err := ParseProtoSchema(tt.filePath, tt.messageName)
57+
if tt.expectErr {
58+
assert.Error(t, err, "Expected an error but got none")
59+
assert.Nil(t, result)
60+
} else {
61+
assert.NoError(t, err, "Expected no error but got one")
62+
assert.NotNil(t, result, "Expected a valid MessageDescriptor but got nil")
63+
assert.Equal(t, tt.messageName, result.GetName())
64+
}
65+
})
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package encoding
2+
3+
import (
4+
"testing"
5+
6+
"github.com/golang/mock/gomock"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestSeriesIteratorPool(t *testing.T) {
11+
ctrl := gomock.NewController(t)
12+
defer ctrl.Finish()
13+
14+
// Create mock object pool
15+
pool := NewSeriesIteratorPool(nil)
16+
pool.Init()
17+
18+
// Test Get()
19+
iter := pool.Get()
20+
assert.NotNil(t, iter)
21+
22+
// Test Put()
23+
pool.Put(iter)
24+
}

0 commit comments

Comments
 (0)