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.

methods_test.gno

3.66 Kb · 119 lines
  1package ufmt
  2
  3import (
  4	"errors"
  5	"strings"
  6	"testing"
  7)
  8
  9type str struct{ s string }
 10
 11func (v str) String() string { return v.s }
 12
 13type errT struct{}
 14
 15func (errT) Error() string  { return "boom" }
 16func (errT) String() string { return "stringer" }
 17
 18type goStr struct{}
 19
 20func (goStr) GoString() string { return "goStr{}" }
 21func (goStr) String() string   { return "plain" }
 22
 23type formatter struct{}
 24
 25func (formatter) Format(f State, verb rune) {
 26	w, wok := f.Width()
 27	p, pok := f.Precision()
 28	Fprintf(f, "F[%c w=%d/%t p=%d/%t minus=%t plus=%t sharp=%t]",
 29		verb, w, wok, p, pok, f.Flag('-'), f.Flag('+'), f.Flag('#'))
 30}
 31
 32type panicky struct{}
 33
 34func (panicky) String() string { panic("nope") }
 35
 36type opaque struct{ n int }
 37
 38// Every want below is what Go's fmt prints for the same call (go1.27.1),
 39// except where a comment says gno cannot see what Go sees.
 40func TestMethods(t *testing.T) {
 41	cases := []struct{ got, want string }{
 42		{Sprintf("%v|%s|%q|%x|%10s|%-6v|", str{"hi"}, str{"hi"}, str{"hi"}, str{"hi"}, str{"hi"}, str{"hi"}),
 43			`hi|hi|"hi"|6869|        hi|hi    |`},
 44		{Sprintf("%v %s", errT{}, errT{}), "boom boom"}, // Error wins over String
 45		{Sprintf("%#v %v", goStr{}, goStr{}), "goStr{} plain"},
 46		{Sprintf("%v|%-8.3s|%+#x", formatter{}, formatter{}, formatter{}),
 47			"F[v w=0/false p=0/false minus=false plus=false sharp=false]|" +
 48				"F[s w=8/true p=3/true minus=true plus=false sharp=false]|" +
 49				"F[x w=0/false p=0/false minus=false plus=true sharp=true]"},
 50		{Sprintf("%v", panicky{}), "%!v(PANIC=String method: nope)"},
 51		{Sprintf("%v", []any{str{"a"}, errT{}}), "[a boom]"},
 52		{Sprintf("%s", []error{errors.New("base"), errT{}}), "[base boom]"},
 53		{Sprint("a", 1, 2, "b", "c", 3.5, true, nil), "a1 2bc3.5 true <nil>"},
 54		{Sprint(str{"x"}, str{"y"}), "x y"},
 55		{Sprintln("a", 1, 2, "b"), "a 1 2 b\n"},
 56
 57		// Go reflects into the struct and prints "{%!d(string=hi)}" and
 58		// "{7}"; gno has no reflect, so v2 says so instead of guessing.
 59		{Sprintf("%d", str{"hi"}), "%!d(unhandled)"},
 60		{Sprintf("%v", opaque{7}), "(unhandled)"},
 61		{Sprintf("%T", opaque{7}), "unknown"},
 62		// Go prints "%!w(*errors.errorString=&{base})": the type is not
 63		// nameable here either.
 64		{Sprintf("%w", errors.New("base")), "%!w(unhandled)"},
 65	}
 66	for i, c := range cases {
 67		if c.got != c.want {
 68			t.Errorf("case %d: got %q, want %q", i, c.got, c.want)
 69		}
 70	}
 71}
 72
 73func TestErrorf(t *testing.T) {
 74	base := errors.New("base")
 75
 76	e := Errorf("wrap: %w", base)
 77	if e.Error() != "wrap: base" || !errors.Is(e, base) || errors.Unwrap(e) != base {
 78		t.Errorf("single %%w: %q, Is=%t", e.Error(), errors.Is(e, base))
 79	}
 80
 81	e2 := Errorf("two: %w and %w", base, errT{})
 82	if e2.Error() != "two: base and boom" || !errors.Is(e2, base) || errors.Unwrap(e2) != nil {
 83		t.Errorf("two %%w: %q, Is=%t", e2.Error(), errors.Is(e2, base))
 84	}
 85
 86	if got := Errorf("%w", "notanerror").Error(); got != "%!w(string=notanerror)" {
 87		t.Errorf("non-error %%w: %q", got)
 88	}
 89
 90	plain := Errorf("plain %d", 1)
 91	if plain.Error() != "plain 1" || errors.Unwrap(plain) != nil {
 92		t.Errorf("plain: %q", plain.Error())
 93	}
 94}
 95
 96func TestWriters(t *testing.T) {
 97	var sb strings.Builder
 98	n, err := Fprintf(&sb, "%04d|", 7)
 99	Fprint(&sb, "a", 1)
100	Fprintln(&sb, "!", 2)
101	if sb.String() != "0007|a1! 2\n" || n != 5 || err != nil {
102		t.Errorf("Fprint*: %q n=%d err=%v", sb.String(), n, err)
103	}
104
105	b := Appendf([]byte("x="), "%x", 255)
106	b = Append(b, " ", true)
107	b = Appendln(b, "", 1)
108	if string(b) != "x=ff true 1\n" {
109		t.Errorf("Append*: %q", string(b))
110	}
111}
112
113// The register dump that v0 could not print: "0x(unhandled verb: %X)".
114func TestRegisterDump(t *testing.T) {
115	got := Sprintf("0x%08X %08x", uint32(0x1004), uint32(0xa00513))
116	if got != "0x00001004 00a00513" {
117		t.Errorf("got %q", got)
118	}
119}