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

validate_test.gno

5.13 Kb · 174 lines
  1package forge
  2
  3import (
  4	"strings"
  5	"testing"
  6
  7	"gno.land/p/nt/testutils/v0"
  8	"gno.land/p/nt/uassert/v0"
  9)
 10
 11func TestValidOID(t *testing.T) {
 12	cases := []struct {
 13		name string
 14		in   string
 15		want bool
 16	}{
 17		{"sha1", strings.Repeat("a", 40), true},
 18		{"sha256", strings.Repeat("0", 64), true},
 19		{"mixed hex", "0123456789abcdef0123456789abcdef01234567", true},
 20		{"empty", "", false},
 21		{"too short", strings.Repeat("a", 39), false},
 22		{"between lengths", strings.Repeat("a", 41), false},
 23		{"uppercase", strings.Repeat("A", 40), false},
 24		{"non hex", strings.Repeat("z", 40), false},
 25		{"abbreviated", "deadbeef", false},
 26	}
 27	for _, tc := range cases {
 28		uassert.Equal(t, tc.want, ValidOID(tc.in), tc.name)
 29	}
 30}
 31
 32func TestValidRefName(t *testing.T) {
 33	cases := []struct {
 34		name string
 35		in   string
 36		want bool
 37	}{
 38		{"branch", "refs/heads/main", true},
 39		{"nested branch", "refs/heads/feat/on-chain-log", true},
 40		{"tag", "refs/tags/v1.0.0", true},
 41		{"stash-like", "refs/stash", true},
 42		{"unqualified", "main", false},
 43		{"empty", "", false},
 44		{"double slash", "refs/heads//main", false},
 45		{"double dot", "refs/heads/a..b", false},
 46		{"at brace", "refs/heads/a@{0}", false},
 47		{"trailing slash", "refs/heads/", false},
 48		{"trailing dot", "refs/heads/main.", false},
 49		{"dot prefix", "refs/heads/.hidden", false},
 50		{"lock suffix", "refs/heads/main.lock", false},
 51		{"space", "refs/heads/my branch", false},
 52		{"caret", "refs/heads/main^", false},
 53		{"colon", "refs/heads/a:b", false},
 54		{"tilde", "refs/heads/main~1", false},
 55		{"question", "refs/heads/what?", false},
 56		{"star", "refs/heads/*", false},
 57		{"backslash", "refs/heads/a\\b", false},
 58		{"control", "refs/heads/a\x01b", false},
 59		{"too long", "refs/heads/" + strings.Repeat("a", 300), false},
 60	}
 61	for _, tc := range cases {
 62		uassert.Equal(t, tc.want, ValidRefName(tc.in), tc.name)
 63	}
 64}
 65
 66func TestValidRepoID(t *testing.T) {
 67	cases := []struct {
 68		name string
 69		in   string
 70		want bool
 71	}{
 72		{"simple", "moul/forge", true},
 73		{"digits", "ns0/repo9", true},
 74		{"dots and dashes", "moul/gno-contracts.x", true},
 75		{"underscore", "moul/my_repo", true},
 76		{"no slash", "forge", false},
 77		{"two slashes", "a/b/c", false},
 78		{"empty ns", "/forge", false},
 79		{"empty name", "moul/", false},
 80		{"uppercase", "Moul/forge", false},
 81		{"leading dash", "moul/-forge", false},
 82		{"trailing dot", "moul/forge.", false},
 83		{"double dot", "moul/fo..rge", false},
 84		{"double dash", "moul/fo--rge", false},
 85		{"space", "moul/my forge", false},
 86		{"too long", "moul/" + strings.Repeat("a", 40), false},
 87	}
 88	for _, tc := range cases {
 89		uassert.Equal(t, tc.want, ValidRepoID(tc.in), tc.name)
 90	}
 91}
 92
 93func TestAddressNamespace(t *testing.T) {
 94	addr := testutils.TestAddress("alice").String()
 95	cases := []struct {
 96		name string
 97		in   string
 98		want bool
 99	}{
100		{"a real address", addr, true},
101		{"wrong prefix", "x1" + addr[2:], false},
102		{"too short", addr[:39], false},
103		{"too long", addr + "a", false},
104		{"bech32 drops b i o 1", "g1" + strings.Repeat("b", 38), false},
105		{"uppercase", "G1" + addr[2:], false},
106		{"a slug is not an address", "moul", false},
107	}
108	for _, tc := range cases {
109		uassert.Equal(t, tc.want, AddressNamespace(tc.in), tc.name)
110	}
111
112	// An address namespace is a valid repo id, and it cannot collide with a
113	// claimed name: 40 characters is past the slug cap.
114	uassert.True(t, ValidRepoID(addr+"/forge"))
115	uassert.False(t, ValidRepoID(strings.Repeat("a", 40)+"/forge"))
116	uassert.False(t, ValidRepoID(addr+"/"+addr), "the name half is always a slug")
117}
118
119func TestSplitRepoID(t *testing.T) {
120	ns, name, ok := SplitRepoID("moul/forge")
121	uassert.True(t, ok)
122	uassert.Equal(t, "moul", ns)
123	uassert.Equal(t, "forge", name)
124
125	for _, bad := range []string{"", "moul", "/forge", "moul/", "a/b/c"} {
126		_, _, ok := SplitRepoID(bad)
127		uassert.False(t, ok, bad)
128	}
129}
130
131func TestValidTextAndLine(t *testing.T) {
132	uassert.True(t, ValidText("hello\nworld\ttab", 64))
133	uassert.False(t, ValidText("bell\x07", 64))
134	uassert.False(t, ValidText("too long", 3))
135	uassert.True(t, ValidText("", 3))
136
137	uassert.True(t, ValidLine("a single line", 64))
138	uassert.False(t, ValidLine("two\nlines", 64))
139	uassert.False(t, ValidLine("a\ttab", 64))
140}
141
142func TestValidMirrorAndLabel(t *testing.T) {
143	cases := []struct {
144		in   string
145		want bool
146	}{
147		{"https://github.com/moul/gno-contracts.git", true},
148		{"[email protected]:moul/gno-contracts.git", true},
149		{"ipfs://bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku", true},
150		{"rad://z3gqcJUoA1n9HaHKufZs5FCSGazv5", true},
151		{"ar://1QKPaf1AmsK_tSSdUgtVDEYGLuQBOKTNr", true},
152		{"ftp://example.com/repo.git", false},
153		{"not a url", false},
154		{"", false},
155	}
156	for _, tc := range cases {
157		uassert.Equal(t, tc.want, ValidMirror(tc.in), tc.in)
158	}
159
160	uassert.True(t, ValidLabel("bug"))
161	uassert.False(t, ValidLabel(""))
162	uassert.False(t, ValidLabel("a,b"))
163	uassert.False(t, ValidLabel(strings.Repeat("x", 33)))
164}
165
166func TestParseRoleRoundTrip(t *testing.T) {
167	for _, r := range []Role{RoleNone, RoleReader, RoleWriter, RoleMaintainer, RoleAdmin, RoleOwner} {
168		got, err := ParseRole(r.String())
169		uassert.NoError(t, err, r.String())
170		uassert.Equal(t, int(r), int(got), r.String())
171	}
172	_, err := ParseRole("root")
173	uassert.ErrorIs(t, err, ErrInvalidRole)
174}