101 lines
3.4 KiB
Go
101 lines
3.4 KiB
Go
package apierrors_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"sync"
|
|
"testing"
|
|
|
|
apierrors "git.yuntuo.hk/k2safe/go-omni/errors"
|
|
)
|
|
|
|
func TestCatalogIsolationDefaultsAndCauses(t *testing.T) {
|
|
catalog := apierrors.Catalog{DefaultStatus: 200, Definitions: map[string]apierrors.Definition{
|
|
"FIRST": {Code: 400002, Message: "first"}, "SECOND": {Code: 400002, Message: "second"}, "DENIED": {Status: 403, Code: "denied", Message: "denied"},
|
|
}}
|
|
r, err := apierrors.NewRegistry(catalog)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
catalog.Definitions["FIRST"] = apierrors.Definition{Message: "changed"}
|
|
r.Catalog().Definitions["FIRST"] = apierrors.Definition{Message: "also changed"}
|
|
cause := errors.New("private secret")
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 40; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
ref := apierrors.ByCode("FIRST").WithCause(cause)
|
|
e := r.Resolve(fmt.Errorf("wrapped: %w", ref))
|
|
if e.Status != 200 || e.BusinessCode != int64(400002) || e.Message != "first" || !errors.Is(e, cause) {
|
|
t.Error(e)
|
|
}
|
|
e.WithCause(errors.New("different"))
|
|
if ref.Cause != cause || r.Resolve(apierrors.ByCode("FIRST")).Cause != nil {
|
|
t.Error("shared state")
|
|
}
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
if got := r.Resolve(apierrors.ByCode("SECOND")); got.Message != "second" || got.BusinessCode != int64(400002) {
|
|
t.Fatal(got)
|
|
}
|
|
if got := r.Resolve(apierrors.ByCode("DENIED")); got.Status != 403 || got.BusinessCode != "denied" {
|
|
t.Fatal(got)
|
|
}
|
|
other := apierrors.MustRegistry(apierrors.Catalog{Definitions: map[string]apierrors.Definition{"FIRST": {Status: 409, Code: 9, Message: "other"}}})
|
|
if got := other.Resolve(apierrors.ByCode("FIRST")); got.Status != 409 || got.Message != "other" {
|
|
t.Fatal(got)
|
|
}
|
|
if got := r.Resolve(apierrors.ByCode("MISSING").WithCause(cause)); got.Status != 500 || got.Code != "INTERNAL_ERROR" || got.Message == cause.Error() || !errors.Is(got, cause) {
|
|
t.Fatal(got)
|
|
}
|
|
if got := apierrors.From(apierrors.ByCode("MISSING")); got.Status != 500 {
|
|
t.Fatal(got)
|
|
}
|
|
legacy := apierrors.New(422, "OLD", "legacy")
|
|
if got := r.Resolve(legacy); got == legacy || got.Status != 422 || got.Message != "legacy" {
|
|
t.Fatal(got)
|
|
}
|
|
}
|
|
|
|
func TestCatalogStrictJSONAndValues(t *testing.T) {
|
|
raw := `{"defaultStatus":200,"definitions":{"LARGE":{"code":9223372036854775807,"message":"large"}}}`
|
|
var c apierrors.Catalog
|
|
if err := json.Unmarshal([]byte(raw), &c); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
e := apierrors.MustRegistry(c).Resolve(apierrors.ByCode("LARGE"))
|
|
if e.BusinessCode != int64(math.MaxInt64) {
|
|
t.Fatal(e.BusinessCode)
|
|
}
|
|
for _, raw := range []string{
|
|
`{"definitions":{"A":{"code":1,"message":"a"},"A":{"code":2,"message":"b"}}}`,
|
|
`{"definitions":{"A":{"code":1,"code":2,"message":"a"}}}`,
|
|
`{"definitions":{"A":{"code":1,"message":"a","typo":true}}}`,
|
|
`{"defaultStatus":204,"definitions":{}}`,
|
|
`{"definitions":{"A":{"code":1.5,"message":"a"}}}`,
|
|
`{"definitions":{"A":{"code":9223372036854775808,"message":"a"}}}`,
|
|
} {
|
|
var invalid apierrors.Catalog
|
|
err := json.Unmarshal([]byte(raw), &invalid)
|
|
if err == nil {
|
|
err = invalid.Validate()
|
|
}
|
|
if err == nil {
|
|
t.Errorf("accepted %s", raw)
|
|
}
|
|
}
|
|
for _, status := range []int{0, 99, 199, 204, 205, 304, 600} {
|
|
c := apierrors.Catalog{Definitions: map[string]apierrors.Definition{"A": {Status: status, Code: "a", Message: "a"}}}
|
|
if status == 0 {
|
|
continue
|
|
}
|
|
if c.Validate() == nil {
|
|
t.Fatal(status)
|
|
}
|
|
}
|
|
}
|