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.

pkg_test.gno

6.11 Kb · 165 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 TestValidPkgPath(t *testing.T) {
 11	cases := []struct {
 12		name string
 13		path string
 14		want bool
 15	}{
 16		{"a realm", "gno.land/r/nym-moultest123/home", true},
 17		{"a pure package", "gno.land/p/nym-moultest123/forge/v1", true},
 18		{"deep", "gno.land/r/nym-moultest123/x/daily/asciiart/v0", true},
 19		{"an address namespace", "gno.land/r/g1abc/thing", true},
 20		{"underscores and dashes", "gno.land/r/ns/a-b_c", true},
 21		// Shape only. A realm cannot ask the chain whether a path is deployed,
 22		// so anything stricter would be a check that only sometimes works.
 23		{"not deployed but well formed", "gno.land/r/nobody/nothing", true},
 24		{"empty", "", false},
 25		{"two parts", "gno.land/r", false},
 26		{"a traversal", "gno.land/r/../etc", false},
 27		{"trailing slash", "gno.land/r/nym-moultest123/home/", false},
 28		{"an empty element", "gno.land//r/moul", false},
 29		{"a space", "gno.land/r/nym-moultest123/my home", false},
 30		{"a colon", "gno.land/r/nym-moultest123/home:tab", false},
 31	}
 32	for _, tc := range cases {
 33		t.Run(tc.name, func(t *testing.T) {
 34			uassert.Equal(t, tc.want, ValidPkgPath(tc.path))
 35		})
 36	}
 37}
 38
 39func TestPublishPackageIndexesForgeWide(t *testing.T) {
 40	f, r := newRepo(t)
 41
 42	p, err := f.PublishPackage(carol, 200, r.ID, "gno.land/r/nym-moultest123/home", "refs/heads/main", oid("a"), "")
 43	urequire.NoError(t, err)
 44	uassert.Equal(t, "gno.land/r/nym-moultest123/home", p.Path)
 45	uassert.Equal(t, r.ID, p.RepoID)
 46	uassert.Equal(t, int64(200), p.PublishedAt)
 47
 48	// The lookup an explorer makes: it starts from the path and does not know
 49	// the repo yet, which is the whole reason the index is forge-wide.
 50	uassert.Equal(t, r.ID, f.PackageRepo("gno.land/r/nym-moultest123/home"))
 51	uassert.Equal(t, "", f.PackageRepo("gno.land/r/someone/else"))
 52	uassert.Equal(t, 1, f.PackageCount())
 53	uassert.Equal(t, 1, r.PackageCount())
 54}
 55
 56// One repo publishes many paths: gno-contracts publishes 193.
 57func TestPublishManyPackages(t *testing.T) {
 58	f, r := newRepo(t)
 59
 60	paths := []string{
 61		"gno.land/r/nym-moultest123/home",
 62		"gno.land/p/nym-moultest123/forge/v1",
 63		"gno.land/r/nym-moultest123/blog",
 64	}
 65	for _, path := range paths {
 66		_, err := f.PublishPackage(alice, 200, r.ID, path, "", "", "")
 67		urequire.NoError(t, err)
 68	}
 69	uassert.Equal(t, 3, r.PackageCount())
 70
 71	var seen []string
 72	r.IteratePackages(0, 0, func(p *Package) bool {
 73		seen = append(seen, p.Path)
 74		return false
 75	})
 76	// Path order, which is what the tree gives and what a file list wants.
 77	urequire.Equal(t, 3, len(seen))
 78	uassert.Equal(t, "gno.land/p/nym-moultest123/forge/v1", seen[0])
 79	uassert.Equal(t, "gno.land/r/nym-moultest123/blog", seen[1])
 80	uassert.Equal(t, "gno.land/r/nym-moultest123/home", seen[2])
 81}
 82
 83// Re-publishing the same path from the same repo is a redeploy, and overwrites.
 84func TestRepublishOverwrites(t *testing.T) {
 85	f, r := newRepo(t)
 86
 87	_, err := f.PublishPackage(alice, 200, r.ID, "gno.land/r/nym-moultest123/home", "", oid("a"), "v1.0.0")
 88	urequire.NoError(t, err)
 89	_, err = f.PublishPackage(alice, 300, r.ID, "gno.land/r/nym-moultest123/home", "", oid("b"), "v1.1.0")
 90	urequire.NoError(t, err)
 91
 92	uassert.Equal(t, 1, f.PackageCount())
 93	got := f.PackageAt("gno.land/r/nym-moultest123/home")
 94	urequire.True(t, got != nil)
 95	uassert.Equal(t, oid("b"), got.OID)
 96	uassert.Equal(t, "v1.1.0", got.Tag)
 97	uassert.Equal(t, int64(300), got.PublishedAt)
 98}
 99
