package integration
import (
"context"
"flag"
"testing"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"github.com/google/trillian"
"github.com/google/trillian/client"
"github.com/google/trillian/extension"
"github.com/google/trillian/quota"
"github.com/google/trillian/storage/memory"
"github.com/google/trillian/storage/testdb"
"github.com/google/trillian/testonly/integration"
stestonly "github.com/google/trillian/storage/testonly"
)
var (
treeIDFlag = flag.Int64("treeid", -1, "The tree id to use")
serverFlag = flag.String("log_rpc_server", "localhost:8092", "Server address:port")
queueLeavesFlag = flag.Bool("queue_leaves", true, "If true queues leaves, false just reads from the log")
awaitSequencingFlag = flag.Bool("await_sequencing", true, "If true then waits until log size is at least num_leaves")
checkLogEmptyFlag = flag.Bool("check_log_empty", true, "If true ensures log is empty before queuing anything")
startLeafFlag = flag.Int64("start_leaf", 0, "The first leaf index to use")
numLeavesFlag = flag.Int64("num_leaves", 1000, "The number of leaves to submit and read back")
queueBatchSizeFlag = flag.Int("queue_batch_size", 50, "Batch size when queueing leaves")
sequencerBatchSizeFlag = flag.Int("sequencing_batch_size", 100, "Batch size for server sequencer")
readBatchSizeFlag = flag.Int64("read_batch_size", 50, "Batch size when getting leaves by index")
waitForSequencingFlag = flag.Duration("wait_for_sequencing", time.Second*60, "How long to wait for leaves to be sequenced")
waitBetweenQueueChecksFlag = flag.Duration("queue_poll_wait", time.Second*5, "How frequently to check the queue while waiting")
rpcRequestDeadlineFlag = flag.Duration("rpc_deadline", time.Second*10, "Deadline to use for all RPC requests")
customLeafPrefixFlag = flag.String("custom_leaf_prefix", "", "Prefix string added to all queued leaves")
)
func TestLiveLogIntegration(t *testing.T) {
flag.Parse()
if *treeIDFlag == -1 {
t.Skip("Log integration test skipped as no tree ID provided")
}
params := TestParameters{
TreeID: *treeIDFlag,
CheckLogEmpty: *checkLogEmptyFlag,
QueueLeaves: *queueLeavesFlag,
AwaitSequencing: *awaitSequencingFlag,
StartLeaf: *startLeafFlag,
LeafCount: *numLeavesFlag,
QueueBatchSize: *queueBatchSizeFlag,
SequencerBatchSize: *sequencerBatchSizeFlag,
ReadBatchSize: *readBatchSizeFlag,
SequencingWaitTotal: *waitForSequencingFlag,
SequencingPollWait: *waitBetweenQueueChecksFlag,
RPCRequestDeadline: *rpcRequestDeadlineFlag,
CustomLeafPrefix: *customLeafPrefixFlag,
}
if params.StartLeaf < 0 || params.LeafCount <= 0 {
t.Fatalf("Start leaf index must be >= 0 (%d) and number of leaves must be > 0 (%d)", params.StartLeaf, params.LeafCount)
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
conn, err := grpc.DialContext(ctx, *serverFlag, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
t.Fatalf("Failed to connect to log server: %v", err)
}
defer func() {
if err := conn.Close(); err != nil {
t.Errorf("Close(): %v", err)
}
}()
lc := trillian.NewTrillianLogClient(conn)
if err := RunLogIntegration(lc, params); err != nil {
t.Fatalf("Test failed: %v", err)
}
}
func TestInProcessLogIntegration(t *testing.T) {
testdb.SkipIfNoMySQL(t)
ctx := context.Background()
const numSequencers = 2
env, err := integration.NewLogEnvWithGRPCOptions(ctx, numSequencers, nil, nil)
if err != nil {
t.Fatal(err)
}
defer env.Close()
tree, err := client.CreateAndInitTree(ctx, &trillian.CreateTreeRequest{
Tree: stestonly.LogTree,
}, env.Admin, env.Log)
if err != nil {
t.Fatalf("Failed to create log: %v", err)
}
params := DefaultTestParameters(tree.TreeId)
if err := RunLogIntegration(env.Log, params); err != nil {
t.Fatalf("Test failed: %v", err)
}
}
func TestInProcessLogIntegrationDuplicateLeaves(t *testing.T) {
ctx := context.Background()
const numSequencers = 2
ts := memory.NewTreeStorage()
ms := memory.NewLogStorage(ts, nil)
reggie := extension.Registry{
AdminStorage: memory.NewAdminStorage(ts),
LogStorage: ms,
QuotaManager: quota.Noop(),
}
env, err := integration.NewLogEnvWithRegistry(ctx, numSequencers, reggie)
if err != nil {
t.Fatal(err)
}
defer env.Close()
tree, err := client.CreateAndInitTree(ctx, &trillian.CreateTreeRequest{
Tree: stestonly.LogTree,
}, env.Admin, env.Log)
if err != nil {
t.Fatalf("Failed to create log: %v", err)
}
params := DefaultTestParameters(tree.TreeId)
params.UniqueLeaves = 10
if err := RunLogIntegration(env.Log, params); err != nil {
t.Fatalf("Test failed: %v", err)
}
}