test: expand coverage across readers, writers, cmd, ui, diff and merge
Implements tests/_plans and previously deferred packages; updates plan README with new coverage numbers.
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSQLNameLowercases(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
got string
|
||||
}{
|
||||
{"database", (&Database{Name: "MyDB"}).SQLName()},
|
||||
{"domain", (&Domain{Name: "MyDomain"}).SQLName()},
|
||||
{"schema", (&Schema{Name: "MySchema"}).SQLName()},
|
||||
{"table", (&Table{Name: "MyTable"}).SQLName()},
|
||||
{"view", (&View{Name: "MyView"}).SQLName()},
|
||||
{"sequence", (&Sequence{Name: "MySeq"}).SQLName()},
|
||||
{"column", (&Column{Name: "MyCol"}).SQLName()},
|
||||
{"index", (&Index{Name: "MyIdx"}).SQLName()},
|
||||
{"relationship", (&Relationship{Name: "MyRel"}).SQLName()},
|
||||
{"constraint", (&Constraint{Name: "MyCon"}).SQLName()},
|
||||
{"enum", (&Enum{Name: "MyEnum"}).SQLName()},
|
||||
{"script", (&Script{Name: "MyScript"}).SQLName()},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.got == "" || tt.got != lower(tt.got) {
|
||||
t.Errorf("SQLName not lowercase: %q", tt.got)
|
||||
}
|
||||
})
|
||||
}
|
||||
if got := (&Table{}).SQLName(); got != "" {
|
||||
t.Errorf("empty name: %q", got)
|
||||
}
|
||||
if got := (&Table{Name: "MyTable"}).SQLName(); got != "mytable" {
|
||||
t.Errorf("got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func lower(s string) string {
|
||||
b := []byte(s)
|
||||
for i, c := range b {
|
||||
if c >= 'A' && c <= 'Z' {
|
||||
b[i] = c + 32
|
||||
}
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func TestUpdateDatePropagates(t *testing.T) {
|
||||
db := InitDatabase("d")
|
||||
schema := InitSchema("s")
|
||||
schema.RefDatabase = db
|
||||
table := InitTable("t", "s")
|
||||
table.RefSchema = schema
|
||||
|
||||
table.UpdateDate()
|
||||
for name, v := range map[string]string{"table": table.UpdatedAt, "schema": schema.UpdatedAt, "database": db.UpdatedAt} {
|
||||
ts, err := time.Parse(time.RFC3339, v)
|
||||
if err != nil {
|
||||
t.Fatalf("%s UpdatedAt %q: %v", name, v, err)
|
||||
}
|
||||
if time.Since(ts) > time.Minute {
|
||||
t.Errorf("%s UpdatedAt too old: %v", name, ts)
|
||||
}
|
||||
}
|
||||
|
||||
// Without references only the receiver is updated.
|
||||
lone := InitTable("lone", "s")
|
||||
lone.UpdateDate()
|
||||
if lone.UpdatedAt == "" {
|
||||
t.Error("lone table not updated")
|
||||
}
|
||||
loneSchema := InitSchema("x")
|
||||
loneSchema.UpdateDate()
|
||||
if loneSchema.UpdatedAt == "" {
|
||||
t.Error("lone schema not updated")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPrimaryKey(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cols []*Column
|
||||
want string
|
||||
}{
|
||||
{"none", []*Column{{Name: "a"}}, ""},
|
||||
{"single", []*Column{{Name: "a"}, {Name: "id", IsPrimaryKey: true}}, "id"},
|
||||
{"composite ordered by sequence", []*Column{
|
||||
{Name: "a", IsPrimaryKey: true, Sequence: 2},
|
||||
{Name: "b", IsPrimaryKey: true, Sequence: 1},
|
||||
}, "b"},
|
||||
{"composite without sequence falls back to name", []*Column{
|
||||
{Name: "z", IsPrimaryKey: true},
|
||||
{Name: "m", IsPrimaryKey: true},
|
||||
}, "m"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tbl := InitTable("t", "s")
|
||||
for _, c := range tt.cols {
|
||||
tbl.Columns[c.Name] = c
|
||||
}
|
||||
got := tbl.GetPrimaryKey()
|
||||
if tt.want == "" {
|
||||
if got != nil {
|
||||
t.Errorf("expected nil, got %s", got.Name)
|
||||
}
|
||||
return
|
||||
}
|
||||
if got == nil || got.Name != tt.want {
|
||||
t.Errorf("got %v, want %s", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
if InitTable("empty", "s").GetPrimaryKey() != nil {
|
||||
t.Error("empty table must have no PK")
|
||||
}
|
||||
}
|
||||
|
||||
func TestColumnLess(t *testing.T) {
|
||||
tests := []struct {
|
||||
a, b *Column
|
||||
want bool
|
||||
}{
|
||||
{&Column{Name: "a", Sequence: 1}, &Column{Name: "b", Sequence: 2}, true},
|
||||
{&Column{Name: "a", Sequence: 2}, &Column{Name: "b", Sequence: 1}, false},
|
||||
{&Column{Name: "a"}, &Column{Name: "b"}, true},
|
||||
{&Column{Name: "b"}, &Column{Name: "a"}, false},
|
||||
{&Column{Name: "b", Sequence: 1}, &Column{Name: "a"}, false}, // one side unsequenced: by name
|
||||
{&Column{Name: "a", Sequence: 1}, &Column{Name: "b"}, true},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
if got := columnLess(tt.a, tt.b); got != tt.want {
|
||||
t.Errorf("case %d: got %v, want %v", i, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetForeignKeys(t *testing.T) {
|
||||
tbl := InitTable("t", "s")
|
||||
add := func(name string, typ ConstraintType, seq uint) {
|
||||
c := InitConstraint(name, typ)
|
||||
c.Sequence = seq
|
||||
tbl.Constraints[name] = c
|
||||
}
|
||||
add("pk", PrimaryKeyConstraint, 0)
|
||||
add("fk_b", ForeignKeyConstraint, 0)
|
||||
add("fk_a", ForeignKeyConstraint, 0)
|
||||
add("uq", UniqueConstraint, 0)
|
||||
|
||||
got := tbl.GetForeignKeys()
|
||||
if len(got) != 2 || got[0].Name != "fk_a" || got[1].Name != "fk_b" {
|
||||
t.Errorf("by name: %v", got)
|
||||
}
|
||||
|
||||
tbl.Constraints["fk_a"].Sequence = 5
|
||||
tbl.Constraints["fk_b"].Sequence = 2
|
||||
got = tbl.GetForeignKeys()
|
||||
if got[0].Name != "fk_b" || got[1].Name != "fk_a" {
|
||||
t.Errorf("by sequence: %v", got)
|
||||
}
|
||||
|
||||
if got := InitTable("e", "s").GetForeignKeys(); got == nil || len(got) != 0 {
|
||||
t.Errorf("empty table must give non-nil empty slice, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitConstructors(t *testing.T) {
|
||||
db := InitDatabase("db")
|
||||
if db.Name != "db" || db.Schemas == nil || db.Domains == nil || db.Metadata == nil || db.GUID == "" {
|
||||
t.Errorf("InitDatabase: %+v", db)
|
||||
}
|
||||
s := InitSchema("s")
|
||||
if s.Name != "s" || s.Tables == nil || s.Views == nil || s.Sequences == nil || s.Permissions == nil || s.Metadata == nil || s.Scripts == nil || s.GUID == "" {
|
||||
t.Errorf("InitSchema: %+v", s)
|
||||
}
|
||||
tb := InitTable("t", "s")
|
||||
if tb.Name != "t" || tb.Schema != "s" || tb.Columns == nil || tb.Constraints == nil || tb.Indexes == nil || tb.Relationships == nil || tb.Metadata == nil || tb.GUID == "" {
|
||||
t.Errorf("InitTable: %+v", tb)
|
||||
}
|
||||
c := InitColumn("c", "t", "s")
|
||||
if c.Name != "c" || c.Table != "t" || c.Schema != "s" || c.Metadata == nil || c.GUID == "" {
|
||||
t.Errorf("InitColumn: %+v", c)
|
||||
}
|
||||
ix := InitIndex("i", "t", "s")
|
||||
if ix.Name != "i" || ix.Table != "t" || ix.Schema != "s" || ix.Columns == nil || ix.Include == nil || ix.Metadata == nil || ix.GUID == "" {
|
||||
t.Errorf("InitIndex: %+v", ix)
|
||||
}
|
||||
r := InitRelation("r", "s")
|
||||
if r.Name != "r" || r.FromSchema != "s" || r.ToSchema != "s" || r.Properties == nil || r.FromColumns == nil || r.ToColumns == nil || r.GUID == "" {
|
||||
t.Errorf("InitRelation: %+v", r)
|
||||
}
|
||||
rel := InitRelationship("rel", RelationType("one_to_many"))
|
||||
if rel.Name != "rel" || rel.Type != "one_to_many" || rel.Properties == nil || rel.GUID == "" {
|
||||
t.Errorf("InitRelationship: %+v", rel)
|
||||
}
|
||||
con := InitConstraint("k", UniqueConstraint)
|
||||
if con.Name != "k" || con.Type != UniqueConstraint || con.Columns == nil || con.ReferencedColumns == nil || con.GUID == "" {
|
||||
t.Errorf("InitConstraint: %+v", con)
|
||||
}
|
||||
sc := InitScript("sc")
|
||||
if sc.Name != "sc" || sc.RunAfter == nil || sc.Metadata == nil || sc.GUID == "" {
|
||||
t.Errorf("InitScript: %+v", sc)
|
||||
}
|
||||
v := InitView("v", "s")
|
||||
if v.Name != "v" || v.Schema != "s" || v.Columns == nil || v.Metadata == nil || v.GUID == "" {
|
||||
t.Errorf("InitView: %+v", v)
|
||||
}
|
||||
sq := InitSequence("sq", "s")
|
||||
if sq.Name != "sq" || sq.Schema != "s" || sq.IncrementBy != 1 || sq.StartValue != 1 || sq.GUID == "" {
|
||||
t.Errorf("InitSequence: %+v", sq)
|
||||
}
|
||||
d := InitDomain("d")
|
||||
if d.Name != "d" || d.Tables == nil || d.Metadata == nil || d.GUID == "" {
|
||||
t.Errorf("InitDomain: %+v", d)
|
||||
}
|
||||
dt := InitDomainTable("t", "s")
|
||||
if dt.TableName != "t" || dt.SchemaName != "s" || dt.GUID == "" {
|
||||
t.Errorf("InitDomainTable: %+v", dt)
|
||||
}
|
||||
e := InitEnum("e", "s")
|
||||
if e.Name != "e" || e.Schema != "s" || e.Values == nil || e.GUID == "" {
|
||||
t.Errorf("InitEnum: %+v", e)
|
||||
}
|
||||
|
||||
// GUIDs are unique per call.
|
||||
if InitTable("t", "s").GUID == InitTable("t", "s").GUID {
|
||||
t.Error("GUIDs must be unique")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user