Files
sonr/x/svc/keeper/keeper_test.go
Prad NukalaandGitHub 13e6c3e84d Master (#1262)
* clear

* feat: Add everything

* fix: Commenht
2025-10-03 14:45:52 -04:00

388 lines
11 KiB
Go

package keeper_test
import (
"context"
"testing"
"github.com/stretchr/testify/suite"
"cosmossdk.io/core/address"
"cosmossdk.io/log"
storetypes "cosmossdk.io/store/types"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
sdkaddress "github.com/cosmos/cosmos-sdk/codec/address"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil/integration"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/sonr-io/sonr/app"
didtypes "github.com/sonr-io/sonr/x/did/types"
module "github.com/sonr-io/sonr/x/svc"
"github.com/sonr-io/sonr/x/svc/keeper"
"github.com/sonr-io/sonr/x/svc/types"
)
var maccPerms = map[string][]string{
authtypes.FeeCollectorName: nil,
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
minttypes.ModuleName: {authtypes.Minter},
govtypes.ModuleName: {authtypes.Burner},
}
// SVCMockDIDKeeper provides a minimal mock implementation for SVC testing
type SVCMockDIDKeeper struct{}
func (m *SVCMockDIDKeeper) ResolveDID(
ctx context.Context,
did string,
) (*didtypes.DIDDocument, *didtypes.DIDDocumentMetadata, error) {
if did == "did:example:deactivated" {
return &didtypes.DIDDocument{
Id: did,
Deactivated: true,
}, &didtypes.DIDDocumentMetadata{
Did: did,
}, nil
}
if did == "did:example:no-verification" {
return &didtypes.DIDDocument{
Id: did,
VerificationMethod: []*didtypes.VerificationMethod{},
}, &didtypes.DIDDocumentMetadata{
Did: did,
}, nil
}
return &didtypes.DIDDocument{
Id: did,
VerificationMethod: []*didtypes.VerificationMethod{{Id: did + "#key-1"}},
}, &didtypes.DIDDocumentMetadata{Did: did}, nil
}
func (m *SVCMockDIDKeeper) GetDIDDocument(
ctx context.Context,
did string,
) (*didtypes.DIDDocument, error) {
if did == "did:example:deactivated" {
return &didtypes.DIDDocument{Id: did, Deactivated: true}, nil
}
if did == "did:example:no-verification" {
return &didtypes.DIDDocument{
Id: did,
VerificationMethod: []*didtypes.VerificationMethod{},
}, nil
}
return &didtypes.DIDDocument{
Id: did,
VerificationMethod: []*didtypes.VerificationMethod{{Id: did + "#key-1"}},
}, nil
}
func (m *SVCMockDIDKeeper) VerifyDIDDocumentSignature(
ctx context.Context,
did string,
signature []byte,
) (bool, error) {
return true, nil
}
type testFixture struct {
suite.Suite
ctx sdk.Context
k keeper.Keeper
msgServer types.MsgServer
queryServer types.QueryServer
appModule *module.AppModule
accountkeeper authkeeper.AccountKeeper
bankkeeper bankkeeper.BaseKeeper
stakingKeeper *stakingkeeper.Keeper
mintkeeper mintkeeper.Keeper
addrs []sdk.AccAddress
govModAddr string
}
func SetupTest(t *testing.T) *testFixture {
t.Helper()
f := new(testFixture)
cfg := sdk.GetConfig() // do not seal, more set later
cfg.SetBech32PrefixForAccount(app.Bech32PrefixAccAddr, app.Bech32PrefixAccPub)
cfg.SetBech32PrefixForValidator(app.Bech32PrefixValAddr, app.Bech32PrefixValPub)
cfg.SetBech32PrefixForConsensusNode(app.Bech32PrefixConsAddr, app.Bech32PrefixConsPub)
cfg.SetCoinType(app.CoinType)
validatorAddressCodec := sdkaddress.NewBech32Codec(app.Bech32PrefixValAddr)
accountAddressCodec := sdkaddress.NewBech32Codec(app.Bech32PrefixAccAddr)
consensusAddressCodec := sdkaddress.NewBech32Codec(app.Bech32PrefixConsAddr)
// Base setup
logger := log.NewTestLogger(t)
encCfg := moduletestutil.MakeTestEncodingConfig()
f.govModAddr = authtypes.NewModuleAddress(govtypes.ModuleName).String()
f.addrs = simtestutil.CreateIncrementalAccounts(3)
keys := storetypes.NewKVStoreKeys(
authtypes.ModuleName,
banktypes.ModuleName,
stakingtypes.ModuleName,
minttypes.ModuleName,
types.ModuleName,
)
f.ctx = sdk.NewContext(
integration.CreateMultiStore(keys, logger),
cmtproto.Header{},
false,
logger,
)
// Register SDK modules.
registerBaseSDKModules(
logger,
f,
encCfg,
keys,
accountAddressCodec,
validatorAddressCodec,
consensusAddressCodec,
)
// Setup SVC Keeper with DID dependency only (UCAN is now internal).
mockDIDKeeper := &SVCMockDIDKeeper{}
f.k = keeper.NewKeeper(
encCfg.Codec,
runtime.NewKVStoreService(keys[types.ModuleName]),
logger,
f.govModAddr,
mockDIDKeeper,
)
f.msgServer = keeper.NewMsgServerImpl(f.k)
f.queryServer = keeper.NewQuerier(f.k)
f.appModule = module.NewAppModule(encCfg.Codec, f.k)
return f
}
func registerModuleInterfaces(encCfg moduletestutil.TestEncodingConfig) {
authtypes.RegisterInterfaces(encCfg.InterfaceRegistry)
stakingtypes.RegisterInterfaces(encCfg.InterfaceRegistry)
banktypes.RegisterInterfaces(encCfg.InterfaceRegistry)
minttypes.RegisterInterfaces(encCfg.InterfaceRegistry)
types.RegisterInterfaces(encCfg.InterfaceRegistry)
}
func registerBaseSDKModules(
logger log.Logger,
f *testFixture,
encCfg moduletestutil.TestEncodingConfig,
keys map[string]*storetypes.KVStoreKey,
ac address.Codec,
validator address.Codec,
consensus address.Codec,
) {
registerModuleInterfaces(encCfg)
// Auth Keeper.
f.accountkeeper = authkeeper.NewAccountKeeper(
encCfg.Codec, runtime.NewKVStoreService(keys[authtypes.StoreKey]),
authtypes.ProtoBaseAccount,
maccPerms,
ac, app.Bech32PrefixAccAddr,
f.govModAddr,
)
// Bank Keeper.
f.bankkeeper = bankkeeper.NewBaseKeeper(
encCfg.Codec, runtime.NewKVStoreService(keys[banktypes.StoreKey]),
f.accountkeeper,
nil,
f.govModAddr, logger,
)
// Staking Keeper.
f.stakingKeeper = stakingkeeper.NewKeeper(
encCfg.Codec, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]),
f.accountkeeper, f.bankkeeper, f.govModAddr,
validator,
consensus,
)
// Mint Keeper.
f.mintkeeper = mintkeeper.NewKeeper(
encCfg.Codec, runtime.NewKVStoreService(keys[minttypes.StoreKey]),
f.stakingKeeper, f.accountkeeper, f.bankkeeper,
authtypes.FeeCollectorName, f.govModAddr,
)
}
// Test for VerifyServiceRegistration method
func TestVerifyServiceRegistration(t *testing.T) {
f := SetupTest(t)
// Test case 1: Invalid service ID
valid, err := f.k.VerifyServiceRegistration(f.ctx, "", "example.com")
if err != types.ErrInvalidServiceID {
t.Errorf("Expected ErrInvalidServiceID, got %v", err)
}
if valid {
t.Error("Expected invalid service registration")
}
// Test case 2: Invalid domain
valid, err = f.k.VerifyServiceRegistration(f.ctx, "test-service", "")
if err != types.ErrDomainNotVerified {
t.Errorf("Expected ErrDomainNotVerified, got %v", err)
}
if valid {
t.Error("Expected invalid service registration")
}
// Test case 3: Non-existent service
valid, err = f.k.VerifyServiceRegistration(f.ctx, "non-existent-service", "example.com")
if err != types.ErrInvalidServiceID {
t.Errorf("Expected ErrInvalidServiceID, got %v", err)
}
if valid {
t.Error("Expected invalid service registration")
}
}
// Test for GetService method
func TestGetService(t *testing.T) {
f := SetupTest(t)
// Test case 1: Invalid service ID
service, err := f.k.GetService(f.ctx, "")
if err != types.ErrInvalidServiceID {
t.Errorf("Expected ErrInvalidServiceID, got %v", err)
}
if service != nil {
t.Error("Expected nil service")
}
// Test case 2: Non-existent service
service, err = f.k.GetService(f.ctx, "non-existent-service")
if err != types.ErrInvalidServiceID {
t.Errorf("Expected ErrInvalidServiceID, got %v", err)
}
if service != nil {
t.Error("Expected nil service")
}
}
// Test for IsDomainVerified method
func TestIsDomainVerified(t *testing.T) {
f := SetupTest(t)
// Test case 1: Empty domain
verified, err := f.k.IsDomainVerified(f.ctx, "", "owner")
if err != types.ErrDomainNotVerified {
t.Errorf("Expected ErrDomainNotVerified, got %v", err)
}
if verified {
t.Error("Expected domain not verified")
}
// Test case 2: Non-existent domain
verified, err = f.k.IsDomainVerified(f.ctx, "non-existent.com", "owner")
if err != types.ErrDomainNotVerified {
t.Errorf("Expected ErrDomainNotVerified, got %v", err)
}
if verified {
t.Error("Expected domain not verified")
}
}
// Test for GetServicesByDomain method
func TestGetServicesByDomain(t *testing.T) {
f := SetupTest(t)
// Test case 1: Empty domain
services, err := f.k.GetServicesByDomain(f.ctx, "")
if err != types.ErrDomainNotVerified {
t.Errorf("Expected ErrDomainNotVerified, got %v", err)
}
if services != nil {
t.Error("Expected nil services")
}
// Test case 2: Non-existent domain
services, err = f.k.GetServicesByDomain(f.ctx, "non-existent.com")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if len(services) != 0 {
t.Error("Expected empty services slice")
}
}
// Test for ValidateServiceOwnerDID method
func TestValidateServiceOwnerDID(t *testing.T) {
f := SetupTest(t)
// Test case 1: Empty DID
err := f.k.ValidateServiceOwnerDID(f.ctx, "")
if err != types.ErrInvalidOwnerDID {
t.Errorf("Expected ErrInvalidOwnerDID, got %v", err)
}
// Test case 2: Valid DID (mocked)
err = f.k.ValidateServiceOwnerDID(f.ctx, "did:example:123")
if err != nil {
t.Errorf("Expected no error for valid DID, got %v", err)
}
// Test case 3: Deactivated DID
err = f.k.ValidateServiceOwnerDID(f.ctx, "did:example:deactivated")
if err != types.ErrInvalidOwnerDID {
t.Errorf("Expected ErrInvalidOwnerDID for deactivated DID, got %v", err)
}
// Test case 4: DID without verification methods
err = f.k.ValidateServiceOwnerDID(f.ctx, "did:example:no-verification")
if err != types.ErrInvalidOwnerDID {
t.Errorf("Expected ErrInvalidOwnerDID for DID without verification methods, got %v", err)
}
}
// Test for internal UCAN integration basic functionality
func TestInternalUCANIntegrationBasic(t *testing.T) {
f := SetupTest(t)
// Test that keeper was created successfully with internal UCAN integration
if f.k.Logger() == nil {
t.Error("Expected keeper to be properly initialized")
}
// Test ValidateServicePermissions method (which uses internal validation)
permissions := []string{"register", "update"}
err := f.k.ValidateServicePermissions(f.ctx, permissions)
if err != nil {
t.Errorf("ValidateServicePermissions failed: %v", err)
}
// Test UCAN delegation chain validation (which uses internal UCAN library)
// Note: This will fail with properly formatted error since we don't have valid UCAN tokens
invalidChain := "invalid_token"
err = f.k.ValidateUCANDelegationChain(f.ctx, invalidChain)
if err == nil {
t.Error("Expected ValidateUCANDelegationChain to fail with invalid token")
}
}