Rewrite brittle validation and schema tests
This commit is contained in:
@@ -17,44 +17,39 @@ func TestValidateDocumentValid(t *testing.T) {
|
||||
func TestValidateDocumentNil(t *testing.T) {
|
||||
err := ValidateDocument(nil)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("ValidateDocument() error = nil, want error")
|
||||
}
|
||||
if err.Error() != "source document must not be nil" {
|
||||
t.Fatalf("ValidateDocument() error = %q", err.Error())
|
||||
}
|
||||
requireErrorFragments(t, err, "source document", "nil")
|
||||
}
|
||||
|
||||
func TestValidateDocumentMissingFields(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*SourceDocument)
|
||||
wantErr string
|
||||
name string
|
||||
mutate func(*SourceDocument)
|
||||
fragments []string
|
||||
}{
|
||||
{
|
||||
name: "id",
|
||||
mutate: func(doc *SourceDocument) { doc.ID = " \t" },
|
||||
wantErr: "source document id must not be empty",
|
||||
name: "id",
|
||||
mutate: func(doc *SourceDocument) { doc.ID = " \t" },
|
||||
fragments: []string{"source document id", "must not be empty"},
|
||||
},
|
||||
{
|
||||
name: "id surrounding whitespace",
|
||||
mutate: func(doc *SourceDocument) { doc.ID = " source-1 " },
|
||||
wantErr: "source document id \" source-1 \" must not contain leading or trailing whitespace",
|
||||
name: "id surrounding whitespace",
|
||||
mutate: func(doc *SourceDocument) { doc.ID = " source-1 " },
|
||||
fragments: []string{"source document id", "leading or trailing whitespace"},
|
||||
},
|
||||
{
|
||||
name: "kind",
|
||||
mutate: func(doc *SourceDocument) { doc.Kind = "" },
|
||||
wantErr: "source document kind must not be empty",
|
||||
name: "kind",
|
||||
mutate: func(doc *SourceDocument) { doc.Kind = "" },
|
||||
fragments: []string{"source document kind", "must not be empty"},
|
||||
},
|
||||
{
|
||||
name: "format",
|
||||
mutate: func(doc *SourceDocument) { doc.Format = "\n" },
|
||||
wantErr: "source document format must not be empty",
|
||||
name: "format",
|
||||
mutate: func(doc *SourceDocument) { doc.Format = "\n" },
|
||||
fragments: []string{"source document format", "must not be empty"},
|
||||
},
|
||||
{
|
||||
name: "digest",
|
||||
mutate: func(doc *SourceDocument) { doc.Digest = "" },
|
||||
wantErr: "source document digest must not be empty",
|
||||
name: "digest",
|
||||
mutate: func(doc *SourceDocument) { doc.Digest = "" },
|
||||
fragments: []string{"source document digest", "must not be empty"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -65,12 +60,7 @@ func TestValidateDocumentMissingFields(t *testing.T) {
|
||||
|
||||
err := ValidateDocument(doc)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("ValidateDocument() error = nil, want error")
|
||||
}
|
||||
if err.Error() != tt.wantErr {
|
||||
t.Fatalf("ValidateDocument() error = %q, want %q", err.Error(), tt.wantErr)
|
||||
}
|
||||
requireErrorFragments(t, err, tt.fragments...)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -81,34 +71,29 @@ func TestValidateDocumentEmptyUnits(t *testing.T) {
|
||||
|
||||
err := ValidateDocument(doc)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("ValidateDocument() error = nil, want error")
|
||||
}
|
||||
if err.Error() != "source document units must not be empty" {
|
||||
t.Fatalf("ValidateDocument() error = %q", err.Error())
|
||||
}
|
||||
requireErrorFragments(t, err, "source document units", "must not be empty")
|
||||
}
|
||||
|
||||
func TestValidateDocumentMissingUnitFields(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*SourceDocument)
|
||||
wantErr string
|
||||
name string
|
||||
mutate func(*SourceDocument)
|
||||
fragments []string
|
||||
}{
|
||||
{
|
||||
name: "id",
|
||||
mutate: func(doc *SourceDocument) { doc.Units[1].ID = 0 },
|
||||
wantErr: "source unit[1].id must be positive",
|
||||
name: "id",
|
||||
mutate: func(doc *SourceDocument) { doc.Units[1].ID = 0 },
|
||||
fragments: []string{"source unit[1].id", "must be positive"},
|
||||
},
|
||||
{
|
||||
name: "kind",
|
||||
mutate: func(doc *SourceDocument) { doc.Units[1].Kind = " " },
|
||||
wantErr: "source unit[1].kind must not be empty",
|
||||
name: "kind",
|
||||
mutate: func(doc *SourceDocument) { doc.Units[1].Kind = " " },
|
||||
fragments: []string{"source unit[1].kind", "must not be empty"},
|
||||
},
|
||||
{
|
||||
name: "text",
|
||||
mutate: func(doc *SourceDocument) { doc.Units[1].Text = "\n\t" },
|
||||
wantErr: "source unit[1].text must not be empty",
|
||||
name: "text",
|
||||
mutate: func(doc *SourceDocument) { doc.Units[1].Text = "\n\t" },
|
||||
fragments: []string{"source unit[1].text", "must not be empty"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -119,12 +104,7 @@ func TestValidateDocumentMissingUnitFields(t *testing.T) {
|
||||
|
||||
err := ValidateDocument(doc)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("ValidateDocument() error = nil, want error")
|
||||
}
|
||||
if err.Error() != tt.wantErr {
|
||||
t.Fatalf("ValidateDocument() error = %q, want %q", err.Error(), tt.wantErr)
|
||||
}
|
||||
requireErrorFragments(t, err, tt.fragments...)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -135,45 +115,27 @@ func TestValidateDocumentDuplicateUnitIDs(t *testing.T) {
|
||||
|
||||
err := ValidateDocument(doc)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("ValidateDocument() error = nil, want error")
|
||||
}
|
||||
if err.Error() != "source unit id 1 is duplicated" {
|
||||
t.Fatalf("ValidateDocument() error = %q", err.Error())
|
||||
}
|
||||
requireErrorFragments(t, err, "source unit id 1", "duplicated")
|
||||
}
|
||||
|
||||
func TestValidateDocumentUnitReferences(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*SourceDocument)
|
||||
wantErr string
|
||||
name string
|
||||
mutate func(*SourceDocument)
|
||||
fragments []string
|
||||
}{
|
||||
{
|
||||
name: "missing",
|
||||
mutate: func(doc *SourceDocument) { doc.Units[0].Ref = SourceRef{} },
|
||||
wantErr: "source unit[0].ref: source ref source_id must not be empty",
|
||||
name: "nested reference context",
|
||||
mutate: func(doc *SourceDocument) { doc.Units[0].Ref.SourceID = "source-2" },
|
||||
fragments: []string{"source unit[0].ref", "source_id", "does not match"},
|
||||
},
|
||||
{
|
||||
name: "foreign source",
|
||||
mutate: func(doc *SourceDocument) { doc.Units[0].Ref.SourceID = "source-2" },
|
||||
wantErr: "source unit[0].ref: source ref source_id \"source-2\" does not match document id \"source-1\"",
|
||||
},
|
||||
{
|
||||
name: "non-self range",
|
||||
name: "document unit self-reference",
|
||||
mutate: func(doc *SourceDocument) {
|
||||
doc.Units[0].Ref.StartUnitID = 2
|
||||
doc.Units[0].Ref.EndUnitID = 2
|
||||
},
|
||||
wantErr: "source unit[0].ref must identify source unit id 1",
|
||||
},
|
||||
{
|
||||
name: "reversed range",
|
||||
mutate: func(doc *SourceDocument) {
|
||||
doc.Units[0].Ref.StartUnitID = 2
|
||||
doc.Units[0].Ref.EndUnitID = 1
|
||||
},
|
||||
wantErr: "source unit[0].ref: source ref start_unit_id 2 appears after end_unit_id 1",
|
||||
fragments: []string{"source unit[0].ref", "must identify source unit id 1"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -183,12 +145,7 @@ func TestValidateDocumentUnitReferences(t *testing.T) {
|
||||
tt.mutate(doc)
|
||||
|
||||
err := ValidateDocument(doc)
|
||||
if err == nil {
|
||||
t.Fatal("ValidateDocument() error = nil, want unit reference error")
|
||||
}
|
||||
if err.Error() != tt.wantErr {
|
||||
t.Fatalf("ValidateDocument() error = %q, want %q", err.Error(), tt.wantErr)
|
||||
}
|
||||
requireErrorFragments(t, err, tt.fragments...)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -294,59 +251,51 @@ func TestValidateRefValid(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRefSourceIDMismatch(t *testing.T) {
|
||||
doc := validDocument()
|
||||
ref := SourceRef{
|
||||
SourceID: "source-2",
|
||||
StartUnitID: 1,
|
||||
EndUnitID: 2,
|
||||
}
|
||||
|
||||
err := ValidateRef(doc, ref)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("ValidateRef() error = nil, want error")
|
||||
}
|
||||
if err.Error() != "source ref source_id \"source-2\" does not match document id \"source-1\"" {
|
||||
t.Fatalf("ValidateRef() error = %q", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRefMissingUnitIDs(t *testing.T) {
|
||||
func TestValidateRefRejectsMalformedReferences(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ref SourceRef
|
||||
wantErr string
|
||||
name string
|
||||
ref SourceRef
|
||||
fragments []string
|
||||
}{
|
||||
{
|
||||
name: "missing source id",
|
||||
ref: SourceRef{StartUnitID: 1, EndUnitID: 2},
|
||||
wantErr: "source ref source_id must not be empty",
|
||||
name: "missing source id",
|
||||
ref: SourceRef{StartUnitID: 1, EndUnitID: 2},
|
||||
fragments: []string{"source_id", "must not be empty"},
|
||||
},
|
||||
{
|
||||
name: "source id surrounding whitespace",
|
||||
ref: SourceRef{SourceID: " source-1 ", StartUnitID: 1, EndUnitID: 2},
|
||||
wantErr: "source ref source_id \" source-1 \" must not contain leading or trailing whitespace",
|
||||
name: "source id surrounding whitespace",
|
||||
ref: SourceRef{SourceID: " source-1 ", StartUnitID: 1, EndUnitID: 2},
|
||||
fragments: []string{"source_id", "leading or trailing whitespace"},
|
||||
},
|
||||
{
|
||||
name: "missing start id",
|
||||
ref: SourceRef{SourceID: "source-1", EndUnitID: 2},
|
||||
wantErr: "source ref start_unit_id must be positive",
|
||||
name: "missing start id",
|
||||
ref: SourceRef{SourceID: "source-1", EndUnitID: 2},
|
||||
fragments: []string{"start_unit_id", "must be positive"},
|
||||
},
|
||||
{
|
||||
name: "missing end id",
|
||||
ref: SourceRef{SourceID: "source-1", StartUnitID: 1},
|
||||
wantErr: "source ref end_unit_id must be positive",
|
||||
name: "missing end id",
|
||||
ref: SourceRef{SourceID: "source-1", StartUnitID: 1},
|
||||
fragments: []string{"end_unit_id", "must be positive"},
|
||||
},
|
||||
{
|
||||
name: "unknown start id",
|
||||
ref: SourceRef{SourceID: "source-1", StartUnitID: 9, EndUnitID: 2},
|
||||
wantErr: "source ref start_unit_id 9 was not found",
|
||||
name: "unknown start id",
|
||||
ref: SourceRef{SourceID: "source-1", StartUnitID: 9, EndUnitID: 2},
|
||||
fragments: []string{"start_unit_id", "was not found"},
|
||||
},
|
||||
{
|
||||
name: "unknown end id",
|
||||
ref: SourceRef{SourceID: "source-1", StartUnitID: 1, EndUnitID: 9},
|
||||
wantErr: "source ref end_unit_id 9 was not found",
|
||||
name: "unknown end id",
|
||||
ref: SourceRef{SourceID: "source-1", StartUnitID: 1, EndUnitID: 9},
|
||||
fragments: []string{"end_unit_id", "was not found"},
|
||||
},
|
||||
{
|
||||
name: "source id mismatch",
|
||||
ref: SourceRef{SourceID: "source-2", StartUnitID: 1, EndUnitID: 2},
|
||||
fragments: []string{"source_id", "does not match"},
|
||||
},
|
||||
{
|
||||
name: "reversed unit order",
|
||||
ref: SourceRef{SourceID: "source-1", StartUnitID: 2, EndUnitID: 1},
|
||||
fragments: []string{"start_unit_id", "appears after"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -354,34 +303,11 @@ func TestValidateRefMissingUnitIDs(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := ValidateRef(validDocument(), tt.ref)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("ValidateRef() error = nil, want error")
|
||||
}
|
||||
if err.Error() != tt.wantErr {
|
||||
t.Fatalf("ValidateRef() error = %q, want %q", err.Error(), tt.wantErr)
|
||||
}
|
||||
requireErrorFragments(t, err, tt.fragments...)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRefReversedUnitOrder(t *testing.T) {
|
||||
doc := validDocument()
|
||||
ref := SourceRef{
|
||||
SourceID: "source-1",
|
||||
StartUnitID: 2,
|
||||
EndUnitID: 1,
|
||||
}
|
||||
|
||||
err := ValidateRef(doc, ref)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("ValidateRef() error = nil, want error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "appears after") {
|
||||
t.Fatalf("ValidateRef() error = %q, want reversed order error", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnitIndex(t *testing.T) {
|
||||
doc := validDocument()
|
||||
|
||||
@@ -424,3 +350,15 @@ func validDocument() *SourceDocument {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func requireErrorFragments(t *testing.T, err error, fragments ...string) {
|
||||
t.Helper()
|
||||
if err == nil {
|
||||
t.Fatalf("error = nil, want fragments %q", fragments)
|
||||
}
|
||||
for _, fragment := range fragments {
|
||||
if !strings.Contains(err.Error(), fragment) {
|
||||
t.Fatalf("error = %q, want fragment %q", err.Error(), fragment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user