release_test.gno
4.90 Kb · 155 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 TestValidTag(t *testing.T) {
11 cases := []struct {
12 name string
13 tag string
14 want bool
15 }{
16 {"semver", "v1.2.0", true},
17 // gno.land's own packages are v0 and v1 with no minor or patch. A tag
18 // rule that refused those would refuse the ecosystem it serves.
19 {"a gno version", "v0", true},
20 {"a prerelease", "v1.0.0-rc.1", true},
21 {"build metadata", "v1.0.0+build.5", true},
22 {"not version shaped at all", "genesis-snapshot", true},
23 {"empty", "", false},
24 {"a slash", "release/v1", false},
25 {"a traversal", "v1..0", false},
26 {"a space", "v1 0", false},
27 }
28 for _, tc := range cases {
29 t.Run(tc.name, func(t *testing.T) {
30 uassert.Equal(t, tc.want, ValidTag(tc.tag))
31 })
32 }
33}
34
35func TestCutRelease(t *testing.T) {
36 _, r := newRepo(t)
37
38 rel, err := r.CutRelease(carol, 300, "v1.0.0", "First", "it works", oid("a"), "refs/tags/v1.0.0", false)
39 urequire.NoError(t, err)
40 uassert.Equal(t, "v1.0.0", rel.Tag)
41 uassert.Equal(t, "First", rel.Name)
42 uassert.Equal(t, int64(300), rel.CreatedAt)
43 uassert.False(t, rel.Prerelease)
44 uassert.Equal(t, 1, r.ReleaseCount())
45
46 got := r.Release("v1.0.0")
47 urequire.True(t, got != nil)
48 uassert.Equal(t, "it works", got.Notes)
49 uassert.True(t, r.Release("v9.9.9") == nil)
50}
51
52// A consumer who pinned v1.2.0 and later got different bytes has been lied to.
53// The whole point of a tag is that it does not move.
54func TestCutReleaseIsImmutable(t *testing.T) {
55 _, r := newRepo(t)
56
57 _, err := r.CutRelease(alice, 300, "v1.0.0", "First", "", oid("a"), "", false)
58 urequire.NoError(t, err)
59 _, err = r.CutRelease(alice, 400, "v1.0.0", "Second", "", oid("b"), "", false)
60 uassert.ErrorIs(t, err, ErrReleaseExists)
61 uassert.Equal(t, oid("a"), r.Release("v1.0.0").OID)
62}
63
64// Cut order, never tag order: a lexical sort presents v10 before v2 and calls
65// it newest, and there is no semver to sort by because the tags are not
66// required to be semver.
67func TestIterateReleasesIsCutOrderNotTagOrder(t *testing.T) {
68 _, r := newRepo(t)
69
70 for i, tag := range []string{"v2.0.0", "v10.0.0", "v3.0.0"} {
71 _, err := r.CutRelease(alice, int64(300+i), tag, "", "", "", "", false)
72 urequire.NoError(t, err)
73 }
74
75 var seen []string
76 r.IterateReleases(0, 0, func(rel *Release) bool {
77 seen = append(seen, rel.Tag)
78 return false
79 })
80 urequire.Equal(t, 3, len(seen))
81 uassert.Equal(t, "v3.0.0", seen[0])
82 uassert.Equal(t, "v10.0.0", seen[1])
83 uassert.Equal(t, "v2.0.0", seen[2])
84}
85
86func TestLatestReleaseSkipsPrereleaseAndYanked(t *testing.T) {
87 _, r := newRepo(t)
88
89 _, err := r.CutRelease(alice, 300, "v1.0.0", "", "", "", "", false)
90 urequire.NoError(t, err)
91 uassert.Equal(t, "v1.0.0", r.LatestRelease().Tag)
92
93 // A prerelease is cut later and is still not the latest.
94 _, err = r.CutRelease(alice, 310, "v2.0.0-rc.1", "", "", "", "", true)
95 urequire.NoError(t, err)
96 uassert.Equal(t, "v1.0.0", r.LatestRelease().Tag)
97
98 _, err = r.CutRelease(alice, 320, "v2.0.0", "", "", "", "", false)
99 urequire.NoError(t, err)
100 uassert.Equal(t, "v2.0.0", r.LatestRelease().Tag)
101
102 // Yanking moves it back, and does not delete it.
103 urequire.NoError(t, r.YankRelease(alice, "v2.0.0", "broken migration"))
104 uassert.Equal(t, "v1.0.0", r.LatestRelease().Tag)
105 uassert.Equal(t, 3, r.ReleaseCount())
106 yanked := r.Release("v2.0.0")
107 urequire.True(t, yanked != nil)
108 uassert.True(t, yanked.Yanked)
109 uassert.Equal(t, "broken migration", yanked.YankReason)
110}
111
112func TestLatestReleaseIsNilWhenThereIsNone(t *testing.T) {
113 _, r := newRepo(t)
114 uassert.True(t, r.LatestRelease() == nil)
115
116 _, err := r.CutRelease(alice, 300, "v1.0.0-rc.1", "", "", "", "", true)
117 urequire.NoError(t, err)
118 uassert.True(t, r.LatestRelease() == nil)
119}
120
121func TestReleaseAuthorityAndValidation(t *testing.T) {
122 _, r := newRepo(t)
123
124 _, err := r.CutRelease(dave, 300, "v1.0.0", "", "", "", "", false)
125 uassert.ErrorIs(t, err, ErrUnauthorized)
126 _, err = r.CutRelease(eve, 300, "v1.0.0", "", "", "", "", false)
127 uassert.ErrorIs(t, err, ErrUnauthorized)
128
129 _, err = r.CutRelease(alice, 300, "release/v1", "", "", "", "", false)
130 uassert.ErrorIs(t, err, ErrInvalidTag)
131
132 _, err = r.CutRelease(alice, 300, "v1.0.0", "", "", "nothex", "", false)
133 uassert.ErrorIs(t, err, ErrInvalidOID)
134
135 _, err = r.CutRelease(alice, 300, "v1.0.0", "", "", "", "v1.0.0", false)
136 uassert.ErrorIs(t, err, ErrInvalidRefName)
137
138 uassert.ErrorIs(t, r.YankRelease(dave, "v1.0.0", ""), ErrUnauthorized)
139 uassert.ErrorIs(t, r.YankRelease(alice, "v9.9.9", ""), ErrReleaseNotFound)
140
141 urequire.NoError(t, r.SetArchived(alice, true))
142 _, err = r.CutRelease(alice, 300, "v1.0.0", "", "", "", "", false)
143 uassert.ErrorIs(t, err, ErrRepoArchived)
144}
145
146func TestForkInheritsNoReleases(t *testing.T) {
147 f, r := newRepo(t)
148 _, err := r.CutRelease(alice, 300, "v1.0.0", "", "", "", "", false)
149 urequire.NoError(t, err)
150
151 child, err := f.Fork(eve, 310, r.ID, "eve/forge")
152 urequire.NoError(t, err)
153 uassert.Equal(t, 0, child.ReleaseCount())
154 uassert.True(t, child.LatestRelease() == nil)
155}