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

gns_test.gno

2.92 Kb · 97 lines
 1package gns
 2
 3import (
 4	"testing"
 5)
 6
 7func TestNormalize(t *testing.T) {
 8	reset()
 9
10	cases := []struct {
11		in  string
12		out string
13		ok  bool
14	}{
15		{"alice", "alice", true},
16		{"ALICE", "alice", true},
17		{"Wallet.Alice", "wallet.alice", true},
18		{"a", "a", true},
19		{"a1-b", "a1-b", true},
20		{"-alice", "", false}, // leading hyphen
21		{"alice-", "", false}, // trailing hyphen
22		{"", "", false},       // empty
23		{"a..b", "", false},   // empty label (double dot)
24		{"al ice", "", false}, // space
25		{"café", "", false},   // non-ASCII
26		{"a_b", "", false},    // underscore not allowed
27	}
28	for _, tc := range cases {
29		got, err := Normalize(tc.in)
30		if tc.ok {
31			noErr(t, err, "normalize "+tc.in)
32			eqStr(t, tc.out, got, "normalize "+tc.in)
33		} else {
34			isErr(t, err, "expected error for "+tc.in)
35		}
36	}
37}
38
39func TestNormalizeDepthAndLength(t *testing.T) {
40	reset()
41
42	deep := "a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a" // 17 labels > maxDepth
43	_, err := Normalize(deep)
44	isErr(t, err, "excessive depth rejected")
45
46	long := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" // 64 > 63
47	_, err = Normalize(long)
48	isErr(t, err, "excessive label length rejected")
49}
50
51func TestStatusAndOwnerLifecycle(cur realm, t *testing.T) {
52	reset()
53
54	eqStr(t, string(StatusAvailable), string(Status("alice")), "initial status")
55	isFalse(t, Exists("alice"), "not exists initially")
56
57	doRegister(cur, "alice", alice, 1000)
58
59	eqStr(t, string(StatusActive), string(Status("alice")), "post-register status")
60	isTrue(t, Exists("alice"), "exists after register")
61
62	owner, ok := OwnerOf("alice")
63	isTrue(t, ok, "ownerOf ok")
64	eqStr(t, alice.String(), owner, "owner is alice")
65
66	view, ok := GetName("alice")
67	isTrue(t, ok, "getName ok")
68	eqInt(t, 1, int64(view.Generation), "generation 1")
69	eqStr(t, "alice", view.Canonical, "canonical")
70
71	// advance past expiry, into grace (expiry ≈ +1000s, grace ends ≈ +1100s)
72	testing.SkipHeights(210) // +1050s
73	eqStr(t, string(StatusGrace), string(Status("alice")), "grace status")
74	_, ok = OwnerOf("alice")
75	isTrue(t, ok, "owner known during grace")
76
77	// advance well past grace -> Expired
78	testing.SkipHeights(200) // +1000s more, far beyond grace end
79	eqStr(t, string(StatusExpired), string(Status("alice")), "expired status")
80	isFalse(t, Exists("alice"), "not exists after grace")
81}
82
83func TestExpiredOwnerLosesAuthority(cur realm, t *testing.T) {
84	reset()
85	doRegister(cur, "alice", alice, 1000)
86
87	testing.SkipHeights(300) // beyond grace
88	eqStr(t, string(StatusExpired), string(Status("alice")), "expired")
89
90	// Invariant 2: an expired name grants no owner mutation authority. Tested
91	// against the single authorization gate directly (mutations funnel through
92	// it, then panic on the returned error).
93	n := getRaw("alice")
94	isTrue(t, n != nil, "raw name present")
95	errIs(t, authorize(alice, n, PermManageRecords), errUnauthorized, "expired owner authorize")
96	errIs(t, authorize(alice, n, PermTransfer), errUnauthorized, "expired owner transfer")
97}