Compare commits

..

26 Commits

Author SHA1 Message Date
lash
cb997159f7 Add reverse sessionid address lookup 2024-10-30 00:59:59 +00:00
727f54ee57 Merge pull request 'tests-refactor' (#137) from tests-refactor into master
Reviewed-on: urdt/ussd#137
2024-10-28 16:28:41 +01:00
Carlosokumu
4e1b2d5ddb update account services 2024-10-25 18:01:52 +03:00
Carlosokumu
d8800a665d Merge branch 'master' into tests-refactor 2024-10-25 17:48:40 +03:00
Carlosokumu
3792bfdc1f run mod tidy 2024-10-25 09:38:09 +03:00
Carlosokumu
a0e97cfe5b remove test account service implementation 2024-10-25 09:37:16 +03:00
Carlosokumu
a3be98c514 update test account service 2024-10-25 09:36:43 +03:00
Carlosokumu
2b34b3a75c Merge branch 'master' into tests-refactor 2024-10-25 09:14:16 +03:00
Carlosokumu
f99486c190 correct import 2024-10-24 12:07:00 +03:00
Carlosokumu
57a07af8ca correct import 2024-10-24 12:06:44 +03:00
Carlosokumu
5692440099 move to testutil 2024-10-24 12:05:27 +03:00
Carlosokumu
651969668f move to testutil 2024-10-24 12:05:11 +03:00
Carlosokumu
f3a028f1fc move to testutil 2024-10-24 12:03:32 +03:00
Carlosokumu
1e6cf6a33a run mod tidy 2024-10-23 11:08:51 +03:00
Carlosokumu
2725323f16 Merge branch 'master' into tests-refactor 2024-10-23 11:06:10 +03:00
Carlosokumu
306666a15e load and reload after halt 2024-10-22 20:37:30 +03:00
Carlosokumu
e05dbb4885 check for back option 2024-10-22 20:36:58 +03:00
Carlosokumu
eaac771722 move into testtag package 2024-10-21 16:48:24 +03:00
Carlosokumu
f3a5178de7 update imports 2024-10-21 16:47:43 +03:00
Carlosokumu
549d09890b update imports 2024-10-21 16:47:25 +03:00
Carlosokumu
4a9ef6b5f2 move test account service to testutil 2024-10-21 16:47:00 +03:00
Carlosokumu
961d8d1a5c update package import 2024-10-21 16:46:29 +03:00
Carlosokumu
a904cdbf44 move driver to testutil 2024-10-21 16:45:06 +03:00
Carlosokumu
3af943f77c move account service tags switch to test tags package 2024-10-21 16:44:02 +03:00
Carlosokumu
14455f65cb move account service to testutil 2024-10-21 16:43:24 +03:00
Carlosokumu
0c08654df3 move driver to testutil 2024-10-21 16:42:57 +03:00
24 changed files with 185 additions and 135 deletions

18
common/hex.go Normal file
View File

@@ -0,0 +1,18 @@
package common
import (
"encoding/hex"
)
func NormalizeHex(s string) (string, error) {
if len(s) >= 2 {
if s[:2] == "0x" {
s = s[2:]
}
}
r, err := hex.DecodeString(s)
if err != nil {
return "", err
}
return hex.EncodeToString(r), nil
}

9
go.mod
View File

@@ -7,19 +7,17 @@ toolchain go1.23.2
require (
git.defalsify.org/vise.git v0.2.1-0.20241017112704-307fa6fcdc6b
github.com/alecthomas/assert/v2 v2.2.2
github.com/grassrootseconomics/eth-custodial v1.3.0-beta
github.com/peteole/testdata-loader v0.3.0
gopkg.in/leonelquinteros/gotext.v1 v1.3.1
)
require github.com/joho/godotenv v1.5.1
require (
github.com/grassrootseconomics/eth-custodial v1.3.0-beta
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.7.1 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/joho/godotenv v1.5.1
github.com/kr/text v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
golang.org/x/crypto v0.27.0 // indirect
@@ -42,7 +40,4 @@ require (
github.com/stretchr/testify v1.9.0
github.com/x448/float16 v0.8.4 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@@ -8,7 +8,6 @@ import (
"io"
"net/http"
"os"
"time"
"git.grassecon.net/urdt/ussd/config"
"git.grassecon.net/urdt/ussd/internal/models"
@@ -31,9 +30,6 @@ type AccountServiceInterface interface {
type AccountService struct {
}
type TestAccountService struct {
}
// Parameters:
// - trackingId: A unique identifier for the account.This should be obtained from a previous call to
// CreateAccount or a similar function that returns an AccountResponse. The `trackingId` field in the
@@ -187,88 +183,3 @@ func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) (
}
return &holdings, nil
}
func (tas *TestAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) {
return &api.OKResponse{
Ok: true,
Description: "Account creation request received successfully",
Result: map[string]any{"publicKey": "0x48ADca309b5085852207FAaf2816eD72B52F527C", "trackingId": "28ebe84d-b925-472c-87ae-bbdfa1fb97be"},
}, nil
}
func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) {
balanceResponse := &models.BalanceResponse{
Ok: true,
Result: struct {
Balance string `json:"balance"`
Nonce json.Number `json:"nonce"`
}{
Balance: "0.003 CELO",
Nonce: json.Number("0"),
},
}
return balanceResponse, nil
}
func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) {
return &api.OKResponse{
Ok: true,
Description: "Account creation succeeded",
Result: map[string]any{
"active": true,
},
}, nil
}
func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) {
trackResponse := &models.TrackStatusResponse{
Ok: true,
Result: struct {
Transaction struct {
CreatedAt time.Time "json:\"createdAt\""
Status string "json:\"status\""
TransferValue json.Number "json:\"transferValue\""
TxHash string "json:\"txHash\""
TxType string "json:\"txType\""
}
}{
Transaction: models.Transaction{
CreatedAt: time.Now(),
Status: "SUCCESS",
TransferValue: json.Number("0.5"),
TxHash: "0x123abc456def",
TxType: "transfer",
},
},
}
return trackResponse, nil
}
func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) {
return &models.VoucherHoldingResponse{
Ok: true,
Result: struct {
Holdings []struct {
ContractAddress string `json:"contractAddress"`
TokenSymbol string `json:"tokenSymbol"`
TokenDecimals string `json:"tokenDecimals"`
Balance string `json:"balance"`
} `json:"holdings"`
}{
Holdings: []struct {
ContractAddress string `json:"contractAddress"`
TokenSymbol string `json:"tokenSymbol"`
TokenDecimals string `json:"tokenDecimals"`
Balance string `json:"balance"`
}{
{
ContractAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee",
TokenSymbol: "SRF",
TokenDecimals: "6",
Balance: "2745987",
},
},
},
}, nil
}

