1
2
3
4
5 package acme
6
7 import (
8 "errors"
9 "net/http"
10 "reflect"
11 "testing"
12 "time"
13 )
14
15 func TestExternalAccountBindingString(t *testing.T) {
16 eab := ExternalAccountBinding{
17 KID: "kid",
18 Key: []byte("key"),
19 }
20 got := eab.String()
21 want := `&{KID: "kid", Key: redacted}`
22 if got != want {
23 t.Errorf("eab.String() = %q, want: %q", got, want)
24 }
25 }
26
27 func TestRateLimit(t *testing.T) {
28 now := time.Date(2017, 04, 27, 10, 0, 0, 0, time.UTC)
29 f := timeNow
30 defer func() { timeNow = f }()
31 timeNow = func() time.Time { return now }
32
33 h120, hTime := http.Header{}, http.Header{}
34 h120.Set("Retry-After", "120")
35 hTime.Set("Retry-After", "Tue Apr 27 11:00:00 2017")
36
37 err1 := &Error{
38 ProblemType: "urn:ietf:params:acme:error:nolimit",
39 Header: h120,
40 }
41 err2 := &Error{
42 ProblemType: "urn:ietf:params:acme:error:rateLimited",
43 Header: h120,
44 }
45 err3 := &Error{
46 ProblemType: "urn:ietf:params:acme:error:rateLimited",
47 Header: nil,
48 }
49 err4 := &Error{
50 ProblemType: "urn:ietf:params:acme:error:rateLimited",
51 Header: hTime,
52 }
53
54 tt := []struct {
55 err error
56 res time.Duration
57 ok bool
58 }{
59 {nil, 0, false},
60 {errors.New("dummy"), 0, false},
61 {err1, 0, false},
62 {err2, 2 * time.Minute, true},
63 {err3, 0, true},
64 {err4, time.Hour, true},
65 }
66 for i, test := range tt {
67 res, ok := RateLimit(test.err)
68 if ok != test.ok {
69 t.Errorf("%d: RateLimit(%+v): ok = %v; want %v", i, test.err, ok, test.ok)
70 continue
71 }
72 if res != test.res {
73 t.Errorf("%d: RateLimit(%+v) = %v; want %v", i, test.err, res, test.res)
74 }
75 }
76 }
77
78 func TestAuthorizationError(t *testing.T) {
79 tests := []struct {
80 desc string
81 err *AuthorizationError
82 msg string
83 }{
84 {
85 desc: "when auth error identifier is set",
86 err: &AuthorizationError{
87 Identifier: "domain.com",
88 Errors: []error{
89 (&wireError{
90 Status: 403,
91 Type: "urn:ietf:params:acme:error:caa",
92 Detail: "CAA record for domain.com prevents issuance",
93 }).error(nil),
94 },
95 },
96 msg: "acme: authorization error for domain.com: 403 urn:ietf:params:acme:error:caa: CAA record for domain.com prevents issuance",
97 },
98
99 {
100 desc: "when auth error identifier is unset",
101 err: &AuthorizationError{
102 Errors: []error{
103 (&wireError{
104 Status: 403,
105 Type: "urn:ietf:params:acme:error:caa",
106 Detail: "CAA record for domain.com prevents issuance",
107 }).error(nil),
108 },
109 },
110 msg: "acme: authorization error: 403 urn:ietf:params:acme:error:caa: CAA record for domain.com prevents issuance",
111 },
112 }
113
114 for _, tt := range tests {
115 if tt.err.Error() != tt.msg {
116 t.Errorf("got: %s\nwant: %s", tt.err, tt.msg)
117 }
118 }
119 }
120
121 func TestSubproblems(t *testing.T) {
122 tests := []struct {
123 wire wireError
124 expectedOut Error
125 }{
126 {
127 wire: wireError{
128 Status: 1,
129 Type: "urn:error",
130 Detail: "it's an error",
131 },
132 expectedOut: Error{
133 StatusCode: 1,
134 ProblemType: "urn:error",
135 Detail: "it's an error",
136 },
137 },
138 {
139 wire: wireError{
140 Status: 1,
141 Type: "urn:error",
142 Detail: "it's an error",
143 Subproblems: []Subproblem{
144 {
145 Type: "urn:error:sub",
146 Detail: "it's a subproblem",
147 },
148 },
149 },
150 expectedOut: Error{
151 StatusCode: 1,
152 ProblemType: "urn:error",
153 Detail: "it's an error",
154 Subproblems: []Subproblem{
155 {
156 Type: "urn:error:sub",
157 Detail: "it's a subproblem",
158 },
159 },
160 },
161 },
162 {
163 wire: wireError{
164 Status: 1,
165 Type: "urn:error",
166 Detail: "it's an error",
167 Subproblems: []Subproblem{
168 {
169 Type: "urn:error:sub",
170 Detail: "it's a subproblem",
171 Identifier: &AuthzID{Type: "dns", Value: "example"},
172 },
173 },
174 },
175 expectedOut: Error{
176 StatusCode: 1,
177 ProblemType: "urn:error",
178 Detail: "it's an error",
179 Subproblems: []Subproblem{
180 {
181 Type: "urn:error:sub",
182 Detail: "it's a subproblem",
183 Identifier: &AuthzID{Type: "dns", Value: "example"},
184 },
185 },
186 },
187 },
188 }
189
190 for _, tc := range tests {
191 out := tc.wire.error(nil)
192 if !reflect.DeepEqual(*out, tc.expectedOut) {
193 t.Errorf("Unexpected error: wanted %v, got %v", tc.expectedOut, *out)
194 }
195 }
196 }
197
198 func TestErrorStringerWithSubproblems(t *testing.T) {
199 err := Error{
200 StatusCode: 1,
201 ProblemType: "urn:error",
202 Detail: "it's an error",
203 Subproblems: []Subproblem{
204 {
205 Type: "urn:error:sub",
206 Detail: "it's a subproblem",
207 },
208 {
209 Type: "urn:error:sub",
210 Detail: "it's a subproblem",
211 Identifier: &AuthzID{Type: "dns", Value: "example"},
212 },
213 },
214 }
215 expectedStr := "1 urn:error: it's an error; subproblems:\n\turn:error:sub: it's a subproblem\n\turn:error:sub: [dns: example] it's a subproblem"
216 if err.Error() != expectedStr {
217 t.Errorf("Unexpected error string: wanted %q, got %q", expectedStr, err.Error())
218 }
219 }
220
View as plain text