Files
evm/sync/handlers/code_request_test.go

167 lines
5.5 KiB
Go

// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package handlers
import (
"context"
"testing"
"github.com/luxfi/evm/plugin/evm/message"
"github.com/luxfi/evm/sync/handlers/stats/statstest"
"github.com/luxfi/geth/common"
"github.com/luxfi/geth/core/rawdb"
"github.com/luxfi/ids"
"github.com/stretchr/testify/assert"
)
func TestCodeRequestHandler(t *testing.T) {
tests := map[string]struct {
codeBytes [][]byte
codeHashes []common.Hash
expectedBytes [][]byte
assertStats func(t *testing.T, stats *statstest.TestHandlerStats)
}{
"zero hashes": {
codeBytes: nil,
codeHashes: []common.Hash{},
expectedBytes: [][]byte{},
assertStats: func(t *testing.T, stats *statstest.TestHandlerStats) {
assert.Equal(t, uint32(1), stats.CodeRequestCount)
assert.Equal(t, uint32(0), stats.DuplicateHashesRequested)
assert.Equal(t, uint32(0), stats.TooManyHashesRequested)
assert.Equal(t, uint32(0), stats.MissingCodeHashCount)
assert.Equal(t, uint32(0), stats.CodeBytesReturnedSum)
},
},
"single code": {
codeBytes: [][]byte{{1, 2, 3}},
codeHashes: []common.Hash{{1}},
expectedBytes: [][]byte{{1, 2, 3}},
assertStats: func(t *testing.T, stats *statstest.TestHandlerStats) {
assert.Equal(t, uint32(1), stats.CodeRequestCount)
assert.Equal(t, uint32(0), stats.DuplicateHashesRequested)
assert.Equal(t, uint32(0), stats.TooManyHashesRequested)
assert.Equal(t, uint32(0), stats.MissingCodeHashCount)
assert.Equal(t, uint32(3), stats.CodeBytesReturnedSum)
},
},
"multiple hashes": {
codeBytes: [][]byte{{1, 2, 3}, {1}, {255, 0, 15, 16}},
codeHashes: []common.Hash{{1}, {2}, {3}},
expectedBytes: [][]byte{{1, 2, 3}, {1}, {255, 0, 15, 16}},
assertStats: func(t *testing.T, stats *statstest.TestHandlerStats) {
assert.Equal(t, uint32(1), stats.CodeRequestCount)
assert.Equal(t, uint32(0), stats.DuplicateHashesRequested)
assert.Equal(t, uint32(0), stats.TooManyHashesRequested)
assert.Equal(t, uint32(0), stats.MissingCodeHashCount)
assert.Equal(t, uint32(8), stats.CodeBytesReturnedSum)
},
},
"not found code": {
codeBytes: [][]byte{{1, 2, 3}, nil, {255, 0, 15, 16}},
codeHashes: []common.Hash{{1}, {2}, {3}},
expectedBytes: nil,
assertStats: func(t *testing.T, stats *statstest.TestHandlerStats) {
assert.Equal(t, uint32(1), stats.CodeRequestCount)
assert.Equal(t, uint32(0), stats.DuplicateHashesRequested)
assert.Equal(t, uint32(0), stats.TooManyHashesRequested)
assert.Equal(t, uint32(1), stats.MissingCodeHashCount)
assert.Equal(t, uint32(0), stats.CodeBytesReturnedSum)
},
},
"too many hashes": {
codeBytes: make([][]byte, message.MaxCodeHashesPerRequest+1),
codeHashes: make([]common.Hash, message.MaxCodeHashesPerRequest+1),
expectedBytes: nil,
assertStats: func(t *testing.T, stats *statstest.TestHandlerStats) {
assert.Equal(t, uint32(1), stats.CodeRequestCount)
assert.Equal(t, uint32(0), stats.DuplicateHashesRequested)
assert.Equal(t, uint32(1), stats.TooManyHashesRequested)
assert.Equal(t, uint32(0), stats.MissingCodeHashCount)
assert.Equal(t, uint32(0), stats.CodeBytesReturnedSum)
},
},
"duplicate hashes": {
codeBytes: [][]byte{{1, 2, 3}, {1}, {255, 0, 15, 16}},
codeHashes: []common.Hash{{1}, {2}, {1}},
expectedBytes: nil,
assertStats: func(t *testing.T, stats *statstest.TestHandlerStats) {
assert.Equal(t, uint32(1), stats.CodeRequestCount)
assert.Equal(t, uint32(1), stats.DuplicateHashesRequested)
assert.Equal(t, uint32(0), stats.TooManyHashesRequested)
assert.Equal(t, uint32(0), stats.MissingCodeHashCount)
assert.Equal(t, uint32(0), stats.CodeBytesReturnedSum)
},
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
db := rawdb.NewMemoryDatabase()
assert.Equal(t, len(test.codeBytes), len(test.codeHashes))
codeMap := make(map[common.Hash][]byte)
for i, codeBytes := range test.codeBytes {
if codeBytes != nil {
codeMap[test.codeHashes[i]] = codeBytes
rawdb.WriteCode(db, test.codeHashes[i], codeBytes)
}
}
codeRequest := message.CodeRequest{
Hashes: test.codeHashes,
}
testStats := &statstest.TestHandlerStats{}
codeRequestHandler := NewCodeRequestHandler(db, message.Codec, testStats)
responseBytes, err := codeRequestHandler.OnCodeRequest(context.Background(), ids.GenerateTestNodeID(), 1, codeRequest)
assert.NoError(t, err)
if test.expectedBytes == nil {
assert.Nil(t, responseBytes)
} else {
var response message.CodeResponse
_, err = message.Codec.Unmarshal(responseBytes, &response)
assert.NoError(t, err)
assert.Equal(t, test.expectedBytes, response.Data)
}
test.assertStats(t, testStats)
})
}
}
func TestIsUnique(t *testing.T) {
tests := map[string]struct {
hashes []common.Hash
expectUnique bool
}{
"unique": {
hashes: []common.Hash{{1}, {2}, {3}},
expectUnique: true,
},
"not unique": {
hashes: []common.Hash{{1}, {2}, {1}},
expectUnique: false,
},
"empty": {
hashes: []common.Hash{},
expectUnique: true,
},
"single": {
hashes: []common.Hash{{1}},
expectUnique: true,
},
"all same": {
hashes: []common.Hash{{1}, {1}, {1}},
expectUnique: false,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
assert.Equal(t, test.expectUnique, isUnique(test.hashes))
})
}
}