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/r/moul/x/allinone/textlab/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
moul / x / allinone / textlab
Files
4 (README)(gnomod.toml)
Exported functions
1
Module
gno.land/r/moul/x/allinone/textlab/v0
gno
0.9

Files (4)

  • README.mdmarkdown
  • gnomod.tomltoml
  • textlab.gnogno
  • textlab_test.gnogno
textlab_test.gnogno
1package textlab23import (4	"testing"56	"gno.land/p/moul/x/daily/levenshtein/v0"7	"gno.land/p/moul/x/daily/soundex/v0"8	"gno.land/p/nt/uassert/v0"9)1011// TestRomanOf covers the one package here whose input is a number rather than12// a word, in both directions plus the two ways it can be neither.13func TestRomanOf(t *testing.T) {14	tests := []struct{ in, want string }{15		{"1987", "MCMLXXXVII"},16		{"1", "I"},17		{"3999", "MMMCMXCIX"},18		{"0", "out of range (1..3999)"},19		{"-5", "out of range (1..3999)"},20		{"4000", "out of range (1..3999)"},21		{"MCMLXXXVII", "1987 (read as roman)"},22		{"mcmlxxxvii", "1987 (read as roman)"},23		{"knight", "not a number"},24	}25	for _, tt := range tests {26		uassert.Equal(t, tt.want, romanOf(tt.in), "romanOf("+tt.in+")")27	}28}2930// TestTheDisagreement is the claim the realm is built to show, pinned in both31// directions. Measured 2026-09-23; the numbers in the package doc and on the32// page come from here, so if either package changes its mind this fails rather33// than the page quietly stating something false.34func TestTheDisagreement(t *testing.T) {35	// One edit apart, and yet soundex says unrelated: it keys on the first36	// letter, and the silent K changes it.37	uassert.Equal(t, "K523", soundex.Encode("knight"))38	uassert.Equal(t, "N230", soundex.Encode("night"))39	uassert.False(t, soundex.Match("knight", "night"), "different soundex codes")40	uassert.Equal(t, 1, levenshtein.Distance("knight", "night"))41	uassert.Equal(t, 83, levenshtein.Similarity("knight", "night"))4243	// And the other way: two edits apart, identical codes.44	uassert.Equal(t, "R163", soundex.Encode("robert"))45	uassert.Equal(t, "R163", soundex.Encode("rupert"))46	uassert.True(t, soundex.Match("robert", "rupert"), "same soundex code")47	uassert.Equal(t, 2, levenshtein.Distance("robert", "rupert"))48}4950// TestRomanOfDoesNotAbortOnOrdinaryWords is the defect this realm shipped with51// until a test found it: romannum.FromRoman PANICS on a non-numeral instead of52// returning zero, so the DEFAULT view aborted. "knight" is not a roman numeral,53// and neither is most of what anyone would put in the URL.54func TestRomanOfDoesNotAbortOnOrdinaryWords(t *testing.T) {55	for _, w := range []string{"knight", "night", "a|b", "", "hello world", "MMM!"} {56		uassert.Equal(t, "not a number", romanOf(w), "romanOf("+w+")")57	}58	uassert.True(t, isRomanNumeral("MCMLXXXVII"))59	uassert.False(t, isRomanNumeral("KNIGHT"))60	uassert.False(t, isRomanNumeral(""))61}6263// TestInputIsBounded pins the ceiling. levenshtein.Matrix is O(len(a)*len(b)),64// so an unbounded pair out of a URL is a way to make a query expensive for65// whoever serves it.66func TestInputIsBounded(t *testing.T) {67	long := ""68	for i := 0; i < maxInput+1; i++ {69		long += "x"70	}71	uassert.True(t, tooLong(long))72	uassert.False(t, tooLong("knight"))7374	out := Render(long)75	uassert.True(t, len(out) < 600, "an over-long input renders a refusal, not a matrix")76}7778// TestTableCellsAreEscaped: the input comes out of a URL and lands in a table79// cell, where an unescaped pipe eats a column.80func TestTableCellsAreEscaped(t *testing.T) {81	out := Render("a|b")82	uassert.False(t, contains(out, "| a|b |"), "a raw pipe reached a table cell")83}8485func contains(h, n string) bool {86	for i := 0; i+len(n) <= len(h); i++ {87		if h[i:i+len(n)] == n {88			return true89		}90	}91	return false92}9394// ExampleRender pins the root view, which is the default word and the "try95// two" list. Nothing here moves with the chain.96func ExampleRender() {97	print(Render(""))98	// Output:99	// # allinone: textlab100	//101	// Eight packages over one input. [source](https://mygnoscan.moul.p2p.team/realm/r/moul/x/allinone/textlab/v0)102	//103	// ## Input: knight104	//105	// | package | answer |106	// | --- | --- |107	// | `x/daily/soundex` | K523 |108	// | `x/daily/rot13` | xavtug |109	// | `x/daily/piglatin` | ightknay |110	// | `x/daily/romannum` | not a number |111	//112	// ## Try two113	//114	// - [knight vs night](/r/moul/x/allinone/textlab/v0:knight/night) (one edit apart, yet soundex says unrelated)115	// - [robert vs rupert](/r/moul/x/allinone/textlab/v0:robert/rupert) (two edits apart, yet soundex says identical)116	// - [1987 as a roman numeral](/r/moul/x/allinone/textlab/v0:1987)117}118119// ExampleRender_pair pins the comparison view, which is the realm's whole120// argument: the same pair, judged opposite ways by the two measures.121func ExampleRender_pair() {122	print(Render("knight/night"))123	// Output:124	// # allinone: textlab125	//126	// Eight packages over one input. [source](https://mygnoscan.moul.p2p.team/realm/r/moul/x/allinone/textlab/v0)127	//128	// ## Input: knight129	//130	// | package | answer |131	// | --- | --- |132	// | `x/daily/soundex` | K523 |133	// | `x/daily/rot13` | xavtug |134	// | `x/daily/piglatin` | ightknay |135	// | `x/daily/romannum` | not a number |136	//137	// ## Compared with night138	//139	// | measure | answer |140	// | --- | --- |141	// | `soundex` of knight | K523 |142	// | `soundex` of night | N230 |143	// | sound alike | no |144	// | `levenshtein` distance | 1 |145	// | `levenshtein` similarity | 83% |146}147

Functions

  • Render(path string) string

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

Rendered

RenderedRawgnoweb ↗

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.