Kind Realm (renderable)
Name v0
Namespace moul / gnopm / registry
Exported functions 7
Module gno.land/r/moul/gnopm/registry/v0
gno 0.9 registry_test.gno gno
⧉
1 package registry 2 3 import ( 4 "strings" 5 "testing" 6 7 "gno.land/p/nt/uassert/v0" 8 ClaimCount () int
HasClaims (pkgPath string) bool
OwnerClaim (pkgPath string) (repo string, commit string, dir string, ok bool)
PackageCount () int
Register (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, pkgPath string, repo string, commit string, dir string, ref string)
Render (path string) string
Withdraw (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, pkgPath string)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
)
9
10 func TestRegisterAndWithdraw(cur realm, t *testing.T) {
11 reset()
12 testing.SetRealm(testing.NewUserRealm(alice))
13 Register(cross(cur), otherPkg, repoURL, sha1Zero, "p/moul/md" , "refs/heads/main" )
14
15 uassert.Equal(t, 1 , PackageCount())
16 uassert.Equal(t, 1 , ClaimCount())
17 uassert.True(t, HasClaims(otherPkg))
18 uassert.False(t, HasClaims( "gno.land/p/moul/nope/v0" ))
19
20 testing.SetRealm(testing.NewUserRealm(alice))
21 Withdraw(cross(cur), otherPkg)
22 uassert.Equal(t, 0 , PackageCount())
23 uassert.False(t, HasClaims(otherPkg))
24 }
25
26 // A claim is the claimant's own. Nobody else may take it back, and the refusal
27 // has to abort rather than silently do nothing: a Withdraw that quietly did
28 // nothing reads to the caller exactly like one that worked.
29 func TestWithdrawIsNotTransferable(cur realm, t *testing.T) {
30 reset()
31 testing.SetRealm(testing.NewUserRealm(alice))
32 Register(cross(cur), otherPkg, repoURL, sha1Zero, "" , "" )
33
34 testing.SetRealm(testing.NewUserRealm(bob))
35 uassert.AbortsContains(t, cur, "no such claim" , func () {
36 Withdraw(cross(cur), otherPkg)
37 })
38 uassert.True(t, HasClaims(otherPkg), "alice's claim survived bob" )
39 }
40
41 func TestRegisterAborts(cur realm, t *testing.T) {
42 reset()
43 cases := [] struct {
44 name string
45 pkgPath, repo, commit, dir, ref string
46 contains string
47 }{
48 { "bad path" , "nonsense" , repoURL, sha1Zero, "" , "" , "invalid package path" },
49 { "non-https repo" , otherPkg, "javascript:alert(1)" , sha1Zero, "" , "" , "invalid repository URL" },
50 { "abbreviated commit" , otherPkg, repoURL, "0123456" , "" , "" , "invalid commit id" },
51 { "absolute dir" , otherPkg, repoURL, sha1Zero, "/etc" , "" , "invalid directory" },
52 { "unqualified ref" , otherPkg, repoURL, sha1Zero, "" , "main" , "invalid ref name" },
53 }
54 for _, tc := range cases {
55 testing.SetRealm(testing.NewUserRealm(alice))
56 uassert.AbortsContains(t, cur, tc.contains, func () {
57 Register(cross(cur), tc.pkgPath, tc.repo, tc.commit, tc.dir, tc.ref)
58 }, tc.name)
59 }
60 uassert.Equal(t, 0 , ClaimCount(), "nothing was stored" )
61 }
62
63 // OwnerClaim is the only read that filters, and it filters on the one thing
64 // about a claim the chain can prove. An address namespace belongs to that
65 // account with nothing registered anywhere, so it is testable without
66 // r/sys/users, which a test cannot write to.
67 func TestOwnerClaim(cur realm, t *testing.T) {
68 reset()
69
70 testing.SetRealm(testing.NewUserRealm(bob))
71 Register(cross(cur), alicePkg, "https://github.com/bob/impostor" , sha1One, "" , "" )
72 _, _, _, ok := OwnerClaim(alicePkg)
73 uassert.False(t, ok, "a stranger's claim is not the owner's" )
74
75 testing.SetRealm(testing.NewUserRealm(alice))
76 Register(cross(cur), alicePkg, repoURL, sha1Zero, "scratch" , "" )
77 repo, commit, dir, ok := OwnerClaim(alicePkg)
78 uassert.True(t, ok, "the namespace holder's claim is found" )
79 uassert.Equal(t, repoURL, repo)
80 uassert.Equal(t, sha1Zero, commit)
81 uassert.Equal(t, "scratch" , dir)
82
83 _, _, _, ok = OwnerClaim( "gno.land/p/moul/nothing/v0" )
84 uassert.False(t, ok, "an unclaimed path has no owner claim" )
85 }
86
87 // Re-registering moves the caller's own claim and creates no second one.
88 func TestReregister(cur realm, t *testing.T) {
89 reset()
90 testing.SetRealm(testing.NewUserRealm(alice))
91 Register(cross(cur), otherPkg, repoURL, sha1Zero, "p/moul/md" , "" )
92 testing.SkipHeights( 10 )
93 testing.SetRealm(testing.NewUserRealm(alice))
94 Register(cross(cur), otherPkg, repoURL, sha1One, "p/moul/md" , "refs/tags/v1" )
95
96 uassert.Equal(t, 1 , ClaimCount())
97 got := Render(otherPkg)
98 uassert.True(t, strings.Contains(got, sha1One[: 12 ]), "the new commit renders" )
99 uassert.False(t, strings.Contains(got, sha1Zero[: 12 ]), "the old one is gone" )
100 uassert.True(t, strings.Contains(got, "| last updated | block" ), "an updated claim says when" )
101 }
102
103 // A package path arrives at Render already split on "/", so the routing is the
104 // rejoin. Anything that does not reassemble into a path is a miss, and a miss
105 // must not render as an empty package page.
106 func TestRenderRouting(t *testing.T) {
107 reset()
108 uassert.True(t, strings.Contains(Render( "nonsense" ), "Not found" ), "one bad element" )
109 uassert.True(t, strings.Contains(Render( "a/b/c" ), "Not found" ), "too few elements" )
110 uassert.True(t, strings.Contains(Render( "help" ), "How this registry works" ), "help page" )
111 uassert.True(t, strings.Contains(Render( "" ), "gnopm source registry" ), "home" )
112 uassert.True(t, strings.Contains(Render(otherPkg), "Nobody has claimed" ), "valid but unclaimed" )
113 }
114
115 // The page ranks the owner's claim above a stranger's and says which is which.
116 // Rendering them identically is the whole mistake this realm exists to avoid,
117 // so the separation is pinned rather than left to review.
118 func TestRenderSeparatesOwnerFromStranger(t *testing.T) {
119 seedFixture()
120
121 got := Render(alicePkg)
122 iOwner := strings.Index(got, "Claimed by the namespace owner" )
123 iOthers := strings.Index(got, "Claimed by others" )
124 uassert.True(t, iOwner >= 0 , "the owner section exists" )
125 uassert.True(t, iOthers >= 0 , "the others section exists" )
126 uassert.True(t, iOwner < iOthers, "the owner is ranked first" )
127 uassert.True(t, strings.Contains(got, "impostor" ), "a stranger's claim is shown, not hidden" )
128 uassert.True(t, strings.Contains(got, "do not own" ), "and is labelled as not the owner's" )
129 }
130
vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.