forge_test.gno
5.29 Kb · 160 lines
1package forge
2
3import (
4 "testing"
5
6 "gno.land/p/nt/uassert/v0"
7 "gno.land/p/nt/urequire/v0"
8)
9
10func TestCreateRepo(t *testing.T) {
11 f := New()
12
13 r, err := f.CreateRepo(alice, 42, "moul/forge", "desc", "")
14 urequire.NoError(t, err)
15 uassert.Equal(t, "refs/heads/main", r.DefaultRef, "default ref defaults")
16 uassert.Equal(t, int64(42), r.CreatedAt)
17 uassert.Equal(t, "owner", r.RoleOf(alice).String())
18 uassert.Equal(t, 1, f.Size())
19
20 _, err = f.CreateRepo(bob, 43, "moul/forge", "", "")
21 uassert.ErrorIs(t, err, ErrRepoExists)
22
23 _, err = f.CreateRepo(bob, 43, "Moul/Forge", "", "")
24 uassert.ErrorIs(t, err, ErrInvalidRepoID)
25
26 _, err = f.CreateRepo(bob, 43, "moul/other", "", "main")
27 uassert.ErrorIs(t, err, ErrInvalidRefName)
28
29 uassert.True(t, f.Repo("moul/nope") == nil, "missing repo is nil")
30 uassert.True(t, f.HasRepo("moul/forge"))
31}
32
33func TestMembership(t *testing.T) {
34 _, r := newRepo(t)
35
36 uassert.True(t, r.Can(bob, RoleWriter), "maintainer covers writer")
37 uassert.False(t, r.Can(carol, RoleMaintainer))
38 uassert.Equal(t, "none", r.RoleOf(eve).String())
39 uassert.Equal(t, 4, r.MemberCount())
40
41 // A writer cannot hand out roles.
42 uassert.ErrorIs(t, r.SetMember(carol, eve, RoleWriter), ErrUnauthorized)
43
44 // An admin can promote up to admin, but cannot mint an owner...
45 urequire.NoError(t, r.SetMember(alice, bob, RoleAdmin))
46 uassert.ErrorIs(t, r.SetMember(bob, eve, RoleOwner), ErrUnauthorized)
47 // ...nor demote one.
48 uassert.ErrorIs(t, r.SetMember(bob, alice, RoleReader), ErrUnauthorized)
49
50 // The last owner cannot demote themselves: a repo with no owner is a repo
51 // nobody can ever administer again.
52 uassert.ErrorIs(t, r.SetMember(alice, alice, RoleReader), ErrLastOwner)
53 urequire.NoError(t, r.SetMember(alice, bob, RoleOwner))
54 urequire.NoError(t, r.SetMember(alice, alice, RoleReader))
55 uassert.Equal(t, "reader", r.RoleOf(alice).String())
56
57 // Revoking removes the member outright.
58 urequire.NoError(t, r.SetMember(bob, dave, RoleNone))
59 uassert.Equal(t, "none", r.RoleOf(dave).String())
60 uassert.Equal(t, 3, r.MemberCount())
61
62 uassert.ErrorIs(t, r.SetMember(bob, eve, Role(99)), ErrInvalidRole)
63}
64
65func TestRepoSettings(t *testing.T) {
66 _, r := newRepo(t)
67
68 uassert.ErrorIs(t, r.SetDescription(carol, "nope"), ErrUnauthorized)
69 urequire.NoError(t, r.SetDescription(alice, "an on-chain forge for gno"))
70 uassert.Equal(t, "an on-chain forge for gno", r.Description)
71
72 uassert.ErrorIs(t, r.SetMirrors(carol, []string{"https://example.com/x.git"}), ErrUnauthorized)
73 uassert.ErrorIs(t, r.SetMirrors(bob, []string{"nope"}), ErrInvalidMirror)
74 urequire.NoError(t, r.SetMirrors(bob, []string{"https://github.com/moul/gno-contracts.git"}))
75 uassert.Equal(t, 1, len(r.Mirrors))
76
77 uassert.ErrorIs(t, r.SetPolicy(carol, 2, false), ErrUnauthorized)
78 uassert.ErrorIs(t, r.SetPolicy(alice, 99, false), ErrTooMany)
79 urequire.NoError(t, r.SetPolicy(alice, 2, true))
80 uassert.Equal(t, 2, r.RequiredApprovals)
81 uassert.True(t, r.AllowSelfApproval)
82
83 urequire.NoError(t, r.SetDefaultRef(bob, "refs/heads/trunk"))
84 uassert.Equal(t, "refs/heads/trunk", r.DefaultRef)
85
86 // An archived repo takes no writes at all.
87 urequire.NoError(t, r.SetArchived(alice, true))
88 _, err := r.SetRef(alice, 101, "refs/heads/trunk", "", oid("a"), "")
89 uassert.ErrorIs(t, err, ErrRepoArchived)
90 _, err = r.OpenIssue(eve, 101, "hello", "", nil)
91 uassert.ErrorIs(t, err, ErrRepoArchived)
92 urequire.NoError(t, r.SetArchived(alice, false))
93}
94
95func TestForkSnapshotsRefs(t *testing.T) {
96 f, r := newRepo(t)
97 urequire.NoError(t, r.SetMirrors(alice, []string{"https://github.com/moul/gno-contracts.git"}))
98 _, err := r.SetRef(alice, 101, "refs/heads/main", "", oid("a"), "initial")
99 urequire.NoError(t, err)
100 _, err = r.SetRef(alice, 102, "refs/tags/v0.1.0", "", oid("b"), "tag")
101 urequire.NoError(t, err)
102
103 child, err := f.Fork(eve, 110, "moul/forge", "eve/forge")
104 urequire.NoError(t, err)
105 uassert.Equal(t, "moul/forge", child.ParentID)
106 uassert.Equal(t, "owner", child.RoleOf(eve).String(), "the forker owns the fork")
107 uassert.Equal(t, 2, child.RefCount(), "refs are snapshotted")
108 uassert.Equal(t, 2, child.LogSize(), "and the snapshot is in the log")
109 uassert.Equal(t, oid("a"), child.Ref("refs/heads/main").OID)
110 uassert.Equal(t, 1, len(child.Mirrors), "the fork inherits where to fetch objects")
111
112 ok, bad := child.VerifyLog()
113 uassert.True(t, ok, "fork log is a valid chain")
114 uassert.Equal(t, int64(-1), bad)
115
116 _, err = f.Fork(eve, 111, "moul/nope", "eve/nope")
117 uassert.ErrorIs(t, err, ErrRepoNotFound)
118 _, err = f.Fork(eve, 111, "moul/forge", "eve/forge")
119 uassert.ErrorIs(t, err, ErrRepoExists)
120}
121
122func TestIterateReposAndNamespace(t *testing.T) {
123 f := New()
124 for _, id := range []string{"alice/one", "alice/two", "bob/three"} {
125 _, err := f.CreateRepo(alice, 1, id, "", "")
126 urequire.NoError(t, err)
127 }
128
129 var all []string
130 f.IterateRepos(0, 0, func(r *Repo) bool {
131 all = append(all, r.ID)
132 return false
133 })
134 uassert.Equal(t, "alice/one,alice/two,bob/three", join(all))
135
136 var ns []string
137 f.IterateNamespace("alice", func(r *Repo) bool {
138 ns = append(ns, r.ID)
139 return false
140 })
141 uassert.Equal(t, "alice/one,alice/two", join(ns))
142
143 var page []string
144 f.IterateRepos(1, 1, func(r *Repo) bool {
145 page = append(page, r.ID)
146 return false
147 })
148 uassert.Equal(t, "alice/two", join(page))
149}
150
151func join(ss []string) string {
152 out := ""
153 for i, s := range ss {
154 if i > 0 {
155 out += ","
156 }
157 out += s
158 }
159 return out
160}