Skip to content

Commit

Permalink
Merge pull request #341 from perun-network/concurrent-client-test
Browse files Browse the repository at this point in the history
Client tests: fail on error
  • Loading branch information
cryptphil authored May 23, 2022
2 parents 5d89bb3 + 4a71c1b commit 1e496bd
Show file tree
Hide file tree
Showing 18 changed files with 174 additions and 163 deletions.
6 changes: 2 additions & 4 deletions client/appchannel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"math/big"
"testing"

"github.com/stretchr/testify/assert"
"perun.network/go-perun/channel"
chtest "perun.network/go-perun/channel/test"
"perun.network/go-perun/client"
Expand All @@ -32,7 +31,7 @@ import (
func TestProgression(t *testing.T) {
rng := pkgtest.Prng(t)

setups := NewSetups(rng, []string{"Paul", "Paula"})
setups, errs := NewSetups(rng, []string{"Paul", "Paula"})
roles := [2]clienttest.Executer{
clienttest.NewPaul(t, setups[0]),
clienttest.NewPaula(t, setups[1]),
Expand All @@ -53,6 +52,5 @@ func TestProgression(t *testing.T) {

ctx, cancel := context.WithTimeout(context.Background(), twoPartyTestTimeout)
defer cancel()
err := clienttest.ExecuteTwoPartyTest(ctx, roles, execConfig)
assert.NoError(t, err)
clienttest.ExecuteTwoPartyTest(ctx, t, roles, execConfig, errs)
}
10 changes: 5 additions & 5 deletions client/client_persistence_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ func TestPersistencePetraRobert(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), twoPartyTestTimeout)
defer cancel()

runAliceBobTest(ctx, t, func(rng *rand.Rand) (setups []ctest.RoleSetup, roles [2]ctest.Executer) {
setups = NewSetupsPersistence(t, rng, []string{"Petra", "Robert"})
runAliceBobTest(ctx, t, func(rng *rand.Rand) (setups []ctest.RoleSetup, roles [2]ctest.Executer, errs chan error) {
setups, errs = NewSetupsPersistence(t, rng, []string{"Petra", "Robert"})
roles = [2]ctest.Executer{
ctest.NewPetra(t, setups[0]),
ctest.NewRobert(t, setups[1]),
Expand All @@ -37,11 +37,11 @@ func TestPersistencePetraRobert(t *testing.T) {
})
}

func NewSetupsPersistence(t *testing.T, rng *rand.Rand, names []string) []ctest.RoleSetup {
func NewSetupsPersistence(t *testing.T, rng *rand.Rand, names []string) ([]ctest.RoleSetup, chan error) {
t.Helper()
setups := NewSetups(rng, names)
setups, errs := NewSetups(rng, names)
for i := range names {
setups[i].PR = chprtest.NewPersistRestorer(t)
}
return setups
return setups, errs
}
19 changes: 10 additions & 9 deletions client/client_role_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ const (
twoPartyTestTimeout = 10 * time.Second
)

func NewSetups(rng *rand.Rand, names []string) []ctest.RoleSetup {
func NewSetups(rng *rand.Rand, names []string) ([]ctest.RoleSetup, chan error) {
var (
bus = wiretest.NewSerializingLocalBus()
n = len(names)
setup = make([]ctest.RoleSetup, n)
backend = ctest.NewMockBackend(rng, "1337")
errs = make(chan error)
)

for i := 0; i < n; i++ {
Expand All @@ -63,20 +64,21 @@ func NewSetups(rng *rand.Rand, names []string) []ctest.RoleSetup {
Timeout: roleOperationTimeout,
BalanceReader: backend,
ChallengeDuration: 60,
Errors: errs,
}
}

return setup
return setup, errs
}

type Client struct {
*client.Client
ctest.RoleSetup
}

func NewClients(t *testing.T, rng *rand.Rand, names []string) []*Client {
func NewClients(t *testing.T, rng *rand.Rand, names []string) ([]*Client, chan error) {
t.Helper()
setups := NewSetups(rng, names)
setups, errs := NewSetups(rng, names)
clients := make([]*Client, len(setups))
for i, setup := range setups {
setup.Identity = setup.Wallet.NewRandomAccount(rng)
Expand All @@ -87,14 +89,14 @@ func NewClients(t *testing.T, rng *rand.Rand, names []string) []*Client {
RoleSetup: setup,
}
}
return clients
return clients, errs
}

func runAliceBobTest(ctx context.Context, t *testing.T, setup func(*rand.Rand) ([]ctest.RoleSetup, [2]ctest.Executer)) {
func runAliceBobTest(ctx context.Context, t *testing.T, setup func(*rand.Rand) ([]ctest.RoleSetup, [2]ctest.Executer, chan error)) {
t.Helper()
rng := test.Prng(t)
for i := 0; i < 2; i++ {
setups, roles := setup(rng)
setups, roles, errs := setup(rng)
app := client.WithoutApp()
if i == 1 {
app = client.WithApp(
Expand All @@ -113,7 +115,6 @@ func runAliceBobTest(ctx context.Context, t *testing.T, setup func(*rand.Rand) (
TxAmounts: [2]*big.Int{big.NewInt(5), big.NewInt(3)},
}

err := ctest.ExecuteTwoPartyTest(ctx, roles, cfg)
assert.NoError(t, err)
ctest.ExecuteTwoPartyTest(ctx, t, roles, cfg, errs)
}
}
6 changes: 2 additions & 4 deletions client/dispute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"math/big"
"testing"

"github.com/stretchr/testify/assert"
chtest "perun.network/go-perun/channel/test"
"perun.network/go-perun/client"
ctest "perun.network/go-perun/client/test"
Expand All @@ -33,7 +32,7 @@ func TestDispute(t *testing.T) {
defer cancel()

const mallory, carol = 0, 1 // Indices of Mallory and Carol
setups := NewSetups(rng, []string{"Mallory", "Carol"})
setups, errs := NewSetups(rng, []string{"Mallory", "Carol"})
roles := [2]ctest.Executer{
ctest.NewMallory(t, setups[0]),
ctest.NewCarol(t, setups[1]),
Expand All @@ -49,6 +48,5 @@ func TestDispute(t *testing.T) {
NumPayments: [2]int{5, 0},
TxAmounts: [2]*big.Int{big.NewInt(20), big.NewInt(0)},
}
err := ctest.ExecuteTwoPartyTest(ctx, roles, cfg)
assert.NoError(t, err)
ctest.ExecuteTwoPartyTest(ctx, t, roles, cfg, errs)
}
4 changes: 2 additions & 2 deletions client/happy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ func TestHappyAliceBob(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), twoPartyTestTimeout)
defer cancel()

runAliceBobTest(ctx, t, func(rng *rand.Rand) (setups []ctest.RoleSetup, roles [2]ctest.Executer) {
setups = NewSetups(rng, []string{"Alice", "Bob"})
runAliceBobTest(ctx, t, func(rng *rand.Rand) (setups []ctest.RoleSetup, roles [2]ctest.Executer, errs chan error) {
setups, errs = NewSetups(rng, []string{"Alice", "Bob"})
roles = [2]ctest.Executer{
ctest.NewAlice(t, setups[0]),
ctest.NewBob(t, setups[1]),
Expand Down
5 changes: 2 additions & 3 deletions client/subchannel_dispute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"math/big"
"testing"

"github.com/stretchr/testify/assert"
chtest "perun.network/go-perun/channel/test"
"perun.network/go-perun/client"
ctest "perun.network/go-perun/client/test"
Expand All @@ -30,7 +29,7 @@ import (
func TestSubChannelDispute(t *testing.T) {
rng := test.Prng(t)

setups := NewSetups(rng, []string{"DisputeSusie", "DisputeTim"})
setups, errs := NewSetups(rng, []string{"DisputeSusie", "DisputeTim"})
roles := [2]ctest.Executer{
ctest.NewDisputeSusie(t, setups[0]),
ctest.NewDisputeTim(t, setups[1]),
Expand All @@ -50,5 +49,5 @@ func TestSubChannelDispute(t *testing.T) {

ctx, cancel := context.WithTimeout(context.Background(), twoPartyTestTimeout)
defer cancel()
assert.NoError(t, ctest.ExecuteTwoPartyTest(ctx, roles, cfg))
ctest.ExecuteTwoPartyTest(ctx, t, roles, cfg, errs)
}
5 changes: 2 additions & 3 deletions client/subchannel_happy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"math/big"
"testing"

"github.com/stretchr/testify/assert"
"perun.network/go-perun/apps/payment"
chtest "perun.network/go-perun/channel/test"
"perun.network/go-perun/client"
Expand All @@ -31,7 +30,7 @@ import (
func TestSubChannelHappy(t *testing.T) {
rng := test.Prng(t)

setups := NewSetups(rng, []string{"Susie", "Tim"})
setups, errs := NewSetups(rng, []string{"Susie", "Tim"})
roles := [2]ctest.Executer{
ctest.NewSusie(t, setups[0]),
ctest.NewTim(t, setups[1]),
Expand Down Expand Up @@ -63,5 +62,5 @@ func TestSubChannelHappy(t *testing.T) {

ctx, cancel := context.WithTimeout(context.Background(), twoPartyTestTimeout)
defer cancel()
assert.NoError(t, ctest.ExecuteTwoPartyTest(ctx, roles, cfg))
ctest.ExecuteTwoPartyTest(ctx, t, roles, cfg, errs)
}
5 changes: 1 addition & 4 deletions client/test/carol.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"

"perun.network/go-perun/channel"
)

Expand Down Expand Up @@ -53,7 +51,6 @@ func (r *Carol) Execute(cfg ExecConfig) {

func (r *Carol) exec(_cfg ExecConfig, ch *paymentChannel, propHandler *acceptNextPropHandler) {
cfg := _cfg.(*MalloryCarolExecConfig)
assert := assert.New(r.t)
_, them := r.Idxs(cfg.Peers())

// start watcher
Expand Down Expand Up @@ -82,7 +79,7 @@ func (r *Carol) exec(_cfg ExecConfig, ch *paymentChannel, propHandler *acceptNex
r.log.Debugf("watcher refuted with the version: %v", e.Version())

r.log.Debug("Waiting until ready to conclude")
assert.NoError(e.Timeout().Wait(r.Ctx())) // wait until ready to conclude
r.RequireNoError(e.Timeout().Wait(r.Ctx())) // wait until ready to conclude

r.log.Debug("Settle")
ch.settle() // conclude and withdraw
Expand Down
31 changes: 14 additions & 17 deletions client/test/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ package test

import (
"context"
"errors"
"io"
"math/big"
"time"

"github.com/stretchr/testify/assert"

"perun.network/go-perun/channel"
"perun.network/go-perun/client"
"perun.network/go-perun/log"
Expand Down Expand Up @@ -73,7 +72,7 @@ func (ch *paymentChannel) openSubChannel(

prop := ch.r.SubChannelProposal(rng, cfg, ch.Channel, &initAlloc, app)
subchannel, err := ch.r.ProposeChannel(prop)
assert.NoError(ch.r.t, err)
ch.r.RequireNoError(err)
ch.r.log.Infof("New subchannel opened: %v", subchannel.Channel)

for i, bal := range initBals {
Expand All @@ -88,7 +87,7 @@ func (ch *paymentChannel) acceptSubchannel(
initBals []*big.Int,
) *paymentChannel {
subchannel, err := propHandler.Next()
assert.NoError(ch.r.t, err)
ch.r.RequireNoError(err)
ch.r.log.Infof("New subchannel opened: %v", subchannel.Channel)

for i, bal := range initBals {
Expand All @@ -105,7 +104,7 @@ func (ch *paymentChannel) sendUpdate(updater func(*channel.State), desc string)

err := ch.Update(ctx, updater)
ch.log.Infof("Sent update: %s, err: %v", desc, err)
assert.NoError(ch.r.t, err)
ch.r.RequireNoError(err)
}

func (ch *paymentChannel) sendTransfer(amount channel.Bal, desc string) {
Expand All @@ -127,10 +126,11 @@ func (ch *paymentChannel) recvUpdate(accept bool, desc string) *channel.State {
select {
case res := <-ch.res:
ch.log.Infof("Received update: %s, err: %v", desc, res.err)
assert.NoError(ch.r.t, res.err)
ch.r.RequireNoError(res.err)
return res.up.State
case <-time.After(ch.r.timeout):
ch.r.t.Error("timeout: expected incoming channel update")
err := errors.New("timeout: expected incoming channel update")
ch.r.RequireNoError(err)
return nil
}
}
Expand All @@ -150,22 +150,21 @@ func (ch *paymentChannel) assertBals(state *channel.State) {
ch.bals[0], ch.bals[1],
bals[0], bals[1],
)
assert := assert.New(ch.r.t)
assert.Zerof(bals[0].Cmp(ch.bals[0]), "bal[0]: %v != %v", bals[0], ch.bals[0])
assert.Zerof(bals[1].Cmp(ch.bals[1]), "bal[1]: %v != %v", bals[1], ch.bals[1])
ch.r.RequireTruef(bals[0].Cmp(ch.bals[0]) == 0, "bal[0]: %v != %v", bals[0], ch.bals[0])
ch.r.RequireTruef(bals[1].Cmp(ch.bals[1]) == 0, "bal[1]: %v != %v", bals[1], ch.bals[1])
}

func (ch *paymentChannel) sendFinal() {
ch.sendUpdate(func(state *channel.State) {
state.IsFinal = true
}, "final")
assert.True(ch.r.t, ch.State().IsFinal)
ch.r.RequireTrue(ch.State().IsFinal)
}

func (ch *paymentChannel) recvFinal() {
state := ch.recvUpdate(true, "final")
assert.NotNil(ch.r.t, state)
assert.True(ch.r.t, state.IsFinal)
ch.r.RequireTrue(state != nil)
ch.r.RequireTrue(state.IsFinal)
}

func (ch *paymentChannel) settle() {
Expand All @@ -177,18 +176,16 @@ func (ch *paymentChannel) settleSecondary() {
}

func (ch *paymentChannel) settleImpl(secondary bool) {
assert := assert.New(ch.r.t)

ctx, cancel := context.WithTimeout(context.Background(), ch.r.timeout)
defer cancel()

assert.NoError(ch.Settle(ctx, secondary))
ch.r.RequireNoError(ch.Settle(ctx, secondary))
ch.assertBals(ch.State())

if ch.IsSubChannel() {
// Track parent channel's balances.
parentChannel, ok := ch.r.chans.channel(ch.Parent().ID())
assert.True(ok, "parent channel not found")
ch.r.RequireTruef(ok, "parent channel not found")

for i, bal := range ch.bals {
parentBal := parentChannel.bals[i]
Expand Down
21 changes: 9 additions & 12 deletions client/test/mallory.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import (
"testing"
"time"

"github.com/stretchr/testify/assert"

"perun.network/go-perun/client"
)

Expand Down Expand Up @@ -53,7 +51,6 @@ func (r *Mallory) Execute(cfg ExecConfig) {

func (r *Mallory) exec(_cfg ExecConfig, ch *paymentChannel) {
cfg := _cfg.(*MalloryCarolExecConfig)
assert := assert.New(r.t)
we, _ := r.Idxs(cfg.Peers())
// AdjudicatorReq for version 0
req0 := client.NewTestChannel(ch.Channel).AdjudicatorReq()
Expand All @@ -73,35 +70,35 @@ func (r *Mallory) exec(_cfg ExecConfig, ch *paymentChannel) {
regCtx, regCancel := context.WithTimeout(context.Background(), r.timeout)
defer regCancel()
r.log.Debug("Registering version 0 state.")
assert.NoError(r.setup.Adjudicator.Register(regCtx, req0, nil))
r.RequireNoError(r.setup.Adjudicator.Register(regCtx, req0, nil))

// within the challenge duration, Carol should refute.
subCtx, subCancel := context.WithTimeout(context.Background(), r.timeout+challengeDuration)
defer subCancel()
sub, err := r.setup.Adjudicator.Subscribe(subCtx, ch.Params().ID())
assert.NoError(err)
r.RequireNoError(err)

// 3rd stage - wait until Carol has refuted
r.waitStage()

event := sub.Next() // should be event caused by Carol's refutation.
assert.NotNil(event)
assert.True(event.Timeout().IsElapsed(subCtx),
r.RequireTrue(event != nil)
r.RequireTruef(event.Timeout().IsElapsed(subCtx),
"Carol's refutation should already have progressed past the timeout.")

assert.NoError(sub.Close())
assert.NoError(sub.Err())
r.RequireNoError(sub.Close())
r.RequireNoError(sub.Err())
r.log.Debugln("<Registered> refuted: ", event)
assert.Equal(ch.State().Version, event.Version(), "expected refutation with current version")
r.RequireTruef(ch.State().Version == event.Version(), "expected refutation with current version")
waitCtx, waitCancel := context.WithTimeout(context.Background(), r.timeout+challengeDuration)
defer waitCancel()
// refutation increased the timeout.
assert.NoError(event.Timeout().Wait(waitCtx))
r.RequireNoError(event.Timeout().Wait(waitCtx))

wdCtx, wdCancel := context.WithTimeout(context.Background(), r.timeout)
defer wdCancel()
err = r.setup.Adjudicator.Withdraw(wdCtx, req0, nil)
assert.Error(err, "withdrawing should fail because Carol should have refuted.")
r.RequireTruef(err != nil, "withdrawing should fail because Carol should have refuted")

// settling current version should work
ch.settle()
Expand Down
Loading

0 comments on commit 1e496bd

Please sign in to comment.