Skip to content

Commit c4f3067

Browse files
committed
✅ [channel/test,backend/eth/channel] Generic adjudicator test
Signed-off-by: Matthias Geihs <[email protected]>
1 parent 2c5c198 commit c4f3067

File tree

2 files changed

+197
-0
lines changed

2 files changed

+197
-0
lines changed

backend/ethereum/channel/adjudicator_test.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package channel_test
1616

1717
import (
1818
"context"
19+
"math/rand"
1920
"testing"
2021
"time"
2122

@@ -33,6 +34,128 @@ import (
3334
pkgtest "perun.network/go-perun/pkg/test"
3435
)
3536

37+
// TestAdjudicator tests the adjudicator.
38+
func TestAdjudicator(t *testing.T) {
39+
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
40+
defer cancel()
41+
42+
rng := pkgtest.Prng(t)
43+
numParts := 2 + rng.Intn(maxNumParts-2)
44+
s := test.NewSetup(t, rng, numParts, blockInterval)
45+
a := newAdjudicatorSetup(s)
46+
channeltest.TestAdjudicator(ctx, t, a)
47+
}
48+
49+
type adjudicatorSetup struct {
50+
setup *test.Setup
51+
}
52+
53+
func newAdjudicatorSetup(setup *test.Setup) *adjudicatorSetup {
54+
return &adjudicatorSetup{
55+
setup: setup,
56+
}
57+
}
58+
59+
type testAdjudicator struct {
60+
*test.SimAdjudicator
61+
}
62+
63+
// Progress is a no-op because app channels are not supported yet.
64+
func (a *testAdjudicator) Progress(ctx context.Context, req channel.ProgressReq) error {
65+
return nil
66+
}
67+
68+
func (a *adjudicatorSetup) Adjudicator() channel.Adjudicator {
69+
return &testAdjudicator{a.setup.Adjs[0]}
70+
}
71+
72+
func (a *adjudicatorSetup) NewRegisterReq(ctx context.Context, rng *rand.Rand) (*channel.AdjudicatorReq, []channel.SignedState) {
73+
req := a.newAdjudicatorReq(ctx, rng, channeltest.WithIsFinal(false))
74+
return req, nil
75+
}
76+
77+
func (a *adjudicatorSetup) newAdjudicatorReq(ctx context.Context, rng *rand.Rand, opts ...channeltest.RandomOpt) *channel.AdjudicatorReq {
78+
params, state := a.newRandomParamsAndState(rng, opts...)
79+
80+
// Fund the channel.
81+
numParts := len(params.Parts)
82+
errs := make(chan error, numParts)
83+
for i, funder := range a.setup.Funders {
84+
req := channel.NewFundingReq(params, state, channel.Index(i), state.Balances)
85+
go func(funder channel.Funder, req channel.FundingReq) {
86+
errs <- funder.Fund(ctx, req)
87+
}(funder, *req)
88+
}
89+
for range a.setup.Funders {
90+
select {
91+
case err := <-errs:
92+
if err != nil {
93+
panic(err)
94+
}
95+
case <-ctx.Done():
96+
panic(ctx.Err())
97+
}
98+
}
99+
100+
tx, err := signState(a.setup.Accs, state)
101+
if err != nil {
102+
panic(err)
103+
}
104+
return &channel.AdjudicatorReq{
105+
Acc: a.setup.Accs[0],
106+
Idx: 0,
107+
Params: params,
108+
Tx: tx,
109+
}
110+
}
111+
112+
func (a *adjudicatorSetup) newRandomParamsAndState(rng *rand.Rand, opts ...channeltest.RandomOpt) (*channel.Params, *channel.State) {
113+
_opts := a.defaultOpts()
114+
_opts = append(_opts, opts...)
115+
return channeltest.NewRandomParamsAndState(rng, _opts...)
116+
}
117+
118+
func (a *adjudicatorSetup) defaultOpts() []channeltest.RandomOpt {
119+
return []channeltest.RandomOpt{
120+
channeltest.WithChallengeDuration(100),
121+
channeltest.WithParts(a.setup.Parts...),
122+
channeltest.WithAssets((*ethchannel.Asset)(&a.setup.Asset)),
123+
channeltest.WithLedgerChannel(true),
124+
channeltest.WithVirtualChannel(false),
125+
channeltest.WithNumLocked(0),
126+
}
127+
}
128+
129+
func (a *adjudicatorSetup) NewProgressReq(context.Context, *rand.Rand) *channel.ProgressReq {
130+
return &channel.ProgressReq{} // Progression test is not implemented.
131+
}
132+
133+
func (a *adjudicatorSetup) NewWithdrawReq(ctx context.Context, rng *rand.Rand) (*channel.AdjudicatorReq, channel.StateMap) {
134+
adj := a.Adjudicator()
135+
req := a.newAdjudicatorReq(ctx, rng, channeltest.WithoutApp())
136+
subChannels := []channel.SignedState{}
137+
138+
if !req.Tx.IsFinal {
139+
// Register.
140+
err := adj.Register(ctx, *req, subChannels)
141+
if err != nil {
142+
panic(err)
143+
}
144+
145+
// Wait until concludable.
146+
sub, err := adj.Subscribe(ctx, req.Params.ID())
147+
if err != nil {
148+
panic(err)
149+
}
150+
err = sub.Next().Timeout().Wait(ctx)
151+
if err != nil {
152+
panic(err)
153+
}
154+
}
155+
156+
return req, channeltest.MakeStateMapFromSignedStates(subChannels...)
157+
}
158+
36159
const defaultTxTimeout = 2 * time.Second
37160

38161
func testSignState(t *testing.T, accounts []*keystore.Account, state *channel.State) channel.Transaction {

channel/test/adjudicator.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2021 - See NOTICE file for copyright holders.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package test
16+
17+
import (
18+
"context"
19+
"math/rand"
20+
"testing"
21+
22+
"github.com/stretchr/testify/require"
23+
"perun.network/go-perun/channel"
24+
pkgtest "perun.network/go-perun/pkg/test"
25+
)
26+
27+
// Adjudicator represents an adjudicator test setup.
28+
//
29+
// Adjudicator should return the adjudicator instance used for testing.
30+
// NewRegisterReq should return the inputs to a successful register call.
31+
// NewProgressReq should return the inputs to a successful progress call.
32+
// NewWithdrawReq should return the inputs to a successful withdraw call.
33+
type Adjudicator interface {
34+
Adjudicator() channel.Adjudicator
35+
NewRegisterReq(context.Context, *rand.Rand) (*channel.AdjudicatorReq, []channel.SignedState)
36+
NewProgressReq(context.Context, *rand.Rand) *channel.ProgressReq
37+
NewWithdrawReq(context.Context, *rand.Rand) (*channel.AdjudicatorReq, channel.StateMap)
38+
}
39+
40+
// TestAdjudicator tests the given adjudicator.
41+
func TestAdjudicator(ctx context.Context, t *testing.T, a Adjudicator) {
42+
rng := pkgtest.Prng(t)
43+
44+
adj := a.Adjudicator()
45+
46+
t.Run("register and subscribe", func(t *testing.T) {
47+
req, subChannels := a.NewRegisterReq(ctx, rng)
48+
err := adj.Register(ctx, *req, subChannels)
49+
require.NoError(t, err, "registering")
50+
51+
_, err = adj.Subscribe(ctx, req.Params.ID())
52+
require.NoError(t, err, "subscribing")
53+
})
54+
55+
t.Run("progress", func(t *testing.T) {
56+
req := a.NewProgressReq(ctx, rng)
57+
err := adj.Progress(ctx, *req)
58+
require.NoError(t, err, "progressing")
59+
})
60+
61+
t.Run("withdraw", func(t *testing.T) {
62+
req, subChannels := a.NewWithdrawReq(ctx, rng)
63+
err := adj.Withdraw(ctx, *req, subChannels)
64+
require.NoError(t, err, "withdrawing")
65+
})
66+
}
67+
68+
func MakeStateMapFromSignedStates(channels ...channel.SignedState) channel.StateMap {
69+
m := channel.MakeStateMap()
70+
for _, c := range channels {
71+
m.Add(c.State)
72+
}
73+
return m
74+
}

0 commit comments

Comments
 (0)