@@ -7,285 +7,123 @@ SPDX-License-Identifier: Apache-2.0
77package ttx_test
88
99import (
10+ "context"
1011 "testing"
1112
1213 "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors"
13- "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/endpoint"
1414 "github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
15- "github.com/hyperledger-labs/fabric-token-sdk/token"
16- "github.com/hyperledger-labs/fabric-token-sdk/token/driver"
17- "github.com/hyperledger-labs/fabric-token-sdk/token/driver/mock"
1815 "github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx"
1916 mock2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep/mock"
20- "github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep/tokenapi"
2117 "github.com/stretchr/testify/assert"
22- "github.com/stretchr/testify/require"
2318)
2419
25- // mockExternalWalletSigner is a mock implementation of ExternalWalletSigner
20+ // mockExternalWalletSigner is a mock implementation of ExternalWalletSigner for testing
2621type mockExternalWalletSigner struct {
27- signCalled int
28- doneCalled int
29- signError error
30- doneError error
22+ signFunc func ( party view. Identity , message [] byte ) ([] byte , error )
23+ doneFunc func () error
24+ doneCalled bool
25+ signCalled bool
3126}
3227
3328func (m * mockExternalWalletSigner ) Sign (party view.Identity , message []byte ) ([]byte , error ) {
34- m .signCalled ++
35- if m .signError != nil {
36- return nil , m . signError
29+ m .signCalled = true
30+ if m .signFunc != nil {
31+ return m . signFunc ( party , message )
3732 }
38- return []byte ("external_signature " ), nil
33+ return []byte ("mock_signature " ), nil
3934}
4035
4136func (m * mockExternalWalletSigner ) Done () error {
42- m .doneCalled ++
43- return m .doneError
44- }
45-
46- func TestCollectEndorsementsView_ExternalWalletCleanup (t * testing.T ) {
47- testCases := []struct {
48- name string
49- setupError error
50- expectDoneCalled bool
51- expectDoneCallCount int
52- errorInSignature bool
53- errorInTransferSignature bool
54- }{
55- {
56- name : "success - Done called once" ,
57- setupError : nil ,
58- expectDoneCalled : true ,
59- expectDoneCallCount : 1 ,
60- },
61- {
62- name : "error in issue signatures - Done still called" ,
63- setupError : nil ,
64- expectDoneCalled : true ,
65- expectDoneCallCount : 1 ,
66- errorInSignature : true ,
67- },
68- {
69- name : "error in transfer signatures - Done still called" ,
70- setupError : nil ,
71- expectDoneCalled : true ,
72- expectDoneCallCount : 1 ,
73- errorInTransferSignature : true ,
74- },
37+ m .doneCalled = true
38+ if m .doneFunc != nil {
39+ return m .doneFunc ()
7540 }
41+ return nil
42+ }
7643
77- for _ , tc := range testCases {
78- t .Run (tc .name , func (t * testing.T ) {
79- // Setup mock context
80- ctx := & mock2.Context {}
81- ctx .ContextReturns (t .Context ())
82-
83- // Setup token management service
84- tms := & mock2.TokenManagementServiceWithExtensions {}
85- tms .NetworkReturns ("test_network" )
86- tms .ChannelReturns ("test_channel" )
87- tmsID := token.TMSID {
88- Network : "test_network" ,
89- Channel : "test_channel" ,
90- Namespace : "test_namespace" ,
91- }
92- tms .IDReturns (tmsID )
93-
94- // Setup token deserializer and identity provider
95- tokenDes := & mock.Deserializer {}
96- tokenIP := & mock.IdentityProvider {}
97- tokenIP .IsMeReturns (false ) // Not me, so it will try external wallet
98- tms .SigServiceReturns (token .NewSignatureService (tokenDes , tokenIP ))
99-
100- // Setup wallet manager with external wallet
101- walletManager := & mock2.WalletManager {}
102- wallet := & mock2.Wallet {}
103- wallet .IDReturns ("external_wallet_1" )
104- walletManager .OwnerWalletReturns (wallet )
105- tms .WalletManagerReturns (walletManager )
106-
107- tokenAPITMS := tokenapi .NewMockedManagementService (t , tmsID )
108- tms .SetTokenManagementServiceStub = func (arg1 * token.Request ) error {
109- arg1 .SetTokenService (tokenAPITMS )
110- return nil
111- }
112-
113- tmsp := & mock2.TokenManagementServiceProvider {}
114- tmsp .TokenManagementServiceReturns (tms , nil )
115-
116- network := & mock2.Network {}
117- network .ComputeTxIDReturns ("test_anchor" )
118- np := & mock2.NetworkProvider {}
119- np .GetNetworkReturns (network , nil )
120-
121- // Create request with issue metadata
122- req := token .NewRequest (nil , "test_anchor" )
123- req .Metadata .Issues = []* driver.IssueMetadata {
124- {
125- Issuer : driver.AuditableIdentity {
126- Identity : []byte ("external_issuer" ),
127- },
128- },
129- }
130- tms .NewRequestReturns (req , nil )
131-
132- // Setup context service calls
133- ctx .GetServiceReturnsOnCall (0 , tmsp , nil )
134- ctx .GetServiceReturnsOnCall (1 , np , nil )
135- ctx .GetServiceReturnsOnCall (2 , & endpoint.Service {}, nil )
136- ctx .GetServiceReturnsOnCall (3 , np , nil )
137- ctx .GetServiceReturnsOnCall (4 , tmsp , nil )
138-
139- // Create transaction
140- tx , err := ttx .NewTransaction (ctx , []byte ("test_signer" ))
141- require .NoError (t , err )
142-
143- // Create mock external wallet signer
144- mockEWS := & mockExternalWalletSigner {}
145- if tc .errorInSignature {
146- mockEWS .signError = errors .New ("signature error" )
147- }
148-
149- // Create CollectEndorsementsView with external wallet signer option
150- opts := []ttx.EndorsementsOpt {
151- ttx .WithExternalWalletSignerProvider (func (walletID string ) ttx.ExternalWalletSigner {
152- return mockEWS
153- }),
154- ttx .WithSkipApproval (),
155- ttx .WithSkipAuditing (),
156- }
157-
158- view := ttx .NewCollectEndorsementsView (tx , opts ... )
159-
160- // Call the view
161- _ , err = view .Call (ctx )
162-
163- // Verify Done was called regardless of error
164- if tc .expectDoneCalled {
165- assert .Equal (t , tc .expectDoneCallCount , mockEWS .doneCalled ,
166- "Done() should be called %d time(s)" , tc .expectDoneCallCount )
167- } else {
168- assert .Equal (t , 0 , mockEWS .doneCalled , "Done() should not be called" )
169- }
44+ // TestCleanupExternalWallets_Success tests that CleanupExternalWallets calls Done() on all wallets
45+ func TestCleanupExternalWallets_Success (t * testing.T ) {
46+ wallet := & mockExternalWalletSigner {}
17047
171- // Verify error behavior
172- if tc .errorInSignature || tc .errorInTransferSignature {
173- require .Error (t , err , "Expected error when signature fails" )
174- }
175- })
48+ externalWallets := map [string ]ttx.ExternalWalletSigner {
49+ "wallet1" : wallet ,
17650 }
177- }
17851
179- func TestCollectEndorsementsView_MultipleExternalWallets ( t * testing. T ) {
180- // Setup mock context
52+ // Create a minimal view and context
53+ view := & ttx. CollectEndorsementsView {}
18154 ctx := & mock2.Context {}
182- ctx .ContextReturns (t . Context ())
55+ ctx .ContextReturns (context . Background ())
18356
184- // Setup token management service
185- tms := & mock2.TokenManagementServiceWithExtensions {}
186- tms .NetworkReturns ("test_network" )
187- tms .ChannelReturns ("test_channel" )
188- tmsID := token.TMSID {
189- Network : "test_network" ,
190- Channel : "test_channel" ,
191- Namespace : "test_namespace" ,
192- }
193- tms .IDReturns (tmsID )
57+ // Call the cleanup method
58+ view .CleanupExternalWallets (ctx , externalWallets )
19459
195- // Setup token deserializer and identity provider
196- tokenDes := & mock.Deserializer {}
197- tokenIP := & mock.IdentityProvider {}
198- tokenIP .IsMeReturns (false )
199- tms .SigServiceReturns (token .NewSignatureService (tokenDes , tokenIP ))
60+ assert .True (t , wallet .doneCalled , "Done() should have been called on the wallet" )
61+ }
20062
201- // Setup wallet manager with multiple external wallets
202- walletManager := & mock2.WalletManager {}
203- wallet1 := & mock2.Wallet {}
204- wallet1 .IDReturns ("external_wallet_1" )
205- wallet2 := & mock2.Wallet {}
206- wallet2 .IDReturns ("external_wallet_2" )
63+ // TestCleanupExternalWallets_MultipleWallets tests that Done() is called on all wallets
64+ func TestCleanupExternalWallets_MultipleWallets (t * testing.T ) {
65+ wallet1 := & mockExternalWalletSigner {}
66+ wallet2 := & mockExternalWalletSigner {}
67+ wallet3 := & mockExternalWalletSigner {}
20768
208- callCount := 0
209- walletManager .OwnerWalletStub = func (ctx2 interface {}, identity view.Identity ) interface {} {
210- callCount ++
211- if callCount % 2 == 1 {
212- return wallet1
213- }
214- return wallet2
69+ externalWallets := map [string ]ttx.ExternalWalletSigner {
70+ "wallet1" : wallet1 ,
71+ "wallet2" : wallet2 ,
72+ "wallet3" : wallet3 ,
21573 }
216- tms .WalletManagerReturns (walletManager )
21774
218- tokenAPITMS := tokenapi .NewMockedManagementService (t , tmsID )
219- tms .SetTokenManagementServiceStub = func (arg1 * token.Request ) error {
220- arg1 .SetTokenService (tokenAPITMS )
221- return nil
222- }
75+ view := & ttx.CollectEndorsementsView {}
76+ ctx := & mock2.Context {}
77+ ctx .ContextReturns (context .Background ())
22378
224- tmsp := & mock2.TokenManagementServiceProvider {}
225- tmsp .TokenManagementServiceReturns (tms , nil )
79+ view .CleanupExternalWallets (ctx , externalWallets )
22680
227- network := & mock2. Network {}
228- network . ComputeTxIDReturns ( "test_anchor " )
229- np := & mock2. NetworkProvider {}
230- np . GetNetworkReturns ( network , nil )
81+ assert . True ( t , wallet1 . doneCalled , "Done() should have been called on wallet1" )
82+ assert . True ( t , wallet2 . doneCalled , "Done() should have been called on wallet2 " )
83+ assert . True ( t , wallet3 . doneCalled , "Done() should have been called on wallet3" )
84+ }
23185
232- // Create request with multiple issues
233- req := token .NewRequest (nil , "test_anchor" )
234- req .Metadata .Issues = []* driver.IssueMetadata {
235- {
236- Issuer : driver.AuditableIdentity {
237- Identity : []byte ("external_issuer_1" ),
238- },
86+ // TestCleanupExternalWallets_DoneError tests that errors from Done() don't stop cleanup
87+ func TestCleanupExternalWallets_DoneError (t * testing.T ) {
88+ wallet1 := & mockExternalWalletSigner {
89+ doneFunc : func () error {
90+ return errors .New ("wallet1 done failed" )
23991 },
240- {
241- Issuer : driver.AuditableIdentity {
242- Identity : []byte ("external_issuer_2" ),
243- },
92+ }
93+ wallet2 := & mockExternalWalletSigner {}
94+ wallet3 := & mockExternalWalletSigner {
95+ doneFunc : func () error {
96+ return errors .New ("wallet3 done failed" )
24497 },
24598 }
246- tms .NewRequestReturns (req , nil )
24799
248- // Setup context service calls
249- ctx .GetServiceReturnsOnCall (0 , tmsp , nil )
250- ctx .GetServiceReturnsOnCall (1 , np , nil )
251- ctx .GetServiceReturnsOnCall (2 , & endpoint.Service {}, nil )
252- ctx .GetServiceReturnsOnCall (3 , np , nil )
253- ctx .GetServiceReturnsOnCall (4 , tmsp , nil )
254-
255- // Create transaction
256- tx , err := ttx .NewTransaction (ctx , []byte ("test_signer" ))
257- require .NoError (t , err )
258-
259- // Create mock external wallet signers
260- mockEWS1 := & mockExternalWalletSigner {}
261- mockEWS2 := & mockExternalWalletSigner {}
100+ externalWallets := map [string ]ttx.ExternalWalletSigner {
101+ "wallet1" : wallet1 ,
102+ "wallet2" : wallet2 ,
103+ "wallet3" : wallet3 ,
104+ }
262105
263- // Simulate error in second wallet's signature
264- mockEWS2 .signError = errors .New ("wallet 2 signature error" )
106+ view := & ttx.CollectEndorsementsView {}
107+ ctx := & mock2.Context {}
108+ ctx .ContextReturns (context .Background ())
265109
266- walletSigners := map [string ]* mockExternalWalletSigner {
267- "external_wallet_1" : mockEWS1 ,
268- "external_wallet_2" : mockEWS2 ,
269- }
110+ // Should not panic even if Done() returns errors
111+ view .CleanupExternalWallets (ctx , externalWallets )
270112
271- // Create CollectEndorsementsView with external wallet signer option
272- opts := []ttx.EndorsementsOpt {
273- ttx .WithExternalWalletSignerProvider (func (walletID string ) ttx.ExternalWalletSigner {
274- return walletSigners [walletID ]
275- }),
276- ttx .WithSkipApproval (),
277- ttx .WithSkipAuditing (),
278- }
113+ assert .True (t , wallet1 .doneCalled , "Done() should have been called on wallet1 despite error" )
114+ assert .True (t , wallet2 .doneCalled , "Done() should have been called on wallet2" )
115+ assert .True (t , wallet3 .doneCalled , "Done() should have been called on wallet3 despite error" )
116+ }
279117
280- view := ttx .NewCollectEndorsementsView (tx , opts ... )
118+ // TestCleanupExternalWallets_EmptyMap tests cleanup with no wallets
119+ func TestCleanupExternalWallets_EmptyMap (t * testing.T ) {
120+ externalWallets := map [string ]ttx.ExternalWalletSigner {}
281121
282- // Call the view - should fail due to wallet 2 error
283- _ , err = view . Call ( ctx )
284- require . Error ( t , err , "Expected error from wallet 2" )
122+ view := & ttx. CollectEndorsementsView {}
123+ ctx := & mock2. Context {}
124+ ctx . ContextReturns ( context . Background () )
285125
286- // Verify Done was called on both wallets despite the error
287- assert .Equal (t , 1 , mockEWS1 .doneCalled , "Done() should be called on wallet 1" )
288- assert .Equal (t , 1 , mockEWS2 .doneCalled , "Done() should be called on wallet 2 even after error" )
126+ // Should not panic with empty map
127+ view .CleanupExternalWallets (ctx , externalWallets )
289128}
290129
291- // Made with Bob
0 commit comments