View File

@@ -21,6 +21,7 @@ import (
"git.defalsify.org/vise.git/state"
"git.grassecon.net/urdt/ussd/internal/handlers/server"
"git.grassecon.net/urdt/ussd/internal/utils"
"git.grassecon.net/urdt/ussd/common"
"gopkg.in/leonelquinteros/gotext.v1"
"git.grassecon.net/urdt/ussd/internal/storage"
@@ -32,6 +33,7 @@ var (
translationDir = path.Join(scriptDir, "locale")
okResponse *api.OKResponse
errResponse *api.ErrResponse
backOption = []byte("0")
)
// FlagManager handles centralized flag management
@@ -152,15 +154,22 @@ func (h *Handlers) createAccountNoExist(ctx context.Context, sessionId string, r
data := map[utils.DataTyp]string{
utils.DATA_TRACKING_ID: trackingId,
utils.DATA_PUBLIC_KEY: publicKey,
utils.DATA_ADDRESS: sessionId,
}
store := h.userdataStore
for key, value := range data {
store := h.userdataStore
err := store.WriteEntry(ctx, sessionId, key, []byte(value))
err = store.WriteEntry(ctx, sessionId, key, []byte(value))
if err != nil {
return err
}
}
publicKeyNormalized, err := common.NormalizeHex(publicKey)
if err != nil {
return err
}
err = store.WriteEntry(ctx, publicKeyNormalized, utils.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId))
if err != nil {
return err
}
res.FlagSet = append(res.FlagSet, flag_account_created)
return nil
@@ -321,6 +330,9 @@ func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte)
return res, fmt.Errorf("missing session")
}
if len(input) > 0 {
if bytes.Equal(input, backOption) {
return res, nil
}
firstName := string(input)
store := h.userdataStore
err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName))
@@ -340,8 +352,10 @@ func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte)
if !ok {
return res, fmt.Errorf("missing session")
}
if len(input) > 0 {
if bytes.Equal(input, backOption) {
return res, nil
}
familyName := string(input)
store := h.userdataStore
err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName))
@@ -383,8 +397,10 @@ func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) (
if !ok {
return res, fmt.Errorf("missing session")
}
if len(input) > 0 {
if bytes.Equal(input, backOption) {
return res, nil
}
location := string(input)
store := h.userdataStore
err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(location))
@@ -405,6 +421,9 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re
if !ok {
return res, fmt.Errorf("missing session")
}
if bytes.Equal(input, backOption) {
return res, nil
}
gender := strings.Split(symbol, "_")[1]
store := h.userdataStore
err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(gender))
@@ -533,7 +552,6 @@ func (h *Handlers) CheckAccountStatus(ctx context.Context, sym string, input []b
if err != nil {
return res, err
}
okResponse, err = h.accountService.TrackAccountStatus(ctx, string(publicKey))
if err != nil {
res.FlagSet = append(res.FlagSet, flag_api_error)

View File

@@ -15,10 +15,12 @@ import (
"git.defalsify.org/vise.git/persist"
"git.defalsify.org/vise.git/resource"
"git.defalsify.org/vise.git/state"
"git.grassecon.net/urdt/ussd/internal/handlers/server"
"git.grassecon.net/urdt/ussd/internal/mocks"
"git.grassecon.net/urdt/ussd/internal/models"
"git.grassecon.net/urdt/ussd/internal/testutil/mocks"
"git.grassecon.net/urdt/ussd/internal/testutil/testservice"
"git.grassecon.net/urdt/ussd/internal/utils"
"git.grassecon.net/urdt/ussd/common"
"github.com/alecthomas/assert/v2"
"github.com/grassrootseconomics/eth-custodial/pkg/api"
testdataloader "github.com/peteole/testdata-loader"
@@ -32,7 +34,7 @@ var (
func TestNewHandlers(t *testing.T) {
fm, err := NewFlagManager(flagsPath)
accountService := server.TestAccountService{}
accountService := testservice.TestAccountService{}
if err != nil {
t.Logf(err.Error())
}
@@ -95,7 +97,7 @@ func TestCreateAccount(t *testing.T) {
Description: "Account creation successed",
Result: map[string]any{
"trackingId": "1234567890",
"publicKey": "1235QERYU",
"publicKey": "0xD3adB33f",
},
},
expectedResult: resource.Result{
@@ -116,9 +118,10 @@ func TestCreateAccount(t *testing.T) {
flagManager: fm.parser,
}
publicKey := tt.serverResponse.Result["publicKey"].(string)
data := map[utils.DataTyp]string{
utils.DATA_TRACKING_ID: tt.serverResponse.Result["trackingId"].(string),
utils.DATA_PUBLIC_KEY: tt.serverResponse.Result["publicKey"].(string),
utils.DATA_PUBLIC_KEY: publicKey,
}
mockDataStore.On("ReadEntry", ctx, sessionId, utils.DATA_ACCOUNT_CREATED).Return([]byte(""), notFoundErr)
@@ -127,6 +130,12 @@ func TestCreateAccount(t *testing.T) {
for key, value := range data {
mockDataStore.On("WriteEntry", ctx, sessionId, key, []byte(value)).Return(nil)
}
publicKeyNormalized, err := common.NormalizeHex(publicKey)
if err != nil {
t.Fatal(err)
}
mockDataStore.On("WriteEntry", ctx, publicKeyNormalized, utils.DATA_PUBLIC_KEY_REVERSE, []byte(sessionId)).Return(nil)
// Call the method you want to test
res, err := h.CreateAccount(ctx, "create_account", []byte("some-input"))

View File

@@ -13,7 +13,7 @@ import (
"git.defalsify.org/vise.git/engine"
"git.grassecon.net/urdt/ussd/internal/handlers"
"git.grassecon.net/urdt/ussd/internal/mocks/httpmocks"
"git.grassecon.net/urdt/ussd/internal/testutil/mocks/httpmocks"
)
// invalidRequestType is a custom type to test invalid request scenarios

View File

@@ -13,6 +13,8 @@ import (
"git.grassecon.net/urdt/ussd/internal/handlers"
"git.grassecon.net/urdt/ussd/internal/handlers/server"
"git.grassecon.net/urdt/ussd/internal/storage"
"git.grassecon.net/urdt/ussd/internal/testutil/testservice"
"git.grassecon.net/urdt/ussd/internal/testutil/testtag"
testdataloader "github.com/peteole/testdata-loader"
)
@@ -80,12 +82,12 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool) {
os.Exit(1)
}
if AccountService == nil {
AccountService = &server.AccountService{}
if testtag.AccountService == nil {
testtag.AccountService = &server.AccountService{}
}
switch AccountService.(type) {
case *server.TestAccountService:
switch testtag.AccountService.(type) {
case *testservice.TestAccountService:
go func() {
eventChannel <- false
}()
@@ -98,7 +100,7 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool) {
panic("Unknown account service type")
}
hl, err := lhs.GetHandler(AccountService)
hl, err := lhs.GetHandler(testtag.AccountService)
if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
os.Exit(1)

View File

@@ -1,11 +0,0 @@
// +build !online
package testutil
import (
"git.grassecon.net/urdt/ussd/internal/handlers/server"
)
var (
AccountService server.AccountServiceInterface = &server.TestAccountService{}
)

View File

@@ -0,0 +1,101 @@
package testservice
import (
"context"
"encoding/json"
"time"
"git.grassecon.net/urdt/ussd/internal/models"
"github.com/grassrootseconomics/eth-custodial/pkg/api"
)
type TestAccountService struct {
}
func (tas *TestAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) {
return &api.OKResponse{
Ok: true,
Description: "Account creation succeeded",
Result: map[string]any{
"trackingId": "075ccc86-f6ef-4d33-97d5-e91cfb37aa0d",
"publicKey": "0x623EFAFa8868df4B934dd12a8B26CB3Dd75A7AdD",
},
}, nil
}
func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) {
balanceResponse := &models.BalanceResponse{
Ok: true,
Result: struct {
Balance string `json:"balance"`
Nonce json.Number `json:"nonce"`
}{
Balance: "0.003 CELO",
Nonce: json.Number("0"),
},
}
return balanceResponse, nil
}
func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) {
trackResponse := &models.TrackStatusResponse{
Ok: true,
Result: struct {
Transaction struct {
CreatedAt time.Time "json:\"createdAt\""
Status string "json:\"status\""
TransferValue json.Number "json:\"transferValue\""
TxHash string "json:\"txHash\""
TxType string "json:\"txType\""
}
}{
Transaction: models.Transaction{
CreatedAt: time.Now(),
Status: "SUCCESS",
TransferValue: json.Number("0.5"),
TxHash: "0x123abc456def",
TxType: "transfer",
},
},
}
return trackResponse, nil
}
func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) {
return &api.OKResponse{
Ok: true,
Description: "Account creation succeeded",
Result: map[string]any{
"active": true,
},
}, nil
}
func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) {
return &models.VoucherHoldingResponse{
Ok: true,
Result: struct {
Holdings []struct {
ContractAddress string `json:"contractAddress"`
TokenSymbol string `json:"tokenSymbol"`
TokenDecimals string `json:"tokenDecimals"`
Balance string `json:"balance"`
} `json:"holdings"`
}{
Holdings: []struct {
ContractAddress string `json:"contractAddress"`
TokenSymbol string `json:"tokenSymbol"`
TokenDecimals string `json:"tokenDecimals"`
Balance string `json:"balance"`
}{
{
ContractAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee",
TokenSymbol: "SRF",
TokenDecimals: "6",
Balance: "2745987",
},
},
},
}, nil
}

View File

@@ -0,0 +1,12 @@
// +build !online
package testtag
import (
"git.grassecon.net/urdt/ussd/internal/handlers/server"
accountservice "git.grassecon.net/urdt/ussd/internal/testutil/testservice"
)
var (
AccountService server.AccountServiceInterface = &accountservice.TestAccountService{}
)

View File

@@ -1,6 +1,6 @@
// +build online
package testutil
package testtag
import "git.grassecon.net/urdt/ussd/internal/handlers/server"

View File

@@ -28,7 +28,7 @@ const (
DATA_ACTIVE_SYM
DATA_TEMPORARY_BAL
DATA_ACTIVE_BAL
DATA_ADDRESS
DATA_PUBLIC_KEY_REVERSE
)
func typToBytes(typ DataTyp) []byte {

View File

@@ -9,8 +9,8 @@ import (
"regexp"
"testing"
"git.grassecon.net/urdt/ussd/driver"
"git.grassecon.net/urdt/ussd/internal/testutil"
"git.grassecon.net/urdt/ussd/internal/testutil/driver"
"github.com/gofrs/uuid"
)

View File

@@ -1,9 +1,8 @@
CATCH incorrect_pin flag_incorrect_pin 1
CATCH profile_update_success flag_allow_update 1
LOAD save_familyname 0
RELOAD save_familyname
MOUT back 0
HALT
LOAD save_familyname 0
RELOAD save_familyname
INCMP _ 0
INCMP pin_entry *

View File

@@ -1,8 +1,8 @@
CATCH incorrect_pin flag_incorrect_pin 1
CATCH profile_update_success flag_allow_update 1
LOAD save_location 0
MOUT back 0
HALT
LOAD save_location 0
RELOAD save_location
INCMP _ 0
INCMP pin_entry *

View File

@@ -1,12 +1,8 @@
CATCH incorrect_pin flag_incorrect_pin 1
CATCH profile_update_success flag_allow_update 1
LOAD save_firstname 0
RELOAD save_firstname
MOUT back 0
HALT
LOAD save_firstname 0
RELOAD save_firstname
INCMP _ 0
INCMP pin_entry *