Files
sonr/app/ante/webauthn_gasless_test.go
Prad NukalaandGitHub 13e6c3e84d Master (#1262)
* clear

* feat: Add everything

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

272 lines
8.0 KiB
Go

package ante_test
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/sonr-io/sonr/app/ante"
)
// MockWebAuthnKeeper implements the WebAuthnKeeperInterface for testing
type MockWebAuthnKeeper struct {
existingCredentials map[string]bool
}
func NewMockWebAuthnKeeper() *MockWebAuthnKeeper {
return &MockWebAuthnKeeper{
existingCredentials: make(map[string]bool),
}
}
func (m *MockWebAuthnKeeper) HasExistingCredential(ctx sdk.Context, credentialId string) bool {
return m.existingCredentials[credentialId]
}
func (m *MockWebAuthnKeeper) AddCredential(credentialId string) {
m.existingCredentials[credentialId] = true
}
// MockAccountKeeper - Simple mock without complex interface implementation
// For comprehensive testing, we'd implement the full AccountKeeper interface
// MockTransaction implements sdk.Tx for testing
type MockTransaction struct {
messages []sdk.Msg
}
func (m *MockTransaction) GetMsgs() []sdk.Msg {
return m.messages
}
func (m *MockTransaction) ValidateBasic() error {
return nil
}
// WebAuthnGaslessTestSuite tests the WebAuthn gasless decorator
type WebAuthnGaslessTestSuite struct {
suite.Suite
didKeeper *MockWebAuthnKeeper
}
func TestWebAuthnGaslessTestSuite(t *testing.T) {
suite.Run(t, new(WebAuthnGaslessTestSuite))
}
func (suite *WebAuthnGaslessTestSuite) SetupTest() {
// Setup minimal test context and keepers
suite.didKeeper = NewMockWebAuthnKeeper()
// We'll focus on testing the logic without complex keeper setup
}
func (suite *WebAuthnGaslessTestSuite) TestGenerateAddressFromCredential() {
// Test that the same credential always generates the same address
credentialID := "test-credential-id-123"
addr1 := ante.GenerateAddressFromCredential(credentialID)
addr2 := ante.GenerateAddressFromCredential(credentialID)
suite.Require().Equal(addr1, addr2, "Same credential should generate same address")
suite.Require().NotNil(addr1, "Generated address should not be nil")
suite.Require().Equal(20, len(addr1), "Address should be 20 bytes")
}
func (suite *WebAuthnGaslessTestSuite) TestGenerateDIDFromCredential() {
// Test DID generation
credentialID := "test-credential-id-123"
username := "testuser"
did1 := ante.GenerateDIDFromCredential(credentialID, username)
did2 := ante.GenerateDIDFromCredential(credentialID, username)
suite.Require().Equal(did1, did2, "Same inputs should generate same DID")
suite.Require().Contains(did1, "did:sonr:", "DID should have correct prefix")
// Different username should generate different DID
did3 := ante.GenerateDIDFromCredential(credentialID, "differentuser")
suite.Require().NotEqual(did1, did3, "Different username should generate different DID")
}
func (suite *WebAuthnGaslessTestSuite) TestWebAuthnGaslessDecorator_StandardMode() {
// Test standard mode behavior
decorator := ante.NewWebAuthnGaslessDecorator(
nil, // accountKeeper would be mocked in full test
suite.didKeeper,
false, // standard mode
)
suite.Require().NotNil(decorator, "Decorator should be created")
}
func (suite *WebAuthnGaslessTestSuite) TestWebAuthnGaslessDecorator_EnhancedMode() {
// Test enhanced mode behavior
decorator := ante.NewWebAuthnGaslessDecorator(
nil, // accountKeeper would be mocked in full test
suite.didKeeper,
true, // enhanced mode
)
suite.Require().NotNil(decorator, "Decorator should be created in enhanced mode")
}
func (suite *WebAuthnGaslessTestSuite) TestConditionalDecorators() {
// Test that conditional decorators are created properly
// We'll use a simple mock decorator for testing
mockDecorator := &MockAnteDecorator{}
feeDecorator := ante.NewConditionalFeeDecorator(mockDecorator)
suite.Require().NotNil(feeDecorator, "Conditional fee decorator should be created")
sigDecorator := ante.NewConditionalSignatureDecorator(mockDecorator)
suite.Require().NotNil(sigDecorator, "Conditional signature decorator should be created")
pubKeyDecorator := ante.NewConditionalPubKeyDecorator(mockDecorator)
suite.Require().NotNil(pubKeyDecorator, "Conditional pubkey decorator should be created")
}
func (suite *WebAuthnGaslessTestSuite) TestWebAuthnCredentialValidation() {
// Test WebAuthn credential structure validation
// This tests the core logic without full ante handler setup
testCases := []struct {
name string
credentialID string
expectError bool
}{
{
name: "valid credential ID",
credentialID: "valid-credential-123",
expectError: false,
},
{
name: "empty credential ID should be caught by message validation",
credentialID: "",
expectError: true, // This would be caught by ValidateStructure
},
{
name: "duplicate credential",
credentialID: "duplicate-cred",
expectError: true,
},
}
// Add a duplicate credential
suite.didKeeper.AddCredential("duplicate-cred")
for _, tc := range testCases {
suite.Run(tc.name, func() {
hasExisting := suite.didKeeper.HasExistingCredential(sdk.Context{}, tc.credentialID)
switch tc.credentialID {
case "duplicate-cred":
suite.Require().True(hasExisting, "Duplicate credential should exist")
case "valid-credential-123":
suite.Require().False(hasExisting, "New credential should not exist")
}
})
}
}
func (suite *WebAuthnGaslessTestSuite) TestEnhancedModeAddressGeneration() {
// Test enhanced mode functionality for address generation
testCredentialID := "test-enhanced-credential"
// Test that the same credential always generates the same address
addr1 := ante.GenerateAddressFromCredential(testCredentialID)
addr2 := ante.GenerateAddressFromCredential(testCredentialID)
suite.Require().Equal(addr1, addr2, "Same credential should generate same address")
suite.Require().Equal(20, len(addr1), "Address should be 20 bytes")
// Test that different credentials generate different addresses
addr3 := ante.GenerateAddressFromCredential("different-credential")
suite.Require().
NotEqual(addr1, addr3, "Different credentials should generate different addresses")
}
// MockAnteDecorator is a simple mock implementation of sdk.AnteDecorator for testing
type MockAnteDecorator struct{}
func (m *MockAnteDecorator) AnteHandle(
ctx sdk.Context,
tx sdk.Tx,
simulate bool,
next sdk.AnteHandler,
) (sdk.Context, error) {
return next(ctx, tx, simulate)
}
// TestAddressGeneration tests the deterministic address generation
func TestAddressGeneration(t *testing.T) {
testCases := []struct {
name string
credentialID string
expectSame bool
}{
{
name: "same credential generates same address",
credentialID: "credential-1",
expectSame: true,
},
{
name: "different credential generates different address",
credentialID: "credential-2",
expectSame: false,
},
}
baseAddr := ante.GenerateAddressFromCredential("base-credential")
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
addr := ante.GenerateAddressFromCredential(tc.credentialID)
require.NotNil(t, addr)
require.Equal(t, 20, len(addr))
if tc.expectSame && tc.credentialID == "base-credential" {
require.Equal(t, baseAddr, addr)
} else if !tc.expectSame {
require.NotEqual(t, baseAddr, addr)
}
})
}
}
// TestDIDGeneration tests the deterministic DID generation
func TestDIDGeneration(t *testing.T) {
testCases := []struct {
name string
credentialID string
username string
expectedPrefix string
}{
{
name: "generates valid DID",
credentialID: "cred-1",
username: "user1",
expectedPrefix: "did:sonr:",
},
{
name: "different username generates different DID",
credentialID: "cred-1",
username: "user2",
expectedPrefix: "did:sonr:",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
did := ante.GenerateDIDFromCredential(tc.credentialID, tc.username)
require.NotEmpty(t, did)
require.Contains(t, did, tc.expectedPrefix)
// Verify deterministic generation
did2 := ante.GenerateDIDFromCredential(tc.credentialID, tc.username)
require.Equal(t, did, did2)
})
}
}