mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
176 lines
5.3 KiB
Go
176 lines
5.3 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package indexer
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/luxfi/database/memdb"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/log"
|
|
"github.com/luxfi/math/set"
|
|
"github.com/luxfi/runtime"
|
|
"github.com/luxfi/timer/mockable"
|
|
"github.com/luxfi/utils"
|
|
)
|
|
|
|
// testRuntime creates a minimal runtime.Runtime for testing
|
|
func testRuntime(chainID ids.ID) *runtime.Runtime {
|
|
return &runtime.Runtime{
|
|
NetworkID: 1,
|
|
ChainID: chainID,
|
|
NodeID: ids.GenerateTestNodeID(),
|
|
}
|
|
}
|
|
|
|
func TestIndex(t *testing.T) {
|
|
// Setup
|
|
pageSize := uint64(64)
|
|
require := require.New(t)
|
|
baseDB := memdb.New()
|
|
// Use a test chain ID
|
|
testChainID := ids.GenerateTestID()
|
|
rt := testRuntime(testChainID)
|
|
|
|
idx, err := newIndex(baseDB, log.NoLog{}, &mockable.Clock{})
|
|
require.NoError(err)
|
|
|
|
// Populate "containers" with random IDs/bytes
|
|
containers := map[ids.ID][]byte{}
|
|
for i := uint64(0); i < 2*pageSize; i++ {
|
|
containers[ids.GenerateTestID()] = utils.RandomBytes(32)
|
|
}
|
|
|
|
// Accept each container and after each, make assertions
|
|
i := uint64(0)
|
|
for containerID, containerBytes := range containers {
|
|
require.NoError(idx.Accept(rt, containerID, containerBytes))
|
|
|
|
lastAcceptedIndex, ok := idx.lastAcceptedIndex()
|
|
require.True(ok)
|
|
require.Equal(i, lastAcceptedIndex)
|
|
require.Equal(i+1, idx.nextAcceptedIndex)
|
|
|
|
gotContainer, err := idx.GetContainerByID(containerID)
|
|
require.NoError(err)
|
|
require.Equal(containerBytes, gotContainer.Bytes)
|
|
|
|
gotIndex, err := idx.GetIndex(containerID)
|
|
require.NoError(err)
|
|
require.Equal(i, gotIndex)
|
|
|
|
gotContainer, err = idx.GetContainerByIndex(i)
|
|
require.NoError(err)
|
|
require.Equal(containerBytes, gotContainer.Bytes)
|
|
|
|
gotContainer, err = idx.GetLastAccepted()
|
|
require.NoError(err)
|
|
require.Equal(containerBytes, gotContainer.Bytes)
|
|
|
|
containers, err := idx.GetContainerRange(i, 1)
|
|
require.NoError(err)
|
|
require.Len(containers, 1)
|
|
require.Equal(containerBytes, containers[0].Bytes)
|
|
|
|
containers, err = idx.GetContainerRange(i, 2)
|
|
require.NoError(err)
|
|
require.Len(containers, 1)
|
|
require.Equal(containerBytes, containers[0].Bytes)
|
|
|
|
i++
|
|
}
|
|
|
|
// Create a new index with the same database and ensure contents still there
|
|
require.NoError(idx.vDB.Commit())
|
|
|
|
// Create a new index by directly using the same base database
|
|
// Don't close the old index to avoid closing the baseDB
|
|
idx, err = newIndex(baseDB, log.NoLog{}, &mockable.Clock{})
|
|
require.NoError(err)
|
|
|
|
// Get all of the containers
|
|
containersList, err := idx.GetContainerRange(0, pageSize)
|
|
require.NoError(err)
|
|
require.Len(containersList, int(pageSize))
|
|
containersList2, err := idx.GetContainerRange(pageSize, pageSize)
|
|
require.NoError(err)
|
|
require.Len(containersList2, int(pageSize))
|
|
containersList = append(containersList, containersList2...)
|
|
|
|
// Ensure that the data is correct
|
|
lastTimestamp := int64(0)
|
|
sawContainers := make(set.Set[ids.ID])
|
|
for _, container := range containersList {
|
|
require.False(sawContainers.Contains(container.ID)) // Should only see this container once
|
|
require.Contains(containers, container.ID)
|
|
require.Equal(containers[container.ID], container.Bytes)
|
|
// Timestamps should be non-decreasing
|
|
require.GreaterOrEqual(container.Timestamp, lastTimestamp)
|
|
lastTimestamp = container.Timestamp
|
|
sawContainers.Add(container.ID)
|
|
}
|
|
}
|
|
|
|
func TestIndexGetContainerByRangeMaxPageSize(t *testing.T) {
|
|
// Setup
|
|
require := require.New(t)
|
|
db := memdb.New()
|
|
// Use a test chain ID
|
|
testChainID := ids.GenerateTestID()
|
|
rt := testRuntime(testChainID)
|
|
idx, err := newIndex(db, log.NoLog{}, &mockable.Clock{})
|
|
require.NoError(err)
|
|
|
|
// Insert [MaxFetchedByRange] + 1 containers
|
|
for i := uint64(0); i < MaxFetchedByRange+1; i++ {
|
|
require.NoError(idx.Accept(rt, ids.GenerateTestID(), utils.RandomBytes(32)))
|
|
}
|
|
|
|
// Page size too large
|
|
_, err = idx.GetContainerRange(0, MaxFetchedByRange+1)
|
|
require.ErrorIs(err, errNumToFetchInvalid)
|
|
|
|
// Make sure data is right
|
|
containers, err := idx.GetContainerRange(0, MaxFetchedByRange)
|
|
require.NoError(err)
|
|
require.Len(containers, MaxFetchedByRange)
|
|
|
|
containers2, err := idx.GetContainerRange(1, MaxFetchedByRange)
|
|
require.NoError(err)
|
|
require.Len(containers2, MaxFetchedByRange)
|
|
|
|
require.Equal(containers[1], containers2[0])
|
|
require.Equal(containers[MaxFetchedByRange-1], containers2[MaxFetchedByRange-2])
|
|
|
|
// Should have last 2 elements
|
|
containers, err = idx.GetContainerRange(MaxFetchedByRange-1, MaxFetchedByRange)
|
|
require.NoError(err)
|
|
require.Len(containers, 2)
|
|
require.Equal(containers[1], containers2[MaxFetchedByRange-1])
|
|
require.Equal(containers[0], containers2[MaxFetchedByRange-2])
|
|
}
|
|
|
|
func TestDontIndexSameContainerTwice(t *testing.T) {
|
|
// Setup
|
|
require := require.New(t)
|
|
db := memdb.New()
|
|
// Use a test chain ID
|
|
testChainID := ids.GenerateTestID()
|
|
rt := testRuntime(testChainID)
|
|
idx, err := newIndex(db, log.NoLog{}, &mockable.Clock{})
|
|
require.NoError(err)
|
|
|
|
// Accept the same container twice
|
|
containerID := ids.GenerateTestID()
|
|
require.NoError(idx.Accept(rt, containerID, []byte{1, 2, 3}))
|
|
require.NoError(idx.Accept(rt, containerID, []byte{4, 5, 6}))
|
|
_, err = idx.GetContainerByIndex(1)
|
|
require.ErrorIs(err, errNoContainerAtIndex)
|
|
gotContainer, err := idx.GetContainerByID(containerID)
|
|
require.NoError(err)
|
|
require.Equal([]byte{1, 2, 3}, gotContainer.Bytes)
|
|
}
|