Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

coinflipduel_test.gno

2.96 Kb · 121 lines
  1package coinflipduel
  2
  3import (
  4	"testing"
  5
  6	"gno.land/p/nt/avl/v0"
  7	"gno.land/p/nt/testutils/v0"
  8)
  9
 10func resetState() {
 11	duels = avl.Tree{}
 12	players = avl.Tree{}
 13	nextID = 0
 14	flipNonce = 0
 15	totalDone = 0
 16	var zero address
 17	champion = zero
 18	championWins = 0
 19}
 20
 21func TestParseCall(t *testing.T) {
 22	for _, s := range []string{"heads", "Heads", " h ", "tails", "T"} {
 23		if _, ok := parseCall(s); !ok {
 24			t.Fatalf("parseCall(%q) should be valid", s)
 25		}
 26	}
 27	if _, ok := parseCall("sideways"); ok {
 28		t.Fatal(`parseCall("sideways") should be invalid`)
 29	}
 30}
 31
 32// Crossing: Challenge and Accept mutate realm state, so the test needs `cur realm`.
 33func TestChallengeAndAccept(cur realm, t *testing.T) {
 34	resetState()
 35	alice := testutils.TestAddress("alice")
 36	bob := testutils.TestAddress("bob")
 37
 38	testing.SetRealm(testing.NewUserRealm(alice))
 39	Challenge(cross(cur), bob.String(), "heads")
 40
 41	if !duels.Has("1") {
 42		t.Fatal("expected duel #1 to exist")
 43	}
 44
 45	testing.SetRealm(testing.NewUserRealm(bob))
 46	Accept(cross(cur), "1")
 47
 48	v := duels.Get("1")
 49	d := v.(*duel)
 50	if d.Status != statusResolved {
 51		t.Fatalf("Status = %v, want resolved", d.Status)
 52	}
 53	if d.Result != "heads" && d.Result != "tails" {
 54		t.Fatalf("Result = %q, want heads or tails", d.Result)
 55	}
 56	if totalDone != 1 {
 57		t.Fatalf("totalDone = %d, want 1", totalDone)
 58	}
 59
 60	winnerStats := getOrCreate(d.Winner)
 61	if winnerStats.Wins != 1 {
 62		t.Fatalf("winner Wins = %d, want 1", winnerStats.Wins)
 63	}
 64	if !champion.IsValid() || champion != d.Winner {
 65		t.Fatal("champion should be the duel winner")
 66	}
 67}
 68
 69func TestChallengeSelfRejected(cur realm, t *testing.T) {
 70	resetState()
 71	alice := testutils.TestAddress("alice")
 72	testing.SetRealm(testing.NewUserRealm(alice))
 73
 74	// Challenge panics inside a cross-realm call; a plain defer/recover in
 75	// this test does not catch a cross-boundary panic, so use revive().
 76	rec := revive(func() { Challenge(cross(cur), alice.String(), "heads") })
 77	if rec == nil {
 78		t.Fatal("expected panic when challenging yourself")
 79	}
 80}
 81
 82func TestOnlyOpponentCanAccept(cur realm, t *testing.T) {
 83	resetState()
 84	alice := testutils.TestAddress("alice")
 85	bob := testutils.TestAddress("bob")
 86	mallory := testutils.TestAddress("mallory")
 87
 88	testing.SetRealm(testing.NewUserRealm(alice))
 89	Challenge(cross(cur), bob.String(), "tails")
 90
 91	testing.SetRealm(testing.NewUserRealm(mallory))
 92	rec := revive(func() { Accept(cross(cur), "1") })
 93	if rec == nil {
 94		t.Fatal("expected panic when a non-opponent accepts")
 95	}
 96}
 97
 98func TestCancel(cur realm, t *testing.T) {
 99	resetState()
100	alice := testutils.TestAddress("alice")
101	bob := testutils.TestAddress("bob")
102
103	testing.SetRealm(testing.NewUserRealm(alice))
104	Challenge(cross(cur), bob.String(), "heads")
105	Cancel(cross(cur), "1")
106
107	v := duels.Get("1")
108	d := v.(*duel)
109	if d.Status != statusCancelled {
110		t.Fatalf("Status = %v, want cancelled", d.Status)
111	}
112}
113
114// Non-crossing: Render is a plain read.
115func TestRenderHome(t *testing.T) {
116	resetState()
117	out := Render("")
118	if out == "" {
119		t.Fatal(`Render("") should not be empty`)
120	}
121}