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.

dev_test.gno

4.51 Kb · 166 lines
  1package dev
  2
  3import (
  4	"chain/runtime"
  5	"strconv"
  6	"strings"
  7	"testing"
  8
  9	"gno.land/p/nt/testutils/v0"
 10	"gno.land/p/nt/uassert/v0"
 11
 12	ninep "gno.land/p/nym-moultest123/x/plan9/ninep/v0"
 13
 14	nsrealm "gno.land/r/nym-moultest123/x/plan9/ns/v1"
 15)
 16
 17func read(t *testing.T, name string) string {
 18	t.Helper()
 19	f, err := tree.Root().Walk(name)
 20	if err != nil {
 21		t.Fatalf("walk %s: %v", name, err)
 22	}
 23	data, err := ninep.ReadAll(f)
 24	if err != nil {
 25		t.Fatalf("read %s: %v", name, err)
 26	}
 27	return data
 28}
 29
 30func TestDevicesFollowTheChain(t *testing.T) {
 31	if got, want := read(t, "sysname"), runtime.ChainID(); got != want {
 32		t.Errorf("sysname: got %q, want %q", got, want)
 33	}
 34	if got, want := read(t, "domain"), runtime.ChainDomain(); got != want {
 35		t.Errorf("domain: got %q, want %q", got, want)
 36	}
 37	if got, want := read(t, "height"), strconv.FormatInt(runtime.ChainHeight(), 10); got != want {
 38		t.Errorf("height: got %q, want %q", got, want)
 39	}
 40
 41	// A device is code, not storage: advance the chain and the file follows.
 42	before := read(t, "height")
 43	testing.SkipHeights(5)
 44	after := read(t, "height")
 45	if before == after {
 46		t.Errorf("height did not move: %q", after)
 47	}
 48	b, _ := strconv.ParseInt(before, 10, 64)
 49	a, _ := strconv.ParseInt(after, 10, 64)
 50	if a-b != 5 {
 51		t.Errorf("height moved by %d, want 5", a-b)
 52	}
 53}
 54
 55func TestRandomIsBlockDeterministic(t *testing.T) {
 56	a := read(t, "random")
 57	if len(a) != 64 {
 58		t.Errorf("a sha256 in hex is 64 characters, got %d", len(a))
 59	}
 60	if a != read(t, "random") {
 61		t.Error("two reads in the same block must agree, or Render is a consensus bug")
 62	}
 63	testing.SkipHeights(1)
 64	if a == read(t, "random") {
 65		t.Error("the value should change with the block")
 66	}
 67}
 68
 69func TestNullAndZero(t *testing.T) {
 70	if got := read(t, "null"); got != "" {
 71		t.Errorf("null: %q", got)
 72	}
 73	f, _ := tree.Root().Walk("zero")
 74	got, _ := f.Read(0, 4)
 75	if got != "\x00\x00\x00\x00" {
 76		t.Errorf("zero: %q", got)
 77	}
 78	// An endless file must not answer an unbounded read with an endless value.
 79	if got, _ := f.Read(0, -1); got != "" {
 80		t.Errorf("unbounded read of /dev/zero: %d bytes", len(got))
 81	}
 82	if got, _ := f.Read(0, 1<<20); len(got) != 4096 {
 83		t.Errorf("a huge read should cap at 4096, got %d", len(got))
 84	}
 85}
 86
 87func TestSessionReportsAPlainKey(t *testing.T) {
 88	got := read(t, "session")
 89	if got != "session no\nscope full\n" {
 90		t.Errorf("a plain key has no session scope: %q", got)
 91	}
 92}
 93
 94func TestDriversListsEveryDevice(t *testing.T) {
 95	got := read(t, "drivers")
 96	ents, err := tree.Root().ReadDir()
 97	if err != nil {
 98		t.Fatalf("readdir: %v", err)
 99	}
100	for _, e := range ents {
101		if !strings.Contains(got, e.Name+"\t") {
102			t.Errorf("/dev/drivers does not document %q", e.Name)
103		}
104	}
105	if len(ents) != len(docs) {
106		t.Errorf("%d devices but %d documented", len(ents), len(docs))
107	}
108}
109
110func TestTreeIsReadOnly(t *testing.T) {
111	var f ninep.File = tree.Root()
112	if _, ok := f.(ninep.Mutable); ok {
113		t.Error("a device tree handed to other realms must not be Mutable")
114	}
115}
116
117// TestPostedAtDeployTime is the cross-realm claim the whole suite rests on:
118// this realm pushed an interface value into another realm at init, and that
119// realm can call it back later from a read.
120func TestPostedAtDeployTime(t *testing.T) {
121	found := false
122	for _, s := range nsrealm.Services() {
123		if s == "dev" {
124			found = true
125		}
126	}
127	if !found {
128		t.Fatalf("dev is not posted in /srv: %v", nsrealm.Services())
129	}
130}
131
132func TestAFreshNamespaceHasDevBound(cur realm, t *testing.T) {
133	user := testutils.TestAddress("glenda")
134	testing.SetRealm(testing.NewUserRealm(user))
135	nsrealm.Reset(cross(cur))
136	// Touch the namespace so it is built with /dev already bound.
137	nsrealm.Exec(cross(cur), "echo hi > /tmp/hi")
138
139	out, err := nsrealm.Run(user.String(), "ls /dev")
140	if err != nil {
141		t.Fatalf("ls /dev: %v", err)
142	}
143	for _, d := range docs {
144		if !strings.Contains(out, d[0]) {
145			t.Errorf("ls /dev is missing %q: %q", d[0], out)
146		}
147	}
148	got, err := nsrealm.Run(user.String(), "cat /dev/sysname")
149	if err != nil {
150		t.Fatalf("cat: %v", err)
151	}
152	if got != runtime.ChainID() {
153		t.Errorf("reading this realm's device through another realm's namespace: %q", got)
154	}
155	// And the mount table says where it came from.
156	if ns := nsrealm.Namespace(user.String()); !strings.Contains(ns, "bind /srv/dev /dev") {
157		t.Errorf("mount table: %q", ns)
158	}
159}
160
161// The device name comes from the URL: escaped in the heading.
162func TestDeviceNameIsEscaped(t *testing.T) {
163	// No slash in the payload: Render splits the path on "/".
164	out := Render("cat/x` [claim](evil.example) `")
165	uassert.False(t, strings.Contains(out, "[claim](evil.example)"), out)
166}