Print variants

This commit is contained in:
Arpad Ryszka 2020-11-23 00:46:14 +01:00
parent 7c66a3e382
commit f999a77ff9
5 changed files with 236 additions and 11 deletions

View File

@ -9,7 +9,7 @@ import (
func TestDebugNode(t *testing.T) { func TestDebugNode(t *testing.T) {
const expect = `"foobarbaz"` const expect = `"foobarbaz"`
o := "foobarbaz" o := "foobarbaz"
n := reflectValue(none, &pending{values: make(map[valueKey]nodeRef)}, reflect.ValueOf(o)) n := reflectValue(none, &pending{values: make(map[uintptr]nodeRef)}, reflect.ValueOf(o))
s := fmt.Sprint(n) s := fmt.Sprint(n)
if s != expect { if s != expect {
t.Fatalf( t.Fatalf(

View File

@ -26,17 +26,12 @@ type wrapLen struct {
first, max, last int first, max, last int
} }
type valueKey struct {
typ reflect.Type
ptr uintptr
}
type nodeRef struct { type nodeRef struct {
id, refCount int id, refCount int
} }
type pending struct { type pending struct {
values map[valueKey]nodeRef values map[uintptr]nodeRef
idCounter int idCounter int
} }
@ -75,6 +70,8 @@ type writer struct {
err error err error
} }
var stderr io.Writer = os.Stderr
func (n node) String() string { func (n node) String() string {
var b bytes.Buffer var b bytes.Buffer
w := &writer{w: &b} w := &writer{w: &b}
@ -167,7 +164,7 @@ func fprintValues(w io.Writer, o opts, v []interface{}) (int, error) {
n := reflectValue( n := reflectValue(
o, o,
&pending{values: make(map[valueKey]nodeRef)}, &pending{values: make(map[uintptr]nodeRef)},
reflect.ValueOf(vi), reflect.ValueOf(vi),
) )
@ -182,6 +179,20 @@ func fprintValues(w io.Writer, o opts, v []interface{}) (int, error) {
return wr.n, wr.err return wr.n, wr.err
} }
func printValues(o opts, v []interface{}) (int, error) {
return fprintValues(stderr, o, v)
}
func printlnValues(o opts, v []interface{}) (int, error) {
n, err := fprintValues(stderr, o, v)
if err != nil {
return n, err
}
nn, err := stderr.Write([]byte("\n"))
return n + nn, err
}
func sprintValues(o opts, v []interface{}) string { func sprintValues(o opts, v []interface{}) string {
var b bytes.Buffer var b bytes.Buffer
fprintValues(&b, o, v) fprintValues(&b, o, v)
@ -212,6 +223,54 @@ func Fprintwv(w io.Writer, v ...interface{}) (int, error) {
return fprintValues(w, wrap|allTypes, v) return fprintValues(w, wrap|allTypes, v)
} }
func Print(v ...interface{}) (int, error) {
return printValues(none, v)
}
func Printw(v ...interface{}) (int, error) {
return printValues(wrap, v)
}
func Printt(v ...interface{}) (int, error) {
return printValues(types, v)
}
func Printwt(v ...interface{}) (int, error) {
return printValues(wrap|types, v)
}
func Printv(v ...interface{}) (int, error) {
return printValues(allTypes, v)
}
func Printwv(v ...interface{}) (int, error) {
return printValues(wrap|allTypes, v)
}
func Println(v ...interface{}) (int, error) {
return printlnValues(none, v)
}
func Printlnw(v ...interface{}) (int, error) {
return printlnValues(wrap, v)
}
func Printlnt(v ...interface{}) (int, error) {
return printlnValues(types, v)
}
func Printlnwt(v ...interface{}) (int, error) {
return printlnValues(wrap|types, v)
}
func Printlnv(v ...interface{}) (int, error) {
return printlnValues(allTypes, v)
}
func Printlnwv(v ...interface{}) (int, error) {
return printlnValues(wrap|allTypes, v)
}
func Sprint(v ...interface{}) string { func Sprint(v ...interface{}) string {
return sprintValues(none, v) return sprintValues(none, v)
} }

153
notation_test.go Normal file
View File

@ -0,0 +1,153 @@
package notation
import (
"bytes"
"testing"
)
func TestPrint(t *testing.T) {
for _, test := range []struct {
p func(...interface{}) (int, error)
o interface{}
e string
}{{
p: Print,
o: struct{foo int}{42},
e: `{foo: 42}`,
}, {
p: Printw,
o: struct{foo int}{42},
e: `{
foo: 42,
}`,
}, {
p: Printt,
o: struct{foo int}{42},
e: `struct{foo int}{foo: 42}`,
}, {
p: Printwt,
o: struct{foo int}{42},
e: `struct{
foo int
}{
foo: 42,
}`,
}, {
p: Printv,
o: struct{foo int}{42},
e: `struct{foo int}{foo: int(42)}`,
}, {
p: Printwv,
o: struct{foo int}{42},
e: `struct{
foo int
}{
foo: int(42),
}`,
}} {
defer withEnv(t, "TABWIDTH=0", "LINEWIDTH=0", "LINEWIDTH1=0")()
t.Run("", func(t *testing.T) {
var b bytes.Buffer
orig := stderr
stderr = &b
defer func() { stderr = orig }()
n, err := test.p(test.o)
if err != nil {
t.Fatal(err)
}
if n != len(test.e) {
t.Fatalf("expected length: %d, got: %d", len(test.e), n)
}
s := b.String()
if s != test.e {
t.Fatalf("expected: %s, got: %s", test.e, s)
}
})
}
}
func TestPrintln(t *testing.T) {
for _, test := range []struct {
p func(...interface{}) (int, error)
f bool
o interface{}
e string
}{{
p: Println,
o: struct{foo int}{42},
e: "{foo: 42}\n",
}, {
p: Printlnw,
o: struct{foo int}{42},
e: `{
foo: 42,
}
`,
}, {
p: Printlnt,
o: struct{foo int}{42},
e: "struct{foo int}{foo: 42}\n",
}, {
p: Printlnwt,
o: struct{foo int}{42},
e: `struct{
foo int
}{
foo: 42,
}
`,
}, {
p: Printlnv,
o: struct{foo int}{42},
e: "struct{foo int}{foo: int(42)}\n",
}, {
p: Printlnwv,
o: struct{foo int}{42},
e: `struct{
foo int
}{
foo: int(42),
}
`,
}, {
p: Println,
o: struct{foo int}{42},
f: true,
}} {
defer withEnv(t, "TABWIDTH=0", "LINEWIDTH=0", "LINEWIDTH1=0")()
t.Run("", func(t *testing.T) {
var b bytes.Buffer
orig := stderr
stderr = &b
if test.f {
var w failingWriter
stderr = &w
}
defer func() { stderr = orig }()
n, err := test.p(test.o)
if test.f && err == nil {
t.Fatal("failed to fail")
}
if test.f {
return
}
if err != nil {
t.Fatal(err)
}
if n != len(test.e) {
t.Fatalf("expected length: %d, got: %d", len(test.e), n)
}
s := b.String()
if s != test.e {
t.Fatalf("expected: %s, got: %s", test.e, s)
}
})
}
}

View File

@ -118,7 +118,7 @@ func reflectInterface(o opts, p *pending, r reflect.Value) node {
return reflectNil(o, false, r) return reflectNil(o, false, r)
} }
e := reflectValue(o, p, r.Elem()) e := reflectValue(o&^skipTypes, p, r.Elem())
if _, t, _ := withType(o); !t { if _, t, _ := withType(o); !t {
return e return e
} }
@ -169,7 +169,11 @@ func reflectMap(o opts, p *pending, r reflect.Value) node {
nodeOf( nodeOf(
sn[skey], sn[skey],
": ", ": ",
reflectValue(itemOpts, p, r.MapIndex(sv[skey])), reflectValue(
itemOpts,
p,
r.MapIndex(sv[skey]),
),
), ),
) )
} }
@ -301,7 +305,7 @@ func checkPending(p *pending, r reflect.Value) (applyRef func(node) node, ref no
} }
var nr nodeRef var nr nodeRef
key := valueKey{typ: r.Type(), ptr: r.Pointer()} key := r.Pointer()
nr, isPending = p.values[key] nr, isPending = p.values[key]
if isPending { if isPending {
nr.refCount++ nr.refCount++

View File

@ -1076,3 +1076,12 @@ func TestCyclicReferences(t *testing.T) {
} }
}) })
} }
func TestInterfaceType(t *testing.T) {
const expect = `struct{foo interface{}}{foo: *struct{bar int}{bar: 42}}`
o := struct{ foo interface{} }{foo: &struct{ bar int }{42}}
s := Sprintt(o)
if s != expect {
t.Fatalf("expected: %s, got: %s", expect, s)
}
}