Files
node/db/rpcdb/grpc_test.go
T
Hanzo DevandGitHub 8aa002d245 rpcdb: consolidate into node/db/rpcdb, drop luxfi/proto dep (#109)
Part A — swap Layer-B wire-types path:
  github.com/luxfi/proto/rpcdb → github.com/luxfi/protocol/rpcdb (v0.0.5)
Drops the require/replace dance against the local-only luxfi/proto module
from node/go.mod. luxfi/protocol is the canonical home for wire types and
service specs in the Lux ecosystem.

Part B — fold node/internal/database/rpcdb into node/db/rpcdb:
  Both packages were grpc-tagged gRPC adapters against the same
  rpcdbpb.DatabaseClient/Server. The internal one (db_client.go/db_server.go)
  predated the Layer A/B/C decomplect; the db/rpcdb one (grpc_server.go +
  zap_server.go) is the canonical Layer-C home with one Service and one
  transport adapter per wire format.

  New grpc_client.go in db/rpcdb mirrors the deleted internal db_client.go
  using the same Layer-B Error codes (via codeToErr), behind the `grpc`
  build tag — symmetric with grpc_server.go.

  Updated service/keystore/rpckeystore/client.go to import the canonical
  db/rpcdb.NewGRPCClient instead of internal/database/rpcdb.NewClient.

  internal/database/rpcdb/ deleted in its entirety. One canonical rpcdb
  home; no dual-shim, no deprecation period.

Default-tag build is clean. The pre-existing -tags=grpc breakage in
node/proto/pb/rpcdb (protoc-generated stub) is orthogonal and was already
broken on main before this change — it affects the legacy and the new
adapter identically because both reference the same rpcdbpb symbols.
2026-05-16 16:35:56 -07:00

140 lines
3.1 KiB
Go

//go:build grpc
// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package rpcdb
import (
"context"
"fmt"
"testing"
"github.com/stretchr/testify/require"
"github.com/luxfi/database/corruptabledb"
"github.com/luxfi/database/dbtest"
"github.com/luxfi/database/memdb"
"github.com/luxfi/log"
"github.com/luxfi/vm/rpc/grpcutils"
rpcdbpb "github.com/luxfi/node/proto/pb/rpcdb"
)
type testGRPCDatabase struct {
client *GRPCClient
server *memdb.Database
}
func setupGRPCDB(t testing.TB) *testGRPCDatabase {
require := require.New(t)
db := &testGRPCDatabase{
server: memdb.New(),
}
listener, err := grpcutils.NewListener()
require.NoError(err)
serverCloser := grpcutils.ServerCloser{}
server := grpcutils.NewServer()
rpcdbpb.RegisterDatabaseServer(server, NewGRPCServer(db.server))
serverCloser.Add(server)
go grpcutils.Serve(listener, server)
conn, err := grpcutils.Dial(listener.Addr().String())
require.NoError(err)
db.client = NewGRPCClient(rpcdbpb.NewDatabaseClient(conn))
t.Cleanup(func() {
serverCloser.Stop()
_ = conn.Close()
_ = listener.Close()
})
return db
}
func TestGRPCInterface(t *testing.T) {
for name, test := range dbtest.Tests {
t.Run(name, func(t *testing.T) {
db := setupGRPCDB(t)
test(t, db.client)
})
}
}
func FuzzGRPCKeyValue(f *testing.F) {
db := setupGRPCDB(f)
dbtest.FuzzKeyValue(f, db.client)
}
func FuzzGRPCNewIteratorWithPrefix(f *testing.F) {
db := setupGRPCDB(f)
dbtest.FuzzNewIteratorWithPrefix(f, db.client)
}
func FuzzGRPCNewIteratorWithStartAndPrefix(f *testing.F) {
db := setupGRPCDB(f)
dbtest.FuzzNewIteratorWithStartAndPrefix(f, db.client)
}
func BenchmarkGRPCInterface(b *testing.B) {
for _, size := range dbtest.BenchmarkSizes {
keys, values := dbtest.SetupBenchmark(b, size[0], size[1], size[2])
for name, bench := range dbtest.Benchmarks {
b.Run(fmt.Sprintf("rpcdb_%d_pairs_%d_keys_%d_values_%s", size[0], size[1], size[2], name), func(b *testing.B) {
db := setupGRPCDB(b)
bench(b, db.client, keys, values)
})
}
}
}
func TestGRPCHealthCheck(t *testing.T) {
scenarios := []struct {
name string
testFn func(db *corruptabledb.Database) error
wantErr bool
wantErrMsg string
}{
{
name: "healthcheck success",
testFn: func(_ *corruptabledb.Database) error {
return nil
},
},
{
name: "healthcheck failed db closed",
testFn: func(db *corruptabledb.Database) error {
return db.Close()
},
wantErr: true,
wantErrMsg: "closed",
},
}
for _, scenario := range scenarios {
t.Run(scenario.name, func(t *testing.T) {
require := require.New(t)
baseDB := setupGRPCDB(t)
db := corruptabledb.New(baseDB.server, log.NoLog{})
defer db.Close()
require.NoError(scenario.testFn(db))
_, err := db.HealthCheck(context.Background())
if scenario.wantErr {
require.Error(err) //nolint:forbidigo
require.Contains(err.Error(), scenario.wantErrMsg)
return
}
require.NoError(err)
_, err = baseDB.client.HealthCheck(context.Background())
require.NoError(err)
})
}
}