100// Silently moving a claimed path would let any repo owner capture another
101// project's package in every explorer that reads this index.
102func TestPublishRefusesAnotherReposPath(t *testing.T) {
103	f, r := newRepo(t)
104	_, err := f.PublishPackage(alice, 200, r.ID, "gno.land/r/nym-moultest123/home", "", "", "")
105	urequire.NoError(t, err)
106
107	other, err := f.CreateRepo(eve, 210, "eve/squat", "", "")
108	urequire.NoError(t, err)
109
110	_, err = f.PublishPackage(eve, 220, other.ID, "gno.land/r/nym-moultest123/home", "", "", "")
111	uassert.ErrorIs(t, err, ErrPackageClaimed)
112	uassert.Equal(t, r.ID, f.PackageRepo("gno.land/r/nym-moultest123/home"))
113}
114
115func TestPublishAuthorityAndValidation(t *testing.T) {
116	f, r := newRepo(t)
117
118	// dave is a reader, eve is nothing: neither may publish.
119	_, err := f.PublishPackage(dave, 200, r.ID, "gno.land/r/nym-moultest123/home", "", "", "")
120	uassert.ErrorIs(t, err, ErrUnauthorized)
121	_, err = f.PublishPackage(eve, 200, r.ID, "gno.land/r/nym-moultest123/home", "", "", "")
122	uassert.ErrorIs(t, err, ErrUnauthorized)
123
124	_, err = f.PublishPackage(alice, 200, "nobody/nothing", "gno.land/r/x/y", "", "", "")
125	uassert.ErrorIs(t, err, ErrRepoNotFound)
126
127	_, err = f.PublishPackage(alice, 200, r.ID, "not a path", "", "", "")
128	uassert.ErrorIs(t, err, ErrInvalidPkgPath)
129
130	_, err = f.PublishPackage(alice, 200, r.ID, "gno.land/r/nym-moultest123/home", "main", "", "")
131	uassert.ErrorIs(t, err, ErrInvalidRefName)
132
133	_, err = f.PublishPackage(alice, 200, r.ID, "gno.land/r/nym-moultest123/home", "", "nothex", "")
134	uassert.ErrorIs(t, err, ErrInvalidOID)
135
136	urequire.NoError(t, r.SetArchived(alice, true))
137	_, err = f.PublishPackage(alice, 200, r.ID, "gno.land/r/nym-moultest123/home", "", "", "")
138	uassert.ErrorIs(t, err, ErrRepoArchived)
139}
140
141func TestUnpublishClearsBothHalvesOfTheIndex(t *testing.T) {
142	f, r := newRepo(t)
143	_, err := f.PublishPackage(alice, 200, r.ID, "gno.land/r/nym-moultest123/home", "", "", "")
144	urequire.NoError(t, err)
145
146	uassert.ErrorIs(t, f.UnpublishPackage(dave, r.ID, "gno.land/r/nym-moultest123/home"), ErrUnauthorized)
147	uassert.ErrorIs(t, f.UnpublishPackage(alice, r.ID, "gno.land/r/nothing"), ErrPackageNotFound)
148
149	urequire.NoError(t, f.UnpublishPackage(alice, r.ID, "gno.land/r/nym-moultest123/home"))
150	uassert.Equal(t, 0, f.PackageCount())
151	uassert.Equal(t, 0, r.PackageCount())
152	uassert.Equal(t, "", f.PackageRepo("gno.land/r/nym-moultest123/home"))
153}
154
155// A fork is not a publisher of its parent's paths.
156func TestForkInheritsNoPackages(t *testing.T) {
157	f, r := newRepo(t)
158	_, err := f.PublishPackage(alice, 200, r.ID, "gno.land/r/nym-moultest123/home", "", "", "")
159	urequire.NoError(t, err)
160
161	child, err := f.Fork(eve, 210, r.ID, "eve/forge")
162	urequire.NoError(t, err)
163	uassert.Equal(t, 0, child.PackageCount())
164	uassert.Equal(t, r.ID, f.PackageRepo("gno.land/r/nym-moultest123/home"))
165}