-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy patherrors_test.go
More file actions
140 lines (130 loc) · 4.95 KB
/
errors_test.go
File metadata and controls
140 lines (130 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package proteus
import (
"errors"
"testing"
)
func TestValidationErrorIdentity(t *testing.T) {
err := ValidationError{Kind: NotPointer}
// exact kind match
if !errors.Is(err, ValidationError{Kind: NotPointer}) {
t.Error("ValidationError{NotPointer} should match itself")
}
// wildcard match
if !errors.Is(err, ValidationError{}) {
t.Error("ValidationError{NotPointer} should match any-ValidationError wildcard")
}
// different kind should not match
if errors.Is(err, ValidationError{Kind: NotPointerToStruct}) {
t.Error("ValidationError{NotPointer} should not match ValidationError{NotPointerToStruct}")
}
}
func TestValidationErrorMessage(t *testing.T) {
cases := []struct {
kind ValidationErrorKind
want string
}{
{NotPointer, "not a pointer"},
{NotPointerToStruct, "not a pointer to struct"},
{NeedExecutorOrQuerier, "need to supply an Executor or Querier parameter"},
{InvalidFirstParam, "first parameter must be of type context.Context, Executor, or Querier"},
{RowsMustBeNonNil, "rows must be non-nil"},
}
for _, c := range cases {
e := ValidationError{Kind: c.kind}
if e.Error() != c.want {
t.Errorf("Kind %d: expected %q, got %q", c.kind, c.want, e.Error())
}
}
}
func TestQueryErrorKinds(t *testing.T) {
err := QueryError{Kind: QueryNotFound, Name: "foo"}
if !errors.Is(err, QueryError{Kind: QueryNotFound}) {
t.Error("QueryError{QueryNotFound} should match exact kind")
}
if !errors.Is(err, QueryError{}) {
t.Error("QueryError should match any-QueryError wildcard")
}
if errors.Is(err, QueryError{Kind: ParameterNotFound}) {
t.Error("QueryError{QueryNotFound} should not match QueryError{ParameterNotFound}")
}
if err.Error() != "no query found for name foo" {
t.Errorf("unexpected message: %s", err.Error())
}
}
func TestQueryErrorMessages(t *testing.T) {
cases := []struct {
err QueryError
want string
}{
{QueryError{Kind: MissingClosingColon, Query: "select *"}, "missing a closing : somewhere: select *"},
{QueryError{Kind: EmptyVariable, Position: 10}, "empty variable declaration at position 10"},
{QueryError{Kind: ParameterNotFound, Name: "p"}, "query parameter p cannot be found in the incoming parameters"},
{QueryError{Kind: NilParameterPath, Name: "p"}, "query parameter p has a path, but the incoming parameter is nil"},
{QueryError{Kind: InvalidParameterType, Name: "p", TypeKind: "int"}, "query parameter p has a path, but the incoming parameter is not a map or a struct it is int"},
}
for _, c := range cases {
if c.err.Error() != c.want {
t.Errorf("expected %q, got %q", c.want, c.err.Error())
}
}
}
func TestIdentifierErrorKinds(t *testing.T) {
err := IdentifierError{Kind: InvalidCharacterInIdentifier, Identifier: "a,b"}
if !errors.Is(err, IdentifierError{Kind: InvalidCharacterInIdentifier}) {
t.Error("IdentifierError should match exact kind")
}
if !errors.Is(err, IdentifierError{}) {
t.Error("IdentifierError should match any-IdentifierError wildcard")
}
if errors.Is(err, IdentifierError{Kind: SemicolonInIdentifier}) {
t.Error("IdentifierError{InvalidCharacter} should not match IdentifierError{Semicolon}")
}
}
func TestIdentifierErrorMessages(t *testing.T) {
cases := []struct {
err IdentifierError
want string
}{
{IdentifierError{Kind: SemicolonInIdentifier, Identifier: "a;b"}, "; is not allowed in an identifier: a;b"},
{IdentifierError{Kind: EmptyOrTrailingDotIdentifier, Identifier: "a."}, "identifiers cannot be empty or end with a .: a."},
{IdentifierError{Kind: MissingDotInIdentifier, Identifier: "ab"}, ". missing between parts of an identifier: ab"},
{IdentifierError{Kind: LeadingOrDoubleDotIdentifier, Identifier: ".a"}, "identifier cannot start with . or have two . in a row: .a"},
{IdentifierError{Kind: InvalidCharacterInIdentifier, Identifier: "a,b"}, "invalid character found in identifier: a,b"},
}
for _, c := range cases {
if c.err.Error() != c.want {
t.Errorf("expected %q, got %q", c.want, c.err.Error())
}
}
}
func TestValidationErrorPropagation(t *testing.T) {
wrapped := Error{
FuncName: "TestFunc",
FieldOrder: 0,
OriginalError: ValidationError{Kind: NotPointer},
}
if !errors.Is(wrapped, ValidationError{Kind: NotPointer}) {
t.Error("ValidationError should be reachable through Error.Unwrap()")
}
if !errors.Is(wrapped, ValidationError{}) {
t.Error("any-ValidationError wildcard should be reachable through Error.Unwrap()")
}
}
func TestErrorsAsExtraction(t *testing.T) {
err := QueryError{Kind: QueryNotFound, Name: "myquery"}
if qe, ok := errors.AsType[QueryError](err); ok {
if qe.Name != "myquery" {
t.Errorf("expected Name=myquery, got %s", qe.Name)
}
} else {
t.Fatal("errors.AsType should succeed for QueryError")
}
err2 := IdentifierError{Kind: SemicolonInIdentifier, Identifier: "a;b"}
if ie, ok := errors.AsType[IdentifierError](err2); ok {
if ie.Identifier != "a;b" {
t.Errorf("expected Identifier=a;b, got %s", ie.Identifier)
}
} else {
t.Fatal("errors.As should succeed for IdentifierError")
}
}