SSH server entry point - take 2 #99
@ -9,6 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.defalsify.org/vise.git/db"
|
"git.defalsify.org/vise.git/db"
|
||||||
|
"git.defalsify.org/vise.git/persist"
|
||||||
"git.defalsify.org/vise.git/resource"
|
"git.defalsify.org/vise.git/resource"
|
||||||
"git.defalsify.org/vise.git/state"
|
"git.defalsify.org/vise.git/state"
|
||||||
"git.grassecon.net/urdt/ussd/internal/mocks"
|
"git.grassecon.net/urdt/ussd/internal/mocks"
|
||||||
@ -16,6 +17,7 @@ import (
|
|||||||
"git.grassecon.net/urdt/ussd/internal/utils"
|
"git.grassecon.net/urdt/ussd/internal/utils"
|
||||||
"github.com/alecthomas/assert/v2"
|
"github.com/alecthomas/assert/v2"
|
||||||
testdataloader "github.com/peteole/testdata-loader"
|
testdataloader "github.com/peteole/testdata-loader"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -94,6 +96,25 @@ func TestCreateAccount(t *testing.T) {
|
|||||||
mockDataStore.AssertExpectations(t)
|
mockDataStore.AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWithPersister(t *testing.T) {
|
||||||
|
// Test case: Setting a persister
|
||||||
|
h := &Handlers{}
|
||||||
|
p := &persist.Persister{}
|
||||||
|
|
||||||
|
result := h.WithPersister(p)
|
||||||
|
|
||||||
|
assert.Equal(t, p, h.pe, "The persister should be set correctly.")
|
||||||
|
assert.Equal(t, h, result, "The returned handler should be the same instance.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithPersister_PanicWhenAlreadySet(t *testing.T) {
|
||||||
|
// Test case: Panic on multiple calls
|
||||||
|
h := &Handlers{pe: &persist.Persister{}}
|
||||||
|
require.Panics(t, func() {
|
||||||
|
h.WithPersister(&persist.Persister{})
|
||||||
|
}, "Should panic when trying to set a persister again.")
|
||||||
|
}
|
||||||
|
|
||||||
func TestSaveFirstname(t *testing.T) {
|
func TestSaveFirstname(t *testing.T) {
|
||||||
// Create a new instance of MockMyDataStore
|
// Create a new instance of MockMyDataStore
|
||||||
mockStore := new(mocks.MockUserDataStore)
|
mockStore := new(mocks.MockUserDataStore)
|
||||||
@ -295,6 +316,7 @@ func TestSaveOfferings(t *testing.T) {
|
|||||||
func TestSaveGender(t *testing.T) {
|
func TestSaveGender(t *testing.T) {
|
||||||
// Create a new instance of MockMyDataStore
|
// Create a new instance of MockMyDataStore
|
||||||
mockStore := new(mocks.MockUserDataStore)
|
mockStore := new(mocks.MockUserDataStore)
|
||||||
|
mockState := state.NewState(16)
|
||||||
|
|
||||||
// Define the session ID and context
|
// Define the session ID and context
|
||||||
sessionId := "session123"
|
sessionId := "session123"
|
||||||
@ -302,34 +324,32 @@ func TestSaveGender(t *testing.T) {
|
|||||||
|
|
||||||
// Define test cases
|
// Define test cases
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
input []byte
|
input []byte
|
||||||
expectedGender string
|
expectedGender string
|
||||||
expectCall bool
|
expectCall bool
|
||||||
|
executingSymbol string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Valid Male Input",
|
name: "Valid Male Input",
|
||||||
input: []byte("1"),
|
input: []byte("1"),
|
||||||
expectedGender: "Male",
|
expectedGender: "male",
|
||||||
expectCall: true,
|
executingSymbol: "set_male",
|
||||||
|
expectCall: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Valid Female Input",
|
name: "Valid Female Input",
|
||||||
input: []byte("2"),
|
input: []byte("2"),
|
||||||
expectedGender: "Female",
|
expectedGender: "female",
|
||||||
expectCall: true,
|
executingSymbol: "set_female",
|
||||||
|
expectCall: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Valid Unspecified Input",
|
name: "Valid Unspecified Input",
|
||||||
input: []byte("3"),
|
input: []byte("3"),
|
||||||
expectedGender: "Unspecified",
|
executingSymbol: "set_unspecified",
|
||||||
expectCall: true,
|
expectedGender: "unspecified",
|
||||||
},
|
expectCall: true,
|
||||||
{
|
|
||||||
name: "Empty Input",
|
|
||||||
input: []byte(""),
|
|
||||||
expectedGender: "",
|
|
||||||
expectCall: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,14 +362,15 @@ func TestSaveGender(t *testing.T) {
|
|||||||
} else {
|
} else {
|
||||||
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)).Return(nil)
|
mockStore.On("WriteEntry", ctx, sessionId, utils.DATA_GENDER, []byte(tt.expectedGender)).Return(nil)
|
||||||
}
|
}
|
||||||
|
mockState.ExecPath = append(mockState.ExecPath, tt.executingSymbol)
|
||||||
// Create the Handlers instance with the mock store
|
// Create the Handlers instance with the mock store
|
||||||
h := &Handlers{
|
h := &Handlers{
|
||||||
userdataStore: mockStore,
|
userdataStore: mockStore,
|
||||||
|
st: mockState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the method
|
// Call the method
|
||||||
_, err := h.SaveGender(ctx, "someSym", tt.input)
|
_, err := h.SaveGender(ctx, "save_gender", tt.input)
|
||||||
|
|
||||||
// Assert no error
|
// Assert no error
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -538,13 +559,13 @@ func TestSetLanguage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// Define test cases
|
// Define test cases
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
execPath []string
|
execPath []string
|
||||||
expectedResult resource.Result
|
expectedResult resource.Result
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Set Default Language (English)",
|
name: "Set Default Language (English)",
|
||||||
execPath: []string{"set_default"},
|
execPath: []string{"set_eng"},
|
||||||
expectedResult: resource.Result{
|
expectedResult: resource.Result{
|
||||||
FlagSet: []uint32{state.FLAG_LANG, 8},
|
FlagSet: []uint32{state.FLAG_LANG, 8},
|
||||||
Content: "eng",
|
Content: "eng",
|
||||||
@ -558,13 +579,6 @@ func TestSetLanguage(t *testing.T) {
|
|||||||
Content: "swa",
|
Content: "swa",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "Unhandled path",
|
|
||||||
execPath: []string{""},
|
|
||||||
expectedResult: resource.Result{
|
|
||||||
FlagSet: []uint32{8},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -592,76 +606,6 @@ func TestSetLanguage(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetResetSingleEdit(t *testing.T) {
|
|
||||||
fm, err := NewFlagManager(flagsPath)
|
|
||||||
|
|
||||||
flag_allow_update, _ := fm.parser.GetFlag("flag_allow_update")
|
|
||||||
flag_single_edit, _ := fm.parser.GetFlag("flag_single_edit")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
// Define test cases
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
input []byte
|
|
||||||
expectedResult resource.Result
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "Set single Edit",
|
|
||||||
input: []byte("2"),
|
|
||||||
expectedResult: resource.Result{
|
|
||||||
FlagSet: []uint32{flag_single_edit},
|
|
||||||
FlagReset: []uint32{flag_allow_update},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Set single Edit",
|
|
||||||
input: []byte("3"),
|
|
||||||
expectedResult: resource.Result{
|
|
||||||
FlagSet: []uint32{flag_single_edit},
|
|
||||||
FlagReset: []uint32{flag_allow_update},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Set single edit",
|
|
||||||
input: []byte("4"),
|
|
||||||
expectedResult: resource.Result{
|
|
||||||
FlagReset: []uint32{flag_allow_update},
|
|
||||||
FlagSet: []uint32{flag_single_edit},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "No single edit set",
|
|
||||||
input: []byte("1"),
|
|
||||||
expectedResult: resource.Result{
|
|
||||||
FlagReset: []uint32{flag_single_edit},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
|
|
||||||
// Create the Handlers instance with the mock flag manager
|
|
||||||
h := &Handlers{
|
|
||||||
flagManager: fm.parser,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the method
|
|
||||||
res, err := h.SetResetSingleEdit(context.Background(), "set_reset_single_edit", tt.input)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
// Assert that the Result FlagSet has the required flags after language switch
|
|
||||||
assert.Equal(t, res, tt.expectedResult, "Flags should match reset edit")
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestResetAllowUpdate(t *testing.T) {
|
func TestResetAllowUpdate(t *testing.T) {
|
||||||
fm, err := NewFlagManager(flagsPath)
|
fm, err := NewFlagManager(flagsPath)
|
||||||
|
|
||||||
@ -1480,7 +1424,7 @@ func TestValidateAmount(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf(err.Error())
|
t.Logf(err.Error())
|
||||||
}
|
}
|
||||||
//flag_invalid_amount, _ := fm.parser.GetFlag("flag_invalid_amount")
|
flag_invalid_amount, _ := fm.parser.GetFlag("flag_invalid_amount")
|
||||||
mockDataStore := new(mocks.MockUserDataStore)
|
mockDataStore := new(mocks.MockUserDataStore)
|
||||||
mockCreateAccountService := new(mocks.MockAccountService)
|
mockCreateAccountService := new(mocks.MockAccountService)
|
||||||
|
|
||||||
@ -1509,26 +1453,26 @@ func TestValidateAmount(t *testing.T) {
|
|||||||
Content: "0.001",
|
Content: "0.001",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// name: "Test with amount larger than balance",
|
name: "Test with amount larger than balance",
|
||||||
// input: []byte("0.02"),
|
input: []byte("0.02"),
|
||||||
// balance: "0.003 CELO",
|
balance: "0.003 CELO",
|
||||||
// publicKey: []byte("0xrqeqrequuq"),
|
publicKey: []byte("0xrqeqrequuq"),
|
||||||
// expectedResult: resource.Result{
|
expectedResult: resource.Result{
|
||||||
// FlagSet: []uint32{flag_invalid_amount},
|
FlagSet: []uint32{flag_invalid_amount},
|
||||||
// Content: "0.02",
|
Content: "0.02",
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
// {
|
{
|
||||||
// name: "Test with invalid amount",
|
name: "Test with invalid amount",
|
||||||
// input: []byte("0.02ms"),
|
input: []byte("0.02ms"),
|
||||||
// balance: "0.003 CELO",
|
balance: "0.003 CELO",
|
||||||
// publicKey: []byte("0xrqeqrequuq"),
|
publicKey: []byte("0xrqeqrequuq"),
|
||||||
// expectedResult: resource.Result{
|
expectedResult: resource.Result{
|
||||||
// FlagSet: []uint32{flag_invalid_amount},
|
FlagSet: []uint32{flag_invalid_amount},
|
||||||
// Content: "0.02ms",
|
Content: "0.02ms",
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -1536,7 +1480,7 @@ func TestValidateAmount(t *testing.T) {
|
|||||||
|
|
||||||
mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.publicKey, nil)
|
mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_PUBLIC_KEY).Return(tt.publicKey, nil)
|
||||||
mockCreateAccountService.On("CheckBalance", string(tt.publicKey)).Return(tt.balance, nil)
|
mockCreateAccountService.On("CheckBalance", string(tt.publicKey)).Return(tt.balance, nil)
|
||||||
mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, tt.input).Return(nil)
|
mockDataStore.On("WriteEntry", ctx, sessionId, utils.DATA_AMOUNT, tt.input).Return(nil).Maybe()
|
||||||
|
|
||||||
// Call the method under test
|
// Call the method under test
|
||||||
res, _ := h.ValidateAmount(ctx, "test_validate_amount", tt.input)
|
res, _ := h.ValidateAmount(ctx, "test_validate_amount", tt.input)
|
||||||
@ -1648,6 +1592,7 @@ func TestGetProfile(t *testing.T) {
|
|||||||
|
|
||||||
mockDataStore := new(mocks.MockUserDataStore)
|
mockDataStore := new(mocks.MockUserDataStore)
|
||||||
mockCreateAccountService := new(mocks.MockAccountService)
|
mockCreateAccountService := new(mocks.MockAccountService)
|
||||||
|
|
||||||
h := &Handlers{
|
h := &Handlers{
|
||||||
userdataStore: mockDataStore,
|
userdataStore: mockDataStore,
|
||||||
accountService: mockCreateAccountService,
|
accountService: mockCreateAccountService,
|
||||||
|
43
internal/storage/db.go
Normal file
43
internal/storage/db.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.defalsify.org/vise.git/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DATATYPE_USERSUB = 64
|
||||||
|
)
|
||||||
|
|
||||||
|
type SubPrefixDb struct {
|
||||||
|
store db.Db
|
||||||
|
pfx []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSubPrefixDb(store db.Db, pfx []byte) *SubPrefixDb {
|
||||||
|
return &SubPrefixDb{
|
||||||
|
store: store,
|
||||||
|
pfx: pfx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func(s *SubPrefixDb) toKey(k []byte) []byte {
|
||||||
|
return append(s.pfx, k...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func(s *SubPrefixDb) Get(ctx context.Context, key []byte) ([]byte, error) {
|
||||||
|
s.store.SetPrefix(DATATYPE_USERSUB)
|
||||||
|
key = s.toKey(key)
|
||||||
|
v, err := s.store.Get(ctx, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func(s *SubPrefixDb) Put(ctx context.Context, key []byte, val []byte) error {
|
||||||
|
s.store.SetPrefix(DATATYPE_USERSUB)
|
||||||
|
key = s.toKey(key)
|
||||||
|
return s.store.Put(ctx, key, val)
|
||||||
|
}
|
54
internal/storage/db_test.go
Normal file
54
internal/storage/db_test.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
memdb "git.defalsify.org/vise.git/db/mem"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSubPrefix(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
db := memdb.NewMemDb()
|
||||||
|
err := db.Connect(ctx, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
sdba := NewSubPrefixDb(db, []byte("tinkywinky"))
|
||||||
|
err = sdba.Put(ctx, []byte("foo"), []byte("dipsy"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := sdba.Get(ctx, []byte("foo"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(r, []byte("dipsy")) {
|
||||||
|
t.Fatalf("expected 'dipsy', got %s", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
sdbb := NewSubPrefixDb(db, []byte("lala"))
|
||||||
|
r, err = sdbb.Get(ctx, []byte("foo"))
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sdbb.Put(ctx, []byte("foo"), []byte("pu"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
r, err = sdbb.Get(ctx, []byte("foo"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(r, []byte("pu")) {
|
||||||
|
t.Fatalf("expected 'pu', got %s", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err = sdba.Get(ctx, []byte("foo"))
|
||||||
|
if !bytes.Equal(r, []byte("dipsy")) {
|
||||||
|
t.Fatalf("expected 'dipsy', got %s", r)
|
||||||
|
}
|
||||||
|
}
|
@ -5,10 +5,6 @@ import (
|
|||||||
"git.defalsify.org/vise.git/persist"
|
"git.defalsify.org/vise.git/persist"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
DATATYPE_CUSTOM = 128
|
|
||||||
)
|
|
||||||
|
|
||||||
type Storage struct {
|
type Storage struct {
|
||||||
Persister *persist.Persister
|
Persister *persist.Persister
|
||||||
UserdataDb db.Db
|
UserdataDb db.Db
|
||||||
|
Loading…
Reference in New Issue
Block a user