Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/storage/rqstore/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const createRQSymbolsDir string = `
PRIMARY KEY (txid)
);`

//go:generate mockgen -destination=rq_mock.go -package=rqstore -source=store.go
type Store interface {
DeleteSymbolsByTxID(txid string) error
StoreSymbolDirectory(txid, dir string) error
Expand Down
53 changes: 53 additions & 0 deletions supernode/cmd/keys_add_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package cmd_test

import (
"bytes"
"testing"

"github.com/LumeraProtocol/supernode/pkg/keyring"
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
)

func TestKeysAddCmd_RunE(t *testing.T) {
cmd := getTestKeysAddCmd(t)

tests := []struct {
name string
args []string
wantErr bool
}{
{"no_name_arg", []string{}, false},
{"with_name_arg", []string{"testkey"}, false},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
buf := new(bytes.Buffer)
cmd.SetOut(buf)
cmd.SetArgs(tt.args)

err := cmd.Execute()
if (err != nil) != tt.wantErr {
t.Errorf("unexpected error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

// getTestKeysAddCmd initializes and returns a test instance of the cobra.Command for keys add.
func getTestKeysAddCmd(t *testing.T) *cobra.Command {
return &cobra.Command{
Use: "add",
RunE: func(cmd *cobra.Command, args []string) error {
name := "testkey"
if len(args) > 0 {
name = args[0]
}
kr, err := keyring.InitKeyring("test", "/tmp")
require.NoError(t, err)
_, _, err = keyring.CreateNewAccount(kr, name)
return err
},
}
}
79 changes: 79 additions & 0 deletions supernode/cmd/service_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package cmd

import (
"context"
"errors"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

// mockService implements the service interface
type mockService struct {
name string
runFunc func(ctx context.Context) error
}

func (m *mockService) Run(ctx context.Context) error {
return m.runFunc(ctx)
}

func TestRunServices_AllSuccessful(t *testing.T) {
s1 := &mockService{name: "s1", runFunc: func(ctx context.Context) error {
return nil
}}
s2 := &mockService{name: "s2", runFunc: func(ctx context.Context) error {
return nil
}}

err := RunServices(context.Background(), s1, s2)
assert.NoError(t, err)
}

func TestRunServices_OneFails(t *testing.T) {
s1 := &mockService{name: "s1", runFunc: func(ctx context.Context) error {
return errors.New("s1 failed")
}}
s2 := &mockService{name: "s2", runFunc: func(ctx context.Context) error {
return nil
}}

err := RunServices(context.Background(), s1, s2)
assert.Error(t, err)
assert.Equal(t, "s1 failed", err.Error())
}

func TestRunServices_MultipleFail(t *testing.T) {
s1 := &mockService{name: "s1", runFunc: func(ctx context.Context) error {
return errors.New("s1 failed")
}}
s2 := &mockService{name: "s2", runFunc: func(ctx context.Context) error {
return errors.New("s2 failed")
}}

err := RunServices(context.Background(), s1, s2)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed") // may not be deterministic which one returns
}

func TestRunServices_WithCancellation(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())

s1 := &mockService{name: "s1", runFunc: func(ctx context.Context) error {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(2 * time.Second):
return nil
}
}}
s2 := &mockService{name: "s2", runFunc: func(ctx context.Context) error {
cancel() // cancel context early
return nil
}}

err := RunServices(ctx, s1, s2)
assert.Error(t, err)
assert.Equal(t, context.Canceled, err)
}
41 changes: 41 additions & 0 deletions supernode/node/action/server/cascade/cascade_action_server_mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package cascade

import (
"context"
"io"

pb "github.com/LumeraProtocol/supernode/gen/supernode/action/cascade"
"google.golang.org/grpc/metadata"
)

// mockStream simulates pb.CascadeService_RegisterServer
type mockStream struct {
ctx context.Context
request []*pb.RegisterRequest
sent []*pb.RegisterResponse
pos int
}

func (m *mockStream) Context() context.Context {
return m.ctx
}

func (m *mockStream) Send(resp *pb.RegisterResponse) error {
m.sent = append(m.sent, resp)
return nil
}

func (m *mockStream) Recv() (*pb.RegisterRequest, error) {
if m.pos >= len(m.request) {
return nil, io.EOF
}
req := m.request[m.pos]
m.pos++
return req, nil
}

func (m *mockStream) SetHeader(md metadata.MD) error { return nil }
func (m *mockStream) SendHeader(md metadata.MD) error { return nil }
func (m *mockStream) SetTrailer(md metadata.MD) {}
func (m *mockStream) SendMsg(_ any) error { return nil }
func (m *mockStream) RecvMsg(_ any) error { return nil }
97 changes: 97 additions & 0 deletions supernode/node/action/server/cascade/cascade_action_server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package cascade

import (
"context"
"errors"
"testing"

pb "github.com/LumeraProtocol/supernode/gen/supernode/action/cascade"
"github.com/LumeraProtocol/supernode/supernode/services/cascade"
cascademocks "github.com/LumeraProtocol/supernode/supernode/services/cascade/mocks"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)

func TestRegister_Success(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockTask := cascademocks.NewMockRegistrationTaskService(ctrl)
mockFactory := cascademocks.NewMockTaskFactory(ctrl)

// Expect Register to be called with any input, respond via callback
mockTask.EXPECT().Register(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(
func(ctx context.Context, req *cascade.RegisterRequest, send func(*cascade.RegisterResponse) error) error {
return send(&cascade.RegisterResponse{
EventType: 1,
Message: "registration successful",
TxHash: "tx123",
})
},
).Times(1)

mockFactory.EXPECT().NewCascadeRegistrationTask().Return(mockTask).Times(1)

server := NewCascadeActionServer(mockFactory)

stream := &mockStream{
ctx: context.Background(),
request: []*pb.RegisterRequest{
{RequestType: &pb.RegisterRequest_Chunk{Chunk: &pb.DataChunk{Data: []byte("abc123")}}},
{RequestType: &pb.RegisterRequest_Metadata{
Metadata: &pb.Metadata{TaskId: "t1", ActionId: "a1"},
}},
},
}

err := server.Register(stream)
assert.NoError(t, err)
assert.Len(t, stream.sent, 1)
assert.Equal(t, "registration successful", stream.sent[0].Message)
assert.Equal(t, "tx123", stream.sent[0].TxHash)
}

func TestRegister_Error_NoMetadata(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockFactory := cascademocks.NewMockTaskFactory(ctrl)
server := NewCascadeActionServer(mockFactory)

stream := &mockStream{
ctx: context.Background(),
request: []*pb.RegisterRequest{
{RequestType: &pb.RegisterRequest_Chunk{Chunk: &pb.DataChunk{Data: []byte("abc123")}}},
},
}

err := server.Register(stream)
assert.EqualError(t, err, "no metadata received")
}

func TestRegister_Error_TaskFails(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockTask := cascademocks.NewMockRegistrationTaskService(ctrl)
mockFactory := cascademocks.NewMockTaskFactory(ctrl)

mockTask.EXPECT().Register(gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("task failed")).Times(1)
mockFactory.EXPECT().NewCascadeRegistrationTask().Return(mockTask).Times(1)

server := NewCascadeActionServer(mockFactory)

stream := &mockStream{
ctx: context.Background(),
request: []*pb.RegisterRequest{
{RequestType: &pb.RegisterRequest_Chunk{Chunk: &pb.DataChunk{Data: []byte("abc123")}}},
{RequestType: &pb.RegisterRequest_Metadata{
Metadata: &pb.Metadata{TaskId: "t1", ActionId: "a1"},
}},
},
}

err := server.Register(stream)
assert.EqualError(t, err, "registration failed: task failed")
}
16 changes: 16 additions & 0 deletions supernode/node/supernode/server/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package server

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestNewConfig_Defaults(t *testing.T) {
cfg := NewConfig()

assert.NotNil(t, cfg)
assert.Equal(t, "0.0.0.0", cfg.ListenAddresses, "default listen address should be 0.0.0.0")
assert.Equal(t, 4444, cfg.Port, "default port should be 4444")
assert.Equal(t, "", cfg.Identity, "default identity should be empty")
}
Loading