blob: db7aade3558de0408243be0f746a86a80ce0abea [file] [log] [blame]
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package codec
import (
"bytes"
"flag"
"go/ast"
"go/token"
"io"
"reflect"
"testing"
"github.com/google/go-cmp/cmp"
"golang.org/x/pkgsite/internal/testing/testhelper"
)
var update = flag.Bool("update", false, "update goldens instead of checking against them")
func TestGoName(t *testing.T) {
var r io.Reader
g := &generator{pkg: "codec"}
for _, test := range []struct {
v any
want string
}{
{0, "int"},
{uint(0), "uint"},
{token.Pos(0), "token.Pos"},
{Encoder{}, "Encoder"},
{[][]Encoder{}, "[][]Encoder"},
{bytes.Buffer{}, "bytes.Buffer"},
{&r, "*io.Reader"},
{[]int(nil), "[]int"},
{map[*Decoder][]io.Writer{}, "map[*Decoder][]io.Writer"},
} {
got := g.goName(reflect.TypeOf(test.v))
if got != test.want {
t.Errorf("%T: got %q, want %q", test.v, got, test.want)
}
}
}
func TestGenerate(t *testing.T) {
testGenerate(t, "slice", [][]int(nil))
testGenerate(t, "map", map[string]bool(nil))
testGenerate(t, "struct", ast.BasicLit{})
}
func testGenerate(t *testing.T, name string, x any) {
t.Helper()
var buf bytes.Buffer
if err := generate(&buf, "somepkg", nil, x); err != nil {
t.Fatal(err)
}
got := buf.String()
testhelper.CompareWithGolden(t, got, name+".go", *update)
}
func TestExportedFields(t *testing.T) {
type ef struct {
A int
B bool
I int `codec:"-"` // this field will be ignored
C string
}
check := func(want, got []field) {
t.Helper()
diff := cmp.Diff(want, got,
cmp.Comparer(func(t1, t2 reflect.Type) bool { return t1 == t2 }))
if diff != "" {
t.Errorf("mismatch (-want, +got):\n%s", diff)
}
}
// First time we see ef, no previous fields.
got := exportedFields(reflect.TypeOf(ef{}), nil)
want := []field{
{"A", reflect.TypeOf(0), "0"},
{"B", reflect.TypeOf(false), "false"},
{"C", reflect.TypeOf(""), `""`},
}
check(want, got)
// Imagine that the previous ef had fields C and A in that order, but not B.
// We should preserve the existing ordering and add B at the end.
got = exportedFields(reflect.TypeOf(ef{}), []string{"C", "A"})
want = []field{
{"C", reflect.TypeOf(""), `""`},
{"A", reflect.TypeOf(0), "0"},
{"B", reflect.TypeOf(false), "false"},
}
check(want, got)
// Imagine instead that there had been a field D that was removed.
// We still keep the names, but the entry for "D" has a nil type.
got = exportedFields(reflect.TypeOf(ef{}), []string{"A", "D", "B", "C"})
want = []field{
{"A", reflect.TypeOf(0), "0"},
{"D", nil, ""},
{"B", reflect.TypeOf(false), "false"},
{"C", reflect.TypeOf(""), `""`},
}
check(want, got)
}