Files

80 lines
3.1 KiB
Go

package main
import (
"context"
"testing"
"time"
ledgerv1 "gl/gen/ledger/v1"
"google.golang.org/grpc"
)
type clientStub struct {
journal *ledgerv1.AppendJournalRequest
events []*ledgerv1.AppendTransactionEventRequest
balance *ledgerv1.GetBalanceRequest
lookup *ledgerv1.GetJournalRequest
}
func (s *clientStub) AppendJournal(_ context.Context, request *ledgerv1.AppendJournalRequest, _ ...grpc.CallOption) (*ledgerv1.AppendJournalResponse, error) {
s.journal = request
return &ledgerv1.AppendJournalResponse{Journal: &ledgerv1.Journal{JournalId: "journal-1"}}, nil
}
func (s *clientStub) AppendTransactionEvent(_ context.Context, request *ledgerv1.AppendTransactionEventRequest, _ ...grpc.CallOption) (*ledgerv1.AppendTransactionEventResponse, error) {
s.events = append(s.events, request)
return &ledgerv1.AppendTransactionEventResponse{}, nil
}
func (s *clientStub) GetJournal(_ context.Context, request *ledgerv1.GetJournalRequest, _ ...grpc.CallOption) (*ledgerv1.Journal, error) {
s.lookup = request
return &ledgerv1.Journal{JournalId: "journal-1"}, nil
}
func (s *clientStub) GetBalance(_ context.Context, request *ledgerv1.GetBalanceRequest, _ ...grpc.CallOption) (*ledgerv1.GetBalanceResponse, error) {
s.balance = request
return &ledgerv1.GetBalanceResponse{Balance: "1"}, nil
}
func TestRunTransactionCreatesWalletAccountsAndFullLifecycle(t *testing.T) {
ledger := &clientStub{}
samples := runTransaction(context.Background(), ledger, config{
RunID: "test-run", Wallets: 10, AssetID: 7, Amount: "2.5", RequestTimeout: time.Second,
}, 3)
if len(samples) != 5 {
t.Fatalf("expected five RPC measurements, got %d", len(samples))
}
if ledger.journal == nil || len(ledger.journal.Entries) != 2 {
t.Fatal("balanced journal was not appended")
}
debit, credit := ledger.journal.Entries[0], ledger.journal.Entries[1]
if debit.Amount != "-2.5" || credit.Amount != "2.5" {
t.Fatalf("unexpected journal amounts: %q and %q", debit.Amount, credit.Amount)
}
if debit.Account.OwnerId == credit.Account.OwnerId || debit.Account.AssetId != 7 || credit.Account.AssetId != 7 {
t.Fatalf("unexpected simulated wallets: debit=%+v credit=%+v", debit.Account, credit.Account)
}
if len(ledger.events) != 2 || ledger.events[0].State != ledgerv1.TransactionState_TRANSACTION_STATE_CREATED || ledger.events[1].State != ledgerv1.TransactionState_TRANSACTION_STATE_SUCCESSFUL {
t.Fatalf("unexpected transaction lifecycle: %+v", ledger.events)
}
if ledger.lookup.GetJournalId() != "journal-1" || ledger.balance.Account.OwnerId != credit.Account.OwnerId {
t.Fatal("journal and balance reads did not follow the write")
}
}
func TestTransactionHashIsStableAndUnique(t *testing.T) {
first := transactionHash("run-1")
if len(first) != 64 || first != transactionHash("run-1") || first == transactionHash("run-2") {
t.Fatalf("unexpected transaction hashes: %q", first)
}
}
func TestPercentileUsesNearestRank(t *testing.T) {
values := []time.Duration{time.Millisecond, 4 * time.Millisecond, 2 * time.Millisecond, 3 * time.Millisecond}
if got := percentile(values, 95); got != 4*time.Millisecond {
t.Fatalf("unexpected p95: %s", got)
}
}