PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/moul/agents/msg/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
moul / agents / msg
Files
4 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/moul/agents/msg/v0
gno
0.9

Files (4)

  • README.mdmarkdown
  • gnomod.tomltoml
  • msg.gnogno
  • msg_test.gnogno
msg_test.gnogno
1package msg23import "testing"45func TestEncodeDecodeRoundTrip(t *testing.T) {6	tests := []struct {7		name string8		m    Msg9	}{10		{"plain", Msg{1, 100, "claude@hermey", "build", "note", "pr/12", "ci is green"}},11		{"empty optional fields", Msg{2, 0, "a", "t", "", "", "b"}},12		{"body holds the separator", Msg{3, 7, "a", "t", "k", "r", "3:abc:def"}},13		{"body holds a newline", Msg{4, 7, "a", "t", "k", "r", "line one\nline two"}},14		{"body holds an encoded message", Msg{5, 7, "a", "t", "k", "r", Msg{1, 1, "x", "y", "z", "w", "v"}.Encode()}},15		{"unicode body", Msg{6, 7, "a", "t", "k", "r", "héllo … 世界"}},16		{"max height", Msg{7, 9223372036854775807, "a", "t", "k", "r", "b"}},17	}18	for _, tt := range tests {19		got, ok := Decode(tt.m.Encode())20		if !ok {21			t.Errorf("%s: Decode reported failure", tt.name)22			continue23		}24		if got != tt.m {25			t.Errorf("%s: round trip changed the message", tt.name)26		}27	}28}2930func TestDecodeRejects(t *testing.T) {31	tests := []struct {32		name string33		s    string34	}{35		{"empty, which is an unwritten ring slot", ""},36		{"not length-prefixed", "hello"},37		{"too few fields", "1:1" + "1:2"},38		{"length runs past the end", "99:short"},39		{"trailing bytes after the last field", Msg{1, 1, "a", "t", "k", "r", "b"}.Encode() + "x"},40		{"seq is not a number", "1:x1:00:00:00:00:01:b"},41		{"negative length", "-1:a"},42		{"no colon", "5abcde"},43	}44	for _, tt := range tests {45		if _, ok := Decode(tt.s); ok {46			t.Errorf("%s: Decode accepted it", tt.name)47		}48	}49}5051func TestEncodeIsUnambiguous(t *testing.T) {52	// The reason for length prefixes: two different splits of the same bytes53	// must not encode to the same string.54	a := Msg{1, 1, "ab", "c", "k", "r", "b"}.Encode()55	b := Msg{1, 1, "a", "bc", "k", "r", "b"}.Encode()56	if a == b {57		t.Error("two distinct messages share an encoding")58	}59}6061func TestValidate(t *testing.T) {62	long := func(n int) string {63		s := ""64		for i := 0; i < n; i++ {65			s += "x"66		}67		return s68	}69	ok := Msg{From: "a", Topic: "t", Body: "b"}7071	tests := []struct {72		name string73		m    Msg74		want string75	}{76		{"valid", ok, ""},77		{"valid with dots and digits", Msg{From: "a", Topic: "build.v2-0", Body: "b"}, ""},78		{"empty from", Msg{Topic: "t", Body: "b"}, "empty from"},79		{"from too long", Msg{From: long(MaxFrom + 1), Topic: "t", Body: "b"}, "from too long"},80		{"empty topic", Msg{From: "a", Body: "b"}, "empty topic"},81		{"topic too long", Msg{From: "a", Topic: long(MaxTopic + 1), Body: "b"}, "topic too long"},82		{"uppercase topic", Msg{From: "a", Topic: "Build", Body: "b"}, "topic must be lowercase a-z, 0-9, dash or dot"},83		{"topic with a slash", Msg{From: "a", Topic: "a/b", Body: "b"}, "topic must be lowercase a-z, 0-9, dash or dot"},84		{"topic with a space", Msg{From: "a", Topic: "a b", Body: "b"}, "topic must be lowercase a-z, 0-9, dash or dot"},85		{"kind too long", Msg{From: "a", Topic: "t", Kind: long(MaxKind + 1), Body: "b"}, "kind too long"},86		{"ref too long", Msg{From: "a", Topic: "t", Ref: long(MaxRef + 1), Body: "b"}, "ref too long"},87		{"empty body", Msg{From: "a", Topic: "t"}, "empty body"},88		{"body too long", Msg{From: "a", Topic: "t", Body: long(MaxBody + 1)}, "body too long"},89		{"body at the limit", Msg{From: "a", Topic: "t", Body: long(MaxBody)}, ""},90	}91	for _, tt := range tests {92		if got := tt.m.Validate(); got != tt.want {93			t.Errorf("%s: got %q, want %q", tt.name, got, tt.want)94		}95	}96}9798func TestFrameUnframe(t *testing.T) {99	tests := []struct {100		name string101		v    string102		tail string103	}{104		{"plain", "g1abc", ""},105		{"empty value", "", "rest"},106		{"value holds a colon", "a:b", "rest"},107		// The bug this pair exists to prevent: scanning backwards for the108		// length prefix cannot tell a body's trailing digits from it.109		{"preceded by a message ending in digits", "g1abc", ""},110	}111	for _, tt := range tests {112		got, rest, ok := Unframe(Frame(tt.v) + tt.tail)113		if !ok || got != tt.v || rest != tt.tail {114			t.Errorf("%s: got (%q, %q, %v), want (%q, %q, true)", tt.name, got, rest, ok, tt.v, tt.tail)115		}116	}117}118119func TestFrameSurvivesABodyEndingInDigits(t *testing.T) {120	// A relay frames the author and concatenates. Decoding must recover both121	// even when the message body ends in the digits a backwards scan would122	// mistake for the author's length prefix.123	m := Msg{1, 1, "a", "t", "k", "r", "ends in 40"}124	addr := "g1manfred47kzduec920z88wfr64ylksmdcedlf5"125	author, rest, ok := Unframe(Frame(addr) + m.Encode())126	if !ok || author != addr {127		t.Fatalf("author not recovered: got %q, ok=%v", author, ok)128	}129	got, ok := Decode(rest)130	if !ok || got != m {131		t.Errorf("message not recovered after the framed author")132	}133}134

Functions

not supported for pure packages by the node (vm/qfuncs)

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.