Skip to content

[dbnode] Added unit tests for dbnode's encoding package #4334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/dbnode/encoding/encoder_pool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package encoding

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/m3db/m3/src/x/pool"
)

func TestEncoderPool(t *testing.T) {
pOpts := pool.NewObjectPoolOptions().SetSize(1)
p := NewEncoderPool(pOpts)
p.Init(NewNullEncoder)

encoder := p.Get()
assert.NotNil(t, encoder)

p.Put(encoder)
}
25 changes: 25 additions & 0 deletions src/dbnode/encoding/encoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package encoding

import (
"math"
"math/bits"
"testing"

"github.com/stretchr/testify/require"
Expand All @@ -35,3 +36,27 @@ func TestNumSig(t *testing.T) {
require.Equal(t, uint8(64), NumSig(uint64(math.MaxUint64)))
require.Equal(t, uint8(64), NumSig(uint64(math.MaxUint64-1)))
}

func TestLeadingAndTrailingZeros(t *testing.T) {
tests := []struct {
name string
input uint64
expectedLZ int
expectedTZ int
}{
{"Zero case", 0, 64, 0},
{"All ones", ^uint64(0), 0, 0},
{"Single bit (LSB)", 1, 63, 0},
{"Single bit (MSB)", 1 << 63, 0, 63},
{"Multiple bits", 0b0000110000000000, 52, 10},
{"Random number", 0xF0F00000000000F, bits.LeadingZeros64(0xF0F00000000000F), bits.TrailingZeros64(0xF0F00000000000F)},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
leading, trailing := LeadingAndTrailingZeros(tt.input)
require.Equal(t, tt.expectedLZ, leading)
require.Equal(t, tt.expectedTZ, trailing)
})
}
}
49 changes: 49 additions & 0 deletions src/dbnode/encoding/iterator_pool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package encoding

import (
"testing"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"

"github.com/m3db/m3/src/dbnode/namespace"
"github.com/m3db/m3/src/dbnode/x/xio"
"github.com/m3db/m3/src/x/pool"
)

// Mocked allocation function
func mockReaderIteratorAllocate(_ xio.Reader64, _ namespace.SchemaDescr) ReaderIterator {
ctrl := gomock.NewController(nil)
defer ctrl.Finish()
return NewMockReaderIterator(ctrl)
}

func TestReaderIteratorPool(t *testing.T) {
opts := pool.NewObjectPoolOptions()
pool := NewReaderIteratorPool(opts)

// Initialize pool with mock allocator
pool.Init(mockReaderIteratorAllocate)

// Get a reader iterator from the pool
iter := pool.Get()
assert.NotNil(t, iter)

// Return the iterator to the pool
pool.Put(iter)
}

func TestMultiReaderIteratorPool(t *testing.T) {
opts := pool.NewObjectPoolOptions()
pool := NewMultiReaderIteratorPool(opts)

// Initialize pool with mock allocator
pool.Init(mockReaderIteratorAllocate)

// Get a multi-reader iterator from the pool
iter := pool.Get()
assert.NotNil(t, iter)

// Return the iterator to the pool
pool.Put(iter)
}
48 changes: 48 additions & 0 deletions src/dbnode/encoding/multi_reader_iterator_array_pool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package encoding

import (
"testing"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"

"github.com/m3db/m3/src/x/pool"
)

func TestMultiReaderIteratorArrayPool(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

// Define pool bucket sizes
buckets := []pool.Bucket{
{Capacity: 2, Count: pool.Size(-1)},
{Capacity: 4, Count: pool.Size(2)},
{Capacity: 8, Count: pool.Size(3)},
}

// Create the pool
pool := NewMultiReaderIteratorArrayPool(buckets)
pool.Init()

// Test Get() - requesting a capacity within bucket limits
arr := pool.Get(4)
assert.Equal(t, 0, len(arr))
assert.Equal(t, 4, cap(arr)) // Should match bucket capacity

// Test Put() - returning an array to the pool
arr = append(arr, nil) // Simulate use
pool.Put(arr)

// Test Get() - retrieving the same array
reusedArr := pool.Get(4)
assert.Equal(t, 0, len(reusedArr))
assert.Equal(t, 4, cap(reusedArr)) // Should be the same bucket

// Test Get() with an oversized request
largeArr := pool.Get(16)
assert.Equal(t, 0, len(largeArr))
assert.Equal(t, 16, cap(largeArr)) // Should allocate new since it's out of range

// Test Put() with an oversized array (should not be stored)
pool.Put(largeArr)
}
64 changes: 64 additions & 0 deletions src/dbnode/encoding/null_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package encoding

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/m3db/m3/src/dbnode/ts"
"github.com/m3db/m3/src/x/context"
xtime "github.com/m3db/m3/src/x/time"
)

func TestNullEncoder(t *testing.T) {
encoder := NewNullEncoder()

// Test Encode (should return nil)
err := encoder.Encode(ts.Datapoint{}, xtime.Unit(0), nil)
assert.NoError(t, err)

// Test Stream (should return nil, false)
stream, ok := encoder.Stream(context.NewBackground())
assert.Nil(t, stream)
assert.False(t, ok)

// Test NumEncoded (should be 0)
assert.Equal(t, 0, encoder.NumEncoded())

// Test LastEncoded (should return an error)
_, err = encoder.LastEncoded()
assert.Error(t, err)

// Test LastAnnotationChecksum (should return an error)
_, err = encoder.LastAnnotationChecksum()
assert.Error(t, err)

// Test Empty (should return true)
assert.True(t, encoder.Empty())

// Test Len (should return 0)
assert.Equal(t, 0, encoder.Len())

// Test Discard (should return an empty segment)
segment := encoder.Discard()
assert.Equal(t, ts.Segment{}, segment)
}

func TestNullReaderIterator(t *testing.T) {
iterator := NewNullReaderIterator()

// Test Current (should return default values)
dp, unit, annotation := iterator.Current()
assert.Equal(t, ts.Datapoint{}, dp)
assert.Equal(t, xtime.Unit(0), unit)
assert.Nil(t, annotation)

// Test Next (should return false)
assert.False(t, iterator.Next())

// Test Err (should return an error)
assert.Error(t, iterator.Err())

// Test Close (should not panic)
iterator.Close()
}
65 changes: 65 additions & 0 deletions src/dbnode/encoding/options_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package encoding

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/m3db/m3/src/x/instrument"
"github.com/m3db/m3/src/x/pool"
xtime "github.com/m3db/m3/src/x/time"
)

func TestOptionsSettersAndGetters(t *testing.T) {
opts := NewOptions()

// Prepare dummy values
newTimeUnit := xtime.Minute
newLRUSize := 10
newM3TSZSize := 64
newProtoSize := 256
newMetrics := NewMetrics(instrument.NewOptions().MetricsScope())

// Create and init a dummy bytes pool
bytesPool := pool.NewCheckedBytesPool(
[]pool.Bucket{{
Capacity: 1024,
Count: 10,
}}, nil, func(s []pool.Bucket) pool.BytesPool {
return pool.NewBytesPool(s, nil)
})
bytesPool.Init()

// Apply all setters
opts2 := opts.
SetDefaultTimeUnit(newTimeUnit).
SetByteFieldDictionaryLRUSize(newLRUSize).
SetIStreamReaderSizeM3TSZ(newM3TSZSize).
SetIStreamReaderSizeProto(newProtoSize).
SetMetrics(newMetrics).
SetBytesPool(bytesPool)

// Validate getters return the new values
require.Equal(t, newTimeUnit, opts2.DefaultTimeUnit())
require.Equal(t, newLRUSize, opts2.ByteFieldDictionaryLRUSize())
require.Equal(t, newM3TSZSize, opts2.IStreamReaderSizeM3TSZ())
require.Equal(t, newProtoSize, opts2.IStreamReaderSizeProto())
require.Equal(t, newMetrics, opts2.Metrics())
require.Equal(t, bytesPool, opts2.BytesPool())

// Original should remain unchanged (immutability check)
require.Equal(t, defaultDefaultTimeUnit, opts.DefaultTimeUnit())
require.Equal(t, defaultByteFieldDictLRUSize, opts.ByteFieldDictionaryLRUSize())
}

func TestOptionsDefaults(t *testing.T) {
opts := NewOptions()

require.Equal(t, defaultDefaultTimeUnit, opts.DefaultTimeUnit())
require.Equal(t, defaultByteFieldDictLRUSize, opts.ByteFieldDictionaryLRUSize())
require.Equal(t, defaultIStreamReaderSizeM3TSZ, opts.IStreamReaderSizeM3TSZ())
require.Equal(t, defaultIStreamReaderSizeProto, opts.IStreamReaderSizeProto())
require.NotNil(t, opts.TimeEncodingSchemes())
require.Equal(t, defaultMarkerEncodingScheme, opts.MarkerEncodingScheme())
require.NotNil(t, opts.Metrics())
}
Loading