safe_test.gno
3.07 Kb · 65 lines
1package safe
2
3import (
4 "testing"
5
6 "gno.land/p/nt/testutils/v0"
7 "gno.land/p/nt/uassert/v0"
8)
9
10// This package is a design sketch: only the constructor and the four read
11// accessors are implemented, and every proposal method is `panic("not
12// implemented")`. The tests below pin the implemented behaviour and pin the
13// stubs as stubs, so implementing one is a deliberate, visible change.
14
15var alice = testutils.TestAddress("alice")
16
17// NewSafe reads unsafe.PreviousRealm(), which needs a real realm frame: a user
18// realm gives "frame not found: cannot seek beyond origin caller override".
19func TestNewSafeDefaults(cur realm, t *testing.T) {
20 testing.SetRealm(testing.NewCodeRealm("gno.land/r/test/safeone"))
21 s := NewSafe()
22
23 uassert.Equal(t, "", s.Name(), "a fresh safe is unnamed")
24 uassert.Equal(t, uint(1), s.Threshold(), "threshold starts at 1")
25 uassert.Equal(t, uint(1), s.Size(), "the creator is the only member")
26 uassert.Equal(t, 1, len(s.Members()))
27 uassert.True(t, s.Members()[0].IsValid(), "the sole member is a valid address")
28}
29
30// Note: caller-sensitivity of NewSafe is NOT asserted here. From a `p/` test
31// package there is a single realm frame, so unsafe.PreviousRealm() resolves to
32// the origin no matter what testing.SetRealm is given — two different code
33// realms seed the identical address. Proving "membership follows the caller"
34// needs an `r/` test package that can actually cross into this one.
35
36func TestSizeTracksMembers(t *testing.T) {
37 s := safe{members: []address{alice, testutils.TestAddress("bob")}, threshold: 2}
38 uassert.Equal(t, uint(2), s.Size())
39 uassert.Equal(t, uint(2), s.Threshold())
40}
41
42// TestUnimplementedMethodsPanic documents the sketch surface. If one of these
43// starts working, this test fails and forces the contract change to be noticed.
44func TestUnimplementedMethodsPanic(cur realm, t *testing.T) {
45 s := safe{members: []address{alice}, threshold: 1}
46
47 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.NextProposal() })
48 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.UpcomingProposals(0) })
49 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.PreviousProposals(0) })
50 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.ProposeAddingMember(alice, 1) })
51 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.ProposeRemovingMember(alice, 1) })
52 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.ProposeUpdatingThreshold(2) })
53 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.GetProposal(0) })
54 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.ApproveProposal(nil) })
55 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.ExecuteProposal(nil) })
56 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.CancelProposal(nil) })
57 uassert.PanicsWithMessage(t, cur, "not implemented", func() { s.Render("") })
58}
59
60// TestSafeSatisfiesInterface is a compile-time check that the concrete type
61// still implements the exported interface.
62func TestSafeSatisfiesInterface(t *testing.T) {
63 var _ Safe = safe{}
64 uassert.True(t, true, "safe implements Safe")
65}