package gcp import ( "errors" "fmt" "testing" "google.golang.org/api/googleapi" "gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/provider" ) func gerr(code int, reasons ...string) error { e := &googleapi.Error{Code: code, Message: "boom"} for _, r := range reasons { e.Errors = append(e.Errors, googleapi.ErrorItem{Reason: r}) } return e } func TestClassify(t *testing.T) { t.Parallel() tests := []struct { name string err error want error }{ {name: "404 is NotFound", err: gerr(404), want: provider.ErrNotFound}, {name: "429 is Quota", err: gerr(429), want: provider.ErrQuotaExceeded}, {name: "403 quotaExceeded is Quota", err: gerr(403, "quotaExceeded"), want: provider.ErrQuotaExceeded}, {name: "403 rateLimitExceeded is Quota", err: gerr(403, "rateLimitExceeded"), want: provider.ErrQuotaExceeded}, {name: "403 plain is Permanent", err: gerr(403, "forbidden"), want: provider.ErrPermanent}, {name: "400 is Permanent", err: gerr(400), want: provider.ErrPermanent}, {name: "401 is Permanent", err: gerr(401), want: provider.ErrPermanent}, {name: "408 is Transient", err: gerr(408), want: provider.ErrTransient}, {name: "500 is Transient", err: gerr(500), want: provider.ErrTransient}, {name: "503 is Transient", err: gerr(503), want: provider.ErrTransient}, {name: "409 is Transient (alreadyExists is handled before classify)", err: gerr(409), want: provider.ErrTransient}, {name: "plain network error is Transient", err: errors.New("connection reset"), want: provider.ErrTransient}, {name: "wrapped googleapi error still classifies", err: fmt.Errorf("calling api: %w", gerr(404)), want: provider.ErrNotFound}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { t.Parallel() if got := classify(tc.err); got != tc.want { t.Errorf("classify() = %v, want %v", got, tc.want) } }) } } // The wrapped error must satisfy both halves of the taxonomy contract: // errors.Is against the sentinel AND errors.As back to the SDK error. func TestWrapErr_isAndAsBothWork(t *testing.T) { t.Parallel() p := &Provider{name: "gcp-eu"} wrapped := p.wrapErr("get", "zones/z/instances/i", gerr(404)) if !errors.Is(wrapped, provider.ErrNotFound) { t.Error("errors.Is(wrapped, ErrNotFound) = false") } var ge *googleapi.Error if !errors.As(wrapped, &ge) || ge.Code != 404 { t.Error("errors.As back to *googleapi.Error failed") } if provider.Class(wrapped) != provider.ErrNotFound { t.Errorf("Class() = %v, want ErrNotFound", provider.Class(wrapped)) } }