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

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}