store_test.gno
6.95 Kb ยท 226 lines
1package users
2
3import (
4 "chain"
5 "testing"
6
7 "gno.land/p/nt/avl"
8 "gno.land/p/nt/testutils"
9 "gno.land/p/nt/uassert"
10 "gno.land/p/nt/urequire"
11)
12
13var (
14 alice = "alice"
15 aliceAddr = testutils.TestAddress(alice)
16 bob = "bob"
17 bobAddr = testutils.TestAddress(bob)
18
19 whitelistedCallerAddr = chain.PackageAddress(gUsersV1Path)
20)
21
22func TestRegister(t *testing.T) {
23 testing.SetRealm(testing.NewCodeRealm(gUsersV1Path))
24
25 t.Run("valid_registration", func(t *testing.T) {
26 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
27
28 res, isLatest := ResolveName(alice)
29 uassert.Equal(t, aliceAddr, res.Addr())
30 uassert.True(t, isLatest)
31
32 res = ResolveAddress(aliceAddr)
33 uassert.Equal(t, alice, res.Name())
34 })
35
36 t.Run("invalid_inputs", func(t *testing.T) {
37 cleanStore(t)
38
39 uassert.ErrorContains(t, RegisterUser(cross, "", aliceAddr), ErrEmptyUsername.Error())
40 uassert.ErrorContains(t, RegisterUser(cross, alice, ""), ErrInvalidAddress.Error())
41 uassert.ErrorContains(t, RegisterUser(cross, alice, "invalidaddress"), ErrInvalidAddress.Error())
42
43 uassert.ErrorContains(t, RegisterUser(cross, "username with a space", aliceAddr), ErrInvalidUsername.Error())
44 uassert.ErrorContains(t,
45 RegisterUser(cross, "verylongusernameverylongusernameverylongusernameverylongusername1", aliceAddr),
46 ErrInvalidUsername.Error())
47 uassert.ErrorContains(t, RegisterUser(cross, "namewith^&()", aliceAddr), ErrInvalidUsername.Error())
48 })
49
50 t.Run("addr_already_registered", func(t *testing.T) {
51 cleanStore(t)
52
53 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
54
55 // Try registering again
56 uassert.ErrorContains(t, RegisterUser(cross, "othername", aliceAddr), ErrAlreadyHasName.Error())
57 })
58
59 t.Run("name_taken", func(t *testing.T) {
60 cleanStore(t)
61
62 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
63
64 // Try registering alice's name with bob's address
65 uassert.ErrorContains(t, RegisterUser(cross, alice, bobAddr), ErrNameTaken.Error())
66 })
67
68 t.Run("user_deleted", func(t *testing.T) {
69 cleanStore(t)
70
71 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
72 data := ResolveAddress(aliceAddr)
73 urequire.NoError(t, data.Delete())
74
75 // Try re-registering after deletion
76 uassert.ErrorContains(t, RegisterUser(cross, "newname", aliceAddr), ErrDeletedUser.Error())
77 })
78
79 t.Run("address_lookalike", func(t *testing.T) {
80 cleanStore(t)
81
82 // Address as username
83 uassert.ErrorContains(t, RegisterUser(cross, "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5", aliceAddr), ErrNameLikeAddress.Error())
84 // Beginning of address as username
85 uassert.ErrorContains(t, RegisterUser(cross, "g1jg8mtutu9khhfwc4nxmu", aliceAddr), ErrNameLikeAddress.Error())
86 uassert.NoError(t, RegisterUser(cross, "g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5longerthananaddress", aliceAddr))
87 })
88}
89
90func TestUpdateName(t *testing.T) {
91 testing.SetRealm(testing.NewCodeRealm(gUsersV1Path))
92
93 t.Run("valid_direct_alias", func(t *testing.T) {
94 cleanStore(t)
95
96 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
97 data := ResolveAddress(aliceAddr)
98 {
99 testing.SetOriginCaller(whitelistedCallerAddr)
100 uassert.NoError(t, data.UpdateName("alice1"))
101 testing.SetRealm(testing.NewCodeRealm("gno.land/r/sys/users"))
102 }
103 })
104
105 t.Run("valid_double_alias", func(t *testing.T) {
106 cleanStore(t)
107
108 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
109 data := ResolveAddress(aliceAddr)
110 {
111 testing.SetOriginCaller(whitelistedCallerAddr)
112 uassert.NoError(t, data.UpdateName("alice2"))
113 uassert.NoError(t, data.UpdateName("alice3"))
114 testing.SetRealm(testing.NewCodeRealm("gno.land/r/sys/users"))
115 }
116 uassert.Equal(t, ResolveAddress(aliceAddr).username, "alice3")
117 })
118
119 t.Run("name_taken", func(t *testing.T) {
120 cleanStore(t)
121
122 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
123
124 data := ResolveAddress(aliceAddr)
125 uassert.Error(t, data.UpdateName(alice), ErrNameTaken.Error())
126 })
127
128 t.Run("alias_before_name", func(t *testing.T) {
129 cleanStore(t)
130 data := ResolveAddress(aliceAddr) // not registered
131
132 uassert.ErrorContains(t, data.UpdateName(alice), ErrUserNotExistOrDeleted.Error())
133 })
134
135 t.Run("alias_after_delete", func(t *testing.T) {
136 cleanStore(t)
137
138 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
139 data := ResolveAddress(aliceAddr)
140 {
141 urequire.NoError(t, data.Delete())
142 testing.SetRealm(testing.NewCodeRealm("gno.land/r/sys/users"))
143 }
144
145 data = ResolveAddress(aliceAddr)
146 {
147 uassert.ErrorContains(t, data.UpdateName("newalice"), ErrUserNotExistOrDeleted.Error())
148 testing.SetRealm(testing.NewCodeRealm("gno.land/r/sys/users"))
149 }
150 })
151
152 t.Run("invalid_inputs", func(t *testing.T) {
153 cleanStore(t)
154
155 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
156 data := ResolveAddress(aliceAddr)
157 {
158 testing.SetOriginCaller(whitelistedCallerAddr)
159 uassert.ErrorContains(t, data.UpdateName(""), ErrEmptyUsername.Error())
160 uassert.ErrorContains(t, data.UpdateName("username with a space"), ErrInvalidUsername.Error())
161 uassert.ErrorContains(t,
162 data.UpdateName("verylongusernameverylongusernameverylongusernameverylongusername1"),
163 ErrInvalidUsername.Error())
164 uassert.ErrorContains(t, data.UpdateName("namewith^&()"), ErrInvalidUsername.Error())
165 testing.SetRealm(testing.NewCodeRealm("gno.land/r/sys/users"))
166 }
167 })
168
169 t.Run("address_lookalike", func(t *testing.T) {
170 cleanStore(t)
171
172 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
173 data := ResolveAddress(aliceAddr)
174
175 {
176 // Address as username
177 uassert.ErrorContains(t, data.UpdateName("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5"), ErrNameLikeAddress.Error())
178 // Beginning of address as username
179 uassert.ErrorContains(t, data.UpdateName("g1jg8mtutu9khhfwc4nxmu"), ErrNameLikeAddress.Error())
180 uassert.NoError(t, data.UpdateName("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5longerthananaddress"))
181 testing.SetRealm(testing.NewCodeRealm("gno.land/r/sys/users"))
182 }
183 })
184}
185
186func TestDelete(t *testing.T) {
187 testing.SetRealm(testing.NewCodeRealm(gUsersV1Path))
188
189 t.Run("non_existent_user", func(t *testing.T) {
190 cleanStore(t)
191
192 data := ResolveAddress(testutils.TestAddress("unregistered"))
193 uassert.ErrorContains(t, data.Delete(), ErrUserNotExistOrDeleted.Error())
194 })
195
196 t.Run("double_delete", func(t *testing.T) {
197 cleanStore(t)
198
199 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
200 data := ResolveAddress(aliceAddr)
201 urequire.NoError(t, data.Delete())
202 data = ResolveAddress(aliceAddr)
203 uassert.ErrorContains(t, data.Delete(), ErrUserNotExistOrDeleted.Error())
204 })
205
206 t.Run("valid_delete", func(t *testing.T) {
207 cleanStore(t)
208
209 urequire.NoError(t, RegisterUser(cross, alice, aliceAddr))
210 data := ResolveAddress(aliceAddr)
211 uassert.NoError(t, data.Delete())
212
213 resolved1, _ := ResolveName(alice)
214 uassert.Equal(t, nil, resolved1)
215 uassert.Equal(t, nil, ResolveAddress(aliceAddr))
216 })
217}
218
219// cleanStore should not be needed, as vm store should be reset after each test.
220// Reference: https://github.com/gnolang/gno/issues/1982
221func cleanStore(t *testing.T) {
222 t.Helper()
223
224 nameStore = avl.NewTree()
225 addressStore = avl.NewTree()
226}