Implements tests/_plans and previously deferred packages; updates plan README with new coverage numbers.
171 lines
5.8 KiB
Go
171 lines
5.8 KiB
Go
package models
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
type sortCase struct {
|
|
name string
|
|
seq uint
|
|
}
|
|
|
|
var sortFixture = []sortCase{{"Banana", 3}, {"apple", 1}, {"Cherry", 2}}
|
|
|
|
var (
|
|
wantNameAsc = []string{"apple", "Banana", "Cherry"}
|
|
wantNameDesc = []string{"Cherry", "Banana", "apple"}
|
|
wantSeqAsc = []string{"apple", "Cherry", "Banana"}
|
|
wantSeqDesc = []string{"Banana", "Cherry", "apple"}
|
|
)
|
|
|
|
func checkNames(t *testing.T, label string, got, want []string) {
|
|
t.Helper()
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Errorf("%s: got %v, want %v", label, got, want)
|
|
}
|
|
}
|
|
|
|
// runSortSuite exercises a by-name and by-sequence sorter pair over the shared fixture.
|
|
func runSortSuite[T any](t *testing.T, build func(sortCase) T, name func(T) string,
|
|
byName func([]T, bool) error, bySeq func([]T, bool) error) {
|
|
t.Helper()
|
|
mk := func() []T {
|
|
out := make([]T, 0, len(sortFixture))
|
|
for _, c := range sortFixture {
|
|
out = append(out, build(c))
|
|
}
|
|
return out
|
|
}
|
|
names := func(items []T) []string {
|
|
out := make([]string, 0, len(items))
|
|
for _, it := range items {
|
|
out = append(out, name(it))
|
|
}
|
|
return out
|
|
}
|
|
if byName != nil {
|
|
items := mk()
|
|
_ = byName(items, false)
|
|
checkNames(t, "name asc", names(items), wantNameAsc)
|
|
_ = byName(items, true)
|
|
checkNames(t, "name desc", names(items), wantNameDesc)
|
|
_ = byName(nil, false)
|
|
_ = byName([]T{}, true)
|
|
}
|
|
if bySeq != nil {
|
|
items := mk()
|
|
_ = bySeq(items, false)
|
|
checkNames(t, "seq asc", names(items), wantSeqAsc)
|
|
_ = bySeq(items, true)
|
|
checkNames(t, "seq desc", names(items), wantSeqDesc)
|
|
_ = bySeq(nil, false)
|
|
}
|
|
}
|
|
|
|
func TestSortSchemas(t *testing.T) {
|
|
runSortSuite(t, func(c sortCase) *Schema { return &Schema{Name: c.name, Sequence: c.seq} },
|
|
func(s *Schema) string { return s.Name }, SortSchemasByName, SortSchemasBySequence)
|
|
}
|
|
|
|
func TestSortTables(t *testing.T) {
|
|
runSortSuite(t, func(c sortCase) *Table { return &Table{Name: c.name, Sequence: c.seq} },
|
|
func(s *Table) string { return s.Name }, SortTablesByName, SortTablesBySequence)
|
|
}
|
|
|
|
func TestSortColumns(t *testing.T) {
|
|
runSortSuite(t, func(c sortCase) *Column { return &Column{Name: c.name, Sequence: c.seq} },
|
|
func(s *Column) string { return s.Name }, SortColumnsByName, SortColumnsBySequence)
|
|
}
|
|
|
|
func TestSortViews(t *testing.T) {
|
|
runSortSuite(t, func(c sortCase) *View { return &View{Name: c.name, Sequence: c.seq} },
|
|
func(s *View) string { return s.Name }, SortViewsByName, SortViewsBySequence)
|
|
}
|
|
|
|
func TestSortSequences(t *testing.T) {
|
|
runSortSuite(t, func(c sortCase) *Sequence { return &Sequence{Name: c.name, Sequence: c.seq} },
|
|
func(s *Sequence) string { return s.Name }, SortSequencesByName, SortSequencesBySequence)
|
|
}
|
|
|
|
func TestSortIndexes(t *testing.T) {
|
|
runSortSuite(t, func(c sortCase) *Index { return &Index{Name: c.name, Sequence: c.seq} },
|
|
func(s *Index) string { return s.Name }, SortIndexesByName, SortIndexesBySequence)
|
|
}
|
|
|
|
func TestSortNameOnly(t *testing.T) {
|
|
runSortSuite(t, func(c sortCase) *Constraint { return &Constraint{Name: c.name} },
|
|
func(s *Constraint) string { return s.Name }, SortConstraintsByName, nil)
|
|
runSortSuite(t, func(c sortCase) *Relationship { return &Relationship{Name: c.name} },
|
|
func(s *Relationship) string { return s.Name }, SortRelationshipsByName, nil)
|
|
runSortSuite(t, func(c sortCase) *Script { return &Script{Name: c.name} },
|
|
func(s *Script) string { return s.Name }, SortScriptsByName, nil)
|
|
runSortSuite(t, func(c sortCase) *Enum { return &Enum{Name: c.name} },
|
|
func(s *Enum) string { return s.Name }, SortEnumsByName, nil)
|
|
}
|
|
|
|
func TestSortStableForTies(t *testing.T) {
|
|
cols := []*Column{{Name: "x", Description: "first"}, {Name: "X", Description: "second"}, {Name: "x", Description: "third"}}
|
|
_ = SortColumnsByName(cols, false)
|
|
if cols[0].Description != "first" || cols[1].Description != "second" || cols[2].Description != "third" {
|
|
t.Errorf("ties must keep input order: %v %v %v", cols[0].Description, cols[1].Description, cols[2].Description)
|
|
}
|
|
_ = SortColumnsBySequence(cols, true)
|
|
if cols[0].Description != "first" || cols[2].Description != "third" {
|
|
t.Errorf("sequence ties must keep input order")
|
|
}
|
|
}
|
|
|
|
func TestSortMapVariants(t *testing.T) {
|
|
cols := map[string]*Column{}
|
|
idx := map[string]*Index{}
|
|
cons := map[string]*Constraint{}
|
|
rels := map[string]*Relationship{}
|
|
for _, c := range sortFixture {
|
|
cols[c.name] = &Column{Name: c.name, Sequence: c.seq}
|
|
idx[c.name] = &Index{Name: c.name, Sequence: c.seq}
|
|
cons[c.name] = &Constraint{Name: c.name}
|
|
rels[c.name] = &Relationship{Name: c.name}
|
|
}
|
|
colNames := func(l []*Column) (o []string) {
|
|
for _, x := range l {
|
|
o = append(o, x.Name)
|
|
}
|
|
return
|
|
}
|
|
idxNames := func(l []*Index) (o []string) {
|
|
for _, x := range l {
|
|
o = append(o, x.Name)
|
|
}
|
|
return
|
|
}
|
|
conNames := func(l []*Constraint) (o []string) {
|
|
for _, x := range l {
|
|
o = append(o, x.Name)
|
|
}
|
|
return
|
|
}
|
|
relNames := func(l []*Relationship) (o []string) {
|
|
for _, x := range l {
|
|
o = append(o, x.Name)
|
|
}
|
|
return
|
|
}
|
|
|
|
checkNames(t, "cols name", colNames(SortColumnsMapByName(cols, false)), wantNameAsc)
|
|
checkNames(t, "cols name desc", colNames(SortColumnsMapByName(cols, true)), wantNameDesc)
|
|
checkNames(t, "cols seq", colNames(SortColumnsMapBySequence(cols, false)), wantSeqAsc)
|
|
checkNames(t, "cols seq desc", colNames(SortColumnsMapBySequence(cols, true)), wantSeqDesc)
|
|
checkNames(t, "idx name", idxNames(SortIndexesMapByName(idx, false)), wantNameAsc)
|
|
checkNames(t, "idx seq", idxNames(SortIndexesMapBySequence(idx, true)), wantSeqDesc)
|
|
checkNames(t, "con name", conNames(SortConstraintsMapByName(cons, false)), wantNameAsc)
|
|
checkNames(t, "rel name", relNames(SortRelationshipsMapByName(rels, true)), wantNameDesc)
|
|
|
|
if got := SortColumnsMapByName(nil, false); got == nil || len(got) != 0 {
|
|
t.Errorf("nil map must give non-nil empty slice")
|
|
}
|
|
if len(cols) != 3 {
|
|
t.Error("input map must not be modified")
|
|
}
|
|
}
|