94 lines
3.3 KiB
Go
94 lines
3.3 KiB
Go
package web
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
|
|
berrors "github.com/letsencrypt/boulder/errors"
|
|
"github.com/letsencrypt/boulder/identifier"
|
|
"github.com/letsencrypt/boulder/probs"
|
|
"github.com/letsencrypt/boulder/test"
|
|
)
|
|
|
|
func TestProblemDetailsForError(t *testing.T) {
|
|
// errMsg is used as the msg argument for `ProblemDetailsForError` and is
|
|
// always returned in the problem detail.
|
|
const errMsg = "testError"
|
|
// detailMsg is used as the msg argument for the individual error types and is
|
|
// sometimes not present in the produced problem's detail.
|
|
const detailMsg = "testDetail"
|
|
// fullDetail is what we expect the problem detail to look like when it
|
|
// contains both the error message and the detail message
|
|
fullDetail := fmt.Sprintf("%s :: %s", errMsg, detailMsg)
|
|
testCases := []struct {
|
|
err error
|
|
statusCode int
|
|
problem probs.ProblemType
|
|
detail string
|
|
}{
|
|
// boulder/errors error types
|
|
// Internal server errors expect just the `errMsg` in detail.
|
|
{berrors.InternalServerError(detailMsg), 500, probs.ServerInternalProblem, errMsg},
|
|
// Other errors expect the full detail message
|
|
{berrors.MalformedError(detailMsg), 400, probs.MalformedProblem, fullDetail},
|
|
{berrors.UnauthorizedError(detailMsg), 403, probs.UnauthorizedProblem, fullDetail},
|
|
{berrors.NotFoundError(detailMsg), 404, probs.MalformedProblem, fullDetail},
|
|
{berrors.RateLimitError(0, detailMsg), 429, probs.RateLimitedProblem, fullDetail + ": see https://letsencrypt.org/docs/rate-limits/"},
|
|
{berrors.InvalidEmailError(detailMsg), 400, probs.InvalidContactProblem, fullDetail},
|
|
{berrors.RejectedIdentifierError(detailMsg), 400, probs.RejectedIdentifierProblem, fullDetail},
|
|
}
|
|
for _, c := range testCases {
|
|
p := ProblemDetailsForError(c.err, errMsg)
|
|
if p.HTTPStatus != c.statusCode {
|
|
t.Errorf("Incorrect status code for %s. Expected %d, got %d", reflect.TypeOf(c.err).Name(), c.statusCode, p.HTTPStatus)
|
|
}
|
|
if p.Type != c.problem {
|
|
t.Errorf("Expected problem urn %#v, got %#v", c.problem, p.Type)
|
|
}
|
|
if p.Detail != c.detail {
|
|
t.Errorf("Expected detailed message %q, got %q", c.detail, p.Detail)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSubProblems(t *testing.T) {
|
|
topErr := (&berrors.BoulderError{
|
|
Type: berrors.CAA,
|
|
Detail: "CAA policy forbids issuance",
|
|
}).WithSubErrors(
|
|
[]berrors.SubBoulderError{
|
|
{
|
|
Identifier: identifier.NewDNS("threeletter.agency"),
|
|
BoulderError: &berrors.BoulderError{
|
|
Type: berrors.CAA,
|
|
Detail: "Forbidden by ■■■■■■■■■■■ and directive ■■■■",
|
|
},
|
|
},
|
|
{
|
|
Identifier: identifier.NewDNS("area51.threeletter.agency"),
|
|
BoulderError: &berrors.BoulderError{
|
|
Type: berrors.NotFound,
|
|
Detail: "No Such Area...",
|
|
},
|
|
},
|
|
})
|
|
|
|
prob := problemDetailsForBoulderError(topErr, "problem with subproblems")
|
|
test.AssertEquals(t, len(prob.SubProblems), len(topErr.SubErrors))
|
|
|
|
subProbsMap := make(map[string]probs.SubProblemDetails, len(prob.SubProblems))
|
|
|
|
for _, subProb := range prob.SubProblems {
|
|
subProbsMap[subProb.Identifier.Value] = subProb
|
|
}
|
|
|
|
subProbA, foundA := subProbsMap["threeletter.agency"]
|
|
subProbB, foundB := subProbsMap["area51.threeletter.agency"]
|
|
test.AssertEquals(t, foundA, true)
|
|
test.AssertEquals(t, foundB, true)
|
|
|
|
test.AssertEquals(t, subProbA.Type, probs.CAAProblem)
|
|
test.AssertEquals(t, subProbB.Type, probs.MalformedProblem)
|
|
}
|