diff --git a/agent/cmd/main.go b/agent/cmd/main.go index 0ce89364..619f07ff 100644 --- a/agent/cmd/main.go +++ b/agent/cmd/main.go @@ -8,13 +8,12 @@ import ( "github.com/yusing/godoxy/agent/pkg/agent" "github.com/yusing/godoxy/agent/pkg/env" "github.com/yusing/godoxy/agent/pkg/server" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/metrics/systeminfo" httpServer "github.com/yusing/godoxy/internal/net/gphttp/server" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/pkg" socketproxy "github.com/yusing/godoxy/socketproxy/pkg" strutils "github.com/yusing/goutils/strings" + "github.com/yusing/goutils/task" ) func main() { @@ -27,21 +26,21 @@ func main() { ca := &agent.PEMPair{} err := ca.Load(env.AgentCACert) if err != nil { - gperr.LogFatal("init CA error", err) + log.Fatal().Err(err).Msg("init CA error") } caCert, err := ca.ToTLSCert() if err != nil { - gperr.LogFatal("init CA error", err) + log.Fatal().Err(err).Msg("init CA error") } srv := &agent.PEMPair{} srv.Load(env.AgentSSLCert) if err != nil { - gperr.LogFatal("init SSL error", err) + log.Fatal().Err(err).Msg("init SSL error") } srvCert, err := srv.ToTLSCert() if err != nil { - gperr.LogFatal("init SSL error", err) + log.Fatal().Err(err).Msg("init SSL error") } log.Info().Msgf("GoDoxy Agent version %s", pkg.GetVersion()) diff --git a/agent/go.mod b/agent/go.mod index e79d59e5..ace5e532 100644 --- a/agent/go.mod +++ b/agent/go.mod @@ -20,7 +20,7 @@ require ( github.com/stretchr/testify v1.11.1 github.com/yusing/godoxy v0.18.6 github.com/yusing/godoxy/socketproxy v0.0.0-00010101000000-000000000000 - github.com/yusing/goutils v0.2.1 + github.com/yusing/goutils v0.3.1 ) require ( diff --git a/agent/go.sum b/agent/go.sum index f7a7423e..3025ca58 100644 --- a/agent/go.sum +++ b/agent/go.sum @@ -208,8 +208,8 @@ github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusing/ds v0.2.0 h1:lPhDU5eA2uvquVrBrzLCrQXRJJgSXlUYA53TbuK2sQY= github.com/yusing/ds v0.2.0/go.mod h1:XhKV4l7cZwBbbl7lRzNC9zX27zvCM0frIwiuD40ULRk= -github.com/yusing/goutils v0.2.1 h1:KjoCrNO0otthaPCZPfQY+5GKsqs5+J77CxP+TNHYa/Y= -github.com/yusing/goutils v0.2.1/go.mod h1:v6RZsMRdzcts4udSg0vqUIFvaD0OaUMPTwYJZ4XnQYo= +github.com/yusing/goutils v0.3.1 h1:xCPoZ/haI8ZJ0ZaPU4g6+okSPdBczs8o98tIZ/TbpsQ= +github.com/yusing/goutils v0.3.1/go.mod h1:meg9GcAU8yvBY21JgYjPuLsXD1Q5VdVHE32A4tG5Y5g= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= diff --git a/agent/pkg/agent/agent_pool.go b/agent/pkg/agent/agent_pool.go index ed01115f..a3793144 100644 --- a/agent/pkg/agent/agent_pool.go +++ b/agent/pkg/agent/agent_pool.go @@ -2,15 +2,16 @@ package agent import ( "iter" + "os" + "strings" "github.com/puzpuzpuz/xsync/v4" - "github.com/yusing/godoxy/internal/common" ) var agentPool = xsync.NewMap[string, *AgentConfig](xsync.WithPresize(10)) func init() { - if common.IsTest { + if strings.HasSuffix(os.Args[0], ".test") { agentPool.Store("test-agent", &AgentConfig{ Addr: "test-agent", }) @@ -63,5 +64,5 @@ func NumAgents() int { func getAgentByAddr(addr string) (agent *AgentConfig, ok bool) { agent, ok = agentPool.Load(addr) - return + return agent, ok } diff --git a/agent/pkg/agent/new_agent.go b/agent/pkg/agent/new_agent.go index ad8de0bc..df0af75d 100644 --- a/agent/pkg/agent/new_agent.go +++ b/agent/pkg/agent/new_agent.go @@ -3,6 +3,8 @@ package agent import ( "crypto/aes" "crypto/cipher" + "crypto/ecdsa" + "crypto/elliptic" "crypto/rand" "crypto/tls" "crypto/x509" @@ -10,14 +12,11 @@ import ( "encoding/base64" "encoding/pem" "errors" + "fmt" "io" "math/big" "strings" "time" - - "crypto/ecdsa" - "crypto/elliptic" - "fmt" ) const ( @@ -244,5 +243,5 @@ func NewAgent() (ca, srv, client *PEMPair, err error) { } client = toPEMPair(clientCertDER, clientKey) - return + return ca, srv, client, err } diff --git a/agent/pkg/agentproxy/config.go b/agent/pkg/agentproxy/config.go index 1babd9b6..06b4623a 100644 --- a/agent/pkg/agentproxy/config.go +++ b/agent/pkg/agentproxy/config.go @@ -43,7 +43,7 @@ func proxyConfigFromHeadersLegacy(h http.Header) (cfg Config) { cfg.Scheme = "https" } - return + return cfg } func proxyConfigFromHeaders(h http.Header) (cfg Config, err error) { diff --git a/agent/pkg/server/server.go b/agent/pkg/server/server.go index c6a23cc5..f8c92dfe 100644 --- a/agent/pkg/server/server.go +++ b/agent/pkg/server/server.go @@ -10,7 +10,7 @@ import ( "github.com/yusing/godoxy/agent/pkg/env" "github.com/yusing/godoxy/agent/pkg/handler" "github.com/yusing/godoxy/internal/net/gphttp/server" - "github.com/yusing/godoxy/internal/task" + "github.com/yusing/goutils/task" ) type Options struct { diff --git a/cmd/main.go b/cmd/main.go index 9f066d02..d0f53046 100755 --- a/cmd/main.go +++ b/cmd/main.go @@ -9,15 +9,15 @@ import ( "github.com/yusing/godoxy/internal/common" "github.com/yusing/godoxy/internal/config" "github.com/yusing/godoxy/internal/dnsproviders" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/homepage" "github.com/yusing/godoxy/internal/logging" "github.com/yusing/godoxy/internal/logging/memlogger" "github.com/yusing/godoxy/internal/metrics/systeminfo" "github.com/yusing/godoxy/internal/metrics/uptime" "github.com/yusing/godoxy/internal/net/gphttp/middleware" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/pkg" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) func parallel(fns ...func()) { diff --git a/go.mod b/go.mod index 068a83cc..3a4f6504 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,7 @@ require ( github.com/yusing/godoxy/agent v0.0.0-20250926130035-55c1c918ba95 github.com/yusing/godoxy/internal/dnsproviders v0.0.0-20250926130035-55c1c918ba95 github.com/yusing/godoxy/internal/utils v0.1.0 - github.com/yusing/goutils v0.2.1 + github.com/yusing/goutils v0.3.1 ) require ( diff --git a/go.sum b/go.sum index 824ac291..e598eaca 100644 --- a/go.sum +++ b/go.sum @@ -1648,8 +1648,8 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusing/ds v0.2.0 h1:lPhDU5eA2uvquVrBrzLCrQXRJJgSXlUYA53TbuK2sQY= github.com/yusing/ds v0.2.0/go.mod h1:XhKV4l7cZwBbbl7lRzNC9zX27zvCM0frIwiuD40ULRk= -github.com/yusing/goutils v0.2.1 h1:KjoCrNO0otthaPCZPfQY+5GKsqs5+J77CxP+TNHYa/Y= -github.com/yusing/goutils v0.2.1/go.mod h1:v6RZsMRdzcts4udSg0vqUIFvaD0OaUMPTwYJZ4XnQYo= +github.com/yusing/goutils v0.3.1 h1:xCPoZ/haI8ZJ0ZaPU4g6+okSPdBczs8o98tIZ/TbpsQ= +github.com/yusing/goutils v0.3.1/go.mod h1:meg9GcAU8yvBY21JgYjPuLsXD1Q5VdVHE32A4tG5Y5g= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= diff --git a/internal/acl/config.go b/internal/acl/config.go index 33f7320d..78b0be41 100644 --- a/internal/acl/config.go +++ b/internal/acl/config.go @@ -7,11 +7,11 @@ import ( "github.com/puzpuzpuz/xsync/v4" "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/logging/accesslog" "github.com/yusing/godoxy/internal/maxmind" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/utils" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) type Config struct { diff --git a/internal/acl/matcher.go b/internal/acl/matcher.go index 4c9fe59d..494c543b 100644 --- a/internal/acl/matcher.go +++ b/internal/acl/matcher.go @@ -4,8 +4,8 @@ import ( "net" "strings" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/maxmind" + gperr "github.com/yusing/goutils/errs" ) type MatcherFunc func(*maxmind.IPInfo) bool diff --git a/internal/api/handler.go b/internal/api/handler.go index 8677019b..96c4b37b 100644 --- a/internal/api/handler.go +++ b/internal/api/handler.go @@ -20,7 +20,7 @@ import ( routeApi "github.com/yusing/godoxy/internal/api/v1/route" "github.com/yusing/godoxy/internal/auth" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) // @title GoDoxy API diff --git a/internal/api/types/error.go b/internal/api/types/error.go index 0951ee5a..2853bc68 100644 --- a/internal/api/types/error.go +++ b/internal/api/types/error.go @@ -3,7 +3,7 @@ package apitypes import ( "errors" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type ErrorResponse struct { diff --git a/internal/api/v1/agent/create.go b/internal/api/v1/agent/create.go index 43545259..225240ea 100644 --- a/internal/api/v1/agent/create.go +++ b/internal/api/v1/agent/create.go @@ -9,7 +9,7 @@ import ( "github.com/gin-gonic/gin" "github.com/yusing/godoxy/agent/pkg/agent" - apitypes "github.com/yusing/godoxy/internal/api/types" + apitypes "github.com/yusing/goutils/apitypes" ) type NewAgentRequest struct { diff --git a/internal/api/v1/agent/verify.go b/internal/api/v1/agent/verify.go index fe2158e8..b219ebc4 100644 --- a/internal/api/v1/agent/verify.go +++ b/internal/api/v1/agent/verify.go @@ -8,8 +8,8 @@ import ( "github.com/gin-gonic/gin" "github.com/yusing/godoxy/agent/pkg/agent" "github.com/yusing/godoxy/agent/pkg/certs" - . "github.com/yusing/godoxy/internal/api/types" config "github.com/yusing/godoxy/internal/config/types" + apitypes "github.com/yusing/goutils/apitypes" ) type VerifyNewAgentRequest struct { @@ -35,44 +35,44 @@ type VerifyNewAgentRequest struct { func Verify(c *gin.Context) { var request VerifyNewAgentRequest if err := c.ShouldBindJSON(&request); err != nil { - c.JSON(http.StatusBadRequest, Error("invalid request", err)) + c.JSON(http.StatusBadRequest, apitypes.Error("invalid request", err)) return } filename, ok := certs.AgentCertsFilepath(request.Host) if !ok { - c.JSON(http.StatusBadRequest, Error("invalid host", nil)) + c.JSON(http.StatusBadRequest, apitypes.Error("invalid host", nil)) return } ca, err := fromEncryptedPEMPairResponse(request.CA) if err != nil { - c.JSON(http.StatusBadRequest, Error("invalid CA", err)) + c.JSON(http.StatusBadRequest, apitypes.Error("invalid CA", err)) return } client, err := fromEncryptedPEMPairResponse(request.Client) if err != nil { - c.JSON(http.StatusBadRequest, Error("invalid client", err)) + c.JSON(http.StatusBadRequest, apitypes.Error("invalid client", err)) return } nRoutesAdded, err := config.GetInstance().VerifyNewAgent(request.Host, ca, client, request.ContainerRuntime) if err != nil { - c.JSON(http.StatusBadRequest, Error("invalid request", err)) + c.JSON(http.StatusBadRequest, apitypes.Error("invalid request", err)) return } zip, err := certs.ZipCert(ca.Cert, client.Cert, client.Key) if err != nil { - c.Error(InternalServerError(err, "failed to zip certs")) + c.Error(apitypes.InternalServerError(err, "failed to zip certs")) return } if err := os.WriteFile(filename, zip, 0o600); err != nil { - c.Error(InternalServerError(err, "failed to write certs")) + c.Error(apitypes.InternalServerError(err, "failed to write certs")) return } - c.JSON(http.StatusOK, Success(fmt.Sprintf("Added %d routes", nRoutesAdded))) + c.JSON(http.StatusOK, apitypes.Success(fmt.Sprintf("Added %d routes", nRoutesAdded))) } diff --git a/internal/api/v1/cert/renew.go b/internal/api/v1/cert/renew.go index 8d8c6f38..51597e82 100644 --- a/internal/api/v1/cert/renew.go +++ b/internal/api/v1/cert/renew.go @@ -8,9 +8,9 @@ import ( "github.com/rs/zerolog/log" apitypes "github.com/yusing/godoxy/internal/api/types" config "github.com/yusing/godoxy/internal/config/types" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/logging/memlogger" "github.com/yusing/godoxy/internal/net/gphttp/websocket" + gperr "github.com/yusing/goutils/errs" ) // @x-id "renew" diff --git a/internal/api/v1/docker/containers.go b/internal/api/v1/docker/containers.go index b67850d6..06f32962 100644 --- a/internal/api/v1/docker/containers.go +++ b/internal/api/v1/docker/containers.go @@ -6,7 +6,7 @@ import ( "github.com/docker/docker/api/types/container" "github.com/gin-gonic/gin" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type ContainerState = container.ContainerState // @name ContainerState diff --git a/internal/api/v1/docker/info.go b/internal/api/v1/docker/info.go index 995100d8..43f4caf0 100644 --- a/internal/api/v1/docker/info.go +++ b/internal/api/v1/docker/info.go @@ -6,7 +6,7 @@ import ( dockerSystem "github.com/docker/docker/api/types/system" "github.com/gin-gonic/gin" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" ) diff --git a/internal/api/v1/docker/logs.go b/internal/api/v1/docker/logs.go index 5c4c5ac0..636bacdf 100644 --- a/internal/api/v1/docker/logs.go +++ b/internal/api/v1/docker/logs.go @@ -13,7 +13,7 @@ import ( apitypes "github.com/yusing/godoxy/internal/api/types" "github.com/yusing/godoxy/internal/docker" "github.com/yusing/godoxy/internal/net/gphttp/websocket" - "github.com/yusing/godoxy/internal/task" + "github.com/yusing/goutils/task" ) type LogsQueryParams struct { diff --git a/internal/api/v1/docker/utils.go b/internal/api/v1/docker/utils.go index f2086edb..65b2b95c 100644 --- a/internal/api/v1/docker/utils.go +++ b/internal/api/v1/docker/utils.go @@ -10,8 +10,8 @@ import ( apitypes "github.com/yusing/godoxy/internal/api/types" config "github.com/yusing/godoxy/internal/config/types" "github.com/yusing/godoxy/internal/docker" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/net/gphttp/websocket" + gperr "github.com/yusing/goutils/errs" "github.com/yusing/goutils/http/httpheaders" ) diff --git a/internal/api/v1/file/validate.go b/internal/api/v1/file/validate.go index 38f13ee8..96889570 100644 --- a/internal/api/v1/file/validate.go +++ b/internal/api/v1/file/validate.go @@ -6,9 +6,9 @@ import ( "github.com/gin-gonic/gin" apitypes "github.com/yusing/godoxy/internal/api/types" config "github.com/yusing/godoxy/internal/config/types" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/net/gphttp/middleware" "github.com/yusing/godoxy/internal/route/provider" + gperr "github.com/yusing/goutils/errs" ) type ValidateFileRequest struct { diff --git a/internal/api/v1/metrics/all_system_info.go b/internal/api/v1/metrics/all_system_info.go index d80b8bd5..f100ace1 100644 --- a/internal/api/v1/metrics/all_system_info.go +++ b/internal/api/v1/metrics/all_system_info.go @@ -14,10 +14,10 @@ import ( "github.com/rs/zerolog/log" "github.com/yusing/godoxy/agent/pkg/agent" apitypes "github.com/yusing/godoxy/internal/api/types" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/metrics/period" "github.com/yusing/godoxy/internal/metrics/systeminfo" "github.com/yusing/godoxy/internal/net/gphttp/websocket" + gperr "github.com/yusing/goutils/errs" "github.com/yusing/goutils/http/httpheaders" "github.com/yusing/goutils/synk" ) diff --git a/internal/auth/oidc.go b/internal/auth/oidc.go index 84feec8c..d5d5b347 100644 --- a/internal/auth/oidc.go +++ b/internal/auth/oidc.go @@ -15,9 +15,9 @@ import ( "github.com/coreos/go-oidc/v3/oidc" "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/net/gphttp" "github.com/yusing/godoxy/internal/utils" + gperr "github.com/yusing/goutils/errs" "golang.org/x/oauth2" "golang.org/x/time/rate" ) diff --git a/internal/auth/oidc_test.go b/internal/auth/oidc_test.go index 9264ba7c..131e616b 100644 --- a/internal/auth/oidc_test.go +++ b/internal/auth/oidc_test.go @@ -16,7 +16,7 @@ import ( "github.com/yusing/godoxy/internal/common" "golang.org/x/oauth2" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) // setupMockOIDC configures mock OIDC provider for testing. @@ -35,7 +35,7 @@ func setupMockOIDC(t *testing.T) { }, Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, }, - endSessionURL: Must(url.Parse("http://mock-provider/logout")), + endSessionURL: expect.Must(url.Parse("http://mock-provider/logout")), oidcProvider: provider, oidcVerifier: provider.Verifier(&oidc.Config{ ClientID: "test-client", @@ -75,7 +75,7 @@ func (j *provider) SignClaims(t *testing.T, claims jwt.Claims) string { token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims) token.Header["kid"] = keyID signed, err := token.SignedString(j.key) - ExpectNoError(t, err) + expect.NoError(t, err) return signed } @@ -84,7 +84,7 @@ func setupProvider(t *testing.T) *provider { // Generate an RSA key pair for the test. privKey, err := rsa.GenerateKey(rand.Reader, 2048) - ExpectNoError(t, err) + expect.NoError(t, err) // Build the matching public JWK that will be served by the endpoint. jwk := buildRSAJWK(t, &privKey.PublicKey, keyID) @@ -227,12 +227,12 @@ func TestOIDCCallbackHandler(t *testing.T) { } if tt.wantStatus == http.StatusTemporaryRedirect { - setCookie := Must(http.ParseSetCookie(w.Header().Get("Set-Cookie"))) - ExpectEqual(t, setCookie.Name, CookieOauthToken) - ExpectTrue(t, setCookie.Value != "") - ExpectEqual(t, setCookie.Path, "/") - ExpectEqual(t, setCookie.SameSite, http.SameSiteLaxMode) - ExpectEqual(t, setCookie.HttpOnly, true) + setCookie := expect.Must(http.ParseSetCookie(w.Header().Get("Set-Cookie"))) + expect.Equal(t, setCookie.Name, CookieOauthToken) + expect.True(t, setCookie.Value != "") + expect.Equal(t, setCookie.Path, "/") + expect.Equal(t, setCookie.SameSite, http.SameSiteLaxMode) + expect.Equal(t, setCookie.HttpOnly, true) } }) } @@ -245,7 +245,7 @@ func TestInitOIDC(t *testing.T) { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") - ExpectNoError(t, json.NewEncoder(w).Encode(discoveryDocument(t, server))) + expect.NoError(t, json.NewEncoder(w).Encode(discoveryDocument(t, server))) }) server = httptest.NewServer(mux) t.Cleanup(server.Close) @@ -445,9 +445,9 @@ func TestCheckToken(t *testing.T) { // Call CheckToken and verify the result. err := auth.CheckToken(req) if tc.wantErr == nil { - ExpectNoError(t, err) + expect.NoError(t, err) } else { - ExpectError(t, tc.wantErr, err) + expect.ErrorIs(t, tc.wantErr, err) } }) } diff --git a/internal/auth/userpass.go b/internal/auth/userpass.go index 16db865e..cab9ae54 100644 --- a/internal/auth/userpass.go +++ b/internal/auth/userpass.go @@ -8,8 +8,8 @@ import ( "github.com/golang-jwt/jwt/v5" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/net/gphttp" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" "golang.org/x/crypto/bcrypt" ) diff --git a/internal/auth/userpass_test.go b/internal/auth/userpass_test.go index e8e1d362..5746a033 100644 --- a/internal/auth/userpass_test.go +++ b/internal/auth/userpass_test.go @@ -9,14 +9,14 @@ import ( "testing" "time" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" "golang.org/x/crypto/bcrypt" ) func newMockUserPassAuth() *UserPassAuth { return &UserPassAuth{ username: "username", - pwdHash: Must(bcrypt.GenerateFromPassword([]byte("password"), bcrypt.DefaultCost)), + pwdHash: expect.Must(bcrypt.GenerateFromPassword([]byte("password"), bcrypt.DefaultCost)), secret: []byte("abcdefghijklmnopqrstuvwxyz"), tokenTTL: time.Hour, } @@ -25,17 +25,17 @@ func newMockUserPassAuth() *UserPassAuth { func TestUserPassValidateCredentials(t *testing.T) { auth := newMockUserPassAuth() err := auth.validatePassword("username", "password") - ExpectNoError(t, err) + expect.NoError(t, err) err = auth.validatePassword("username", "wrong-password") - ExpectError(t, ErrInvalidPassword, err) + expect.ErrorIs(t, ErrInvalidPassword, err) err = auth.validatePassword("wrong-username", "password") - ExpectError(t, ErrInvalidUsername, err) + expect.ErrorIs(t, ErrInvalidUsername, err) } func TestUserPassCheckToken(t *testing.T) { auth := newMockUserPassAuth() token, err := auth.NewToken() - ExpectNoError(t, err) + expect.NoError(t, err) tests := []struct { token string wantErr bool @@ -60,9 +60,9 @@ func TestUserPassCheckToken(t *testing.T) { } err = auth.CheckToken(req) if tt.wantErr { - ExpectTrue(t, err != nil) + expect.True(t, err != nil) } else { - ExpectNoError(t, err) + expect.NoError(t, err) } } } @@ -96,20 +96,20 @@ func TestUserPassLoginCallbackHandler(t *testing.T) { w := httptest.NewRecorder() req := &http.Request{ Host: "app.example.com", - Body: io.NopCloser(bytes.NewReader(Must(json.Marshal(tt.creds)))), + Body: io.NopCloser(bytes.NewReader(expect.Must(json.Marshal(tt.creds)))), } auth.PostAuthCallbackHandler(w, req) if tt.wantErr { - ExpectEqual(t, w.Code, http.StatusUnauthorized) + expect.Equal(t, w.Code, http.StatusUnauthorized) } else { - setCookie := Must(http.ParseSetCookie(w.Header().Get("Set-Cookie"))) - ExpectTrue(t, setCookie.Name == auth.TokenCookieName()) - ExpectTrue(t, setCookie.Value != "") - ExpectEqual(t, setCookie.Domain, "example.com") - ExpectEqual(t, setCookie.Path, "/") - ExpectEqual(t, setCookie.SameSite, http.SameSiteLaxMode) - ExpectEqual(t, setCookie.HttpOnly, true) - ExpectEqual(t, w.Code, http.StatusOK) + setCookie := expect.Must(http.ParseSetCookie(w.Header().Get("Set-Cookie"))) + expect.True(t, setCookie.Name == auth.TokenCookieName()) + expect.True(t, setCookie.Value != "") + expect.Equal(t, setCookie.Domain, "example.com") + expect.Equal(t, setCookie.Path, "/") + expect.Equal(t, setCookie.SameSite, http.SameSiteLaxMode) + expect.Equal(t, setCookie.HttpOnly, true) + expect.Equal(t, w.Code, http.StatusOK) } } } diff --git a/internal/auth/utils.go b/internal/auth/utils.go index c8e42b9c..d7d2bd53 100644 --- a/internal/auth/utils.go +++ b/internal/auth/utils.go @@ -7,7 +7,7 @@ import ( "time" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" ) diff --git a/internal/autocert/config.go b/internal/autocert/config.go index a8bfa792..c6eafc8d 100644 --- a/internal/autocert/config.go +++ b/internal/autocert/config.go @@ -15,8 +15,8 @@ import ( "github.com/go-acme/lego/v4/lego" "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/utils" + gperr "github.com/yusing/goutils/errs" ) type Config struct { diff --git a/internal/autocert/provider.go b/internal/autocert/provider.go index e7014a06..d3b45020 100644 --- a/internal/autocert/provider.go +++ b/internal/autocert/provider.go @@ -18,10 +18,10 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/notif" - "github.com/yusing/godoxy/internal/task" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" + "github.com/yusing/goutils/task" ) type ( diff --git a/internal/autocert/providers.go b/internal/autocert/providers.go index 26f5f2a7..54da5163 100644 --- a/internal/autocert/providers.go +++ b/internal/autocert/providers.go @@ -2,8 +2,8 @@ package autocert import ( "github.com/go-acme/lego/v4/challenge" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/serialization" + gperr "github.com/yusing/goutils/errs" ) type Generator func(map[string]any) (challenge.Provider, gperr.Error) diff --git a/internal/autocert/types/provider.go b/internal/autocert/types/provider.go index 7b271175..69fdf918 100644 --- a/internal/autocert/types/provider.go +++ b/internal/autocert/types/provider.go @@ -3,7 +3,7 @@ package autocert import ( "crypto/tls" - "github.com/yusing/godoxy/internal/task" + "github.com/yusing/goutils/task" ) type Provider interface { diff --git a/internal/config/agents.go b/internal/config/agents.go index c7c0074d..9bbaadb8 100644 --- a/internal/config/agents.go +++ b/internal/config/agents.go @@ -2,8 +2,8 @@ package config import ( "github.com/yusing/godoxy/agent/pkg/agent" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/route/provider" + gperr "github.com/yusing/goutils/errs" ) func (cfg *Config) VerifyNewAgent(host string, ca agent.PEMPair, client agent.PEMPair, containerRuntime agent.ContainerRuntime) (int, gperr.Error) { diff --git a/internal/config/config.go b/internal/config/config.go index 6a3050a0..ef18b02a 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -18,17 +18,17 @@ import ( "github.com/yusing/godoxy/internal/common" config "github.com/yusing/godoxy/internal/config/types" "github.com/yusing/godoxy/internal/entrypoint" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/maxmind" "github.com/yusing/godoxy/internal/net/gphttp/server" "github.com/yusing/godoxy/internal/notif" "github.com/yusing/godoxy/internal/proxmox" proxy "github.com/yusing/godoxy/internal/route/provider" "github.com/yusing/godoxy/internal/serialization" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/watcher" "github.com/yusing/godoxy/internal/watcher/events" + gperr "github.com/yusing/goutils/errs" "github.com/yusing/goutils/strings/ansi" + "github.com/yusing/goutils/task" ) type Config struct { diff --git a/internal/config/types/config.go b/internal/config/types/config.go index 412a033b..adb9cc3c 100644 --- a/internal/config/types/config.go +++ b/internal/config/types/config.go @@ -9,13 +9,13 @@ import ( "github.com/yusing/godoxy/agent/pkg/agent" "github.com/yusing/godoxy/internal/acl" "github.com/yusing/godoxy/internal/autocert" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/logging/accesslog" maxmind "github.com/yusing/godoxy/internal/maxmind/types" "github.com/yusing/godoxy/internal/notif" "github.com/yusing/godoxy/internal/proxmox" "github.com/yusing/godoxy/internal/serialization" "github.com/yusing/godoxy/internal/types" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/dnsproviders/dummy.go b/internal/dnsproviders/dummy.go index c35b0bb8..42ddb47a 100644 --- a/internal/dnsproviders/dummy.go +++ b/internal/dnsproviders/dummy.go @@ -1,7 +1,9 @@ package dnsproviders -type DummyConfig struct{} -type DummyProvider struct{} +type ( + DummyConfig struct{} + DummyProvider struct{} +) func NewDummyDefaultConfig() *DummyConfig { return &DummyConfig{} diff --git a/internal/dnsproviders/go.mod b/internal/dnsproviders/go.mod index 5634cede..fb9a9206 100644 --- a/internal/dnsproviders/go.mod +++ b/internal/dnsproviders/go.mod @@ -148,7 +148,7 @@ require ( github.com/vultr/govultr/v3 v3.24.0 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect github.com/yusing/godoxy/internal/utils v0.1.0 // indirect - github.com/yusing/goutils v0.2.1 // indirect + github.com/yusing/goutils v0.3.1 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect diff --git a/internal/dnsproviders/go.sum b/internal/dnsproviders/go.sum index 3e019736..673e76bc 100644 --- a/internal/dnsproviders/go.sum +++ b/internal/dnsproviders/go.sum @@ -1513,8 +1513,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusing/goutils v0.2.1 h1:KjoCrNO0otthaPCZPfQY+5GKsqs5+J77CxP+TNHYa/Y= -github.com/yusing/goutils v0.2.1/go.mod h1:v6RZsMRdzcts4udSg0vqUIFvaD0OaUMPTwYJZ4XnQYo= +github.com/yusing/goutils v0.3.1 h1:xCPoZ/haI8ZJ0ZaPU4g6+okSPdBczs8o98tIZ/TbpsQ= +github.com/yusing/goutils v0.3.1/go.mod h1:meg9GcAU8yvBY21JgYjPuLsXD1Q5VdVHE32A4tG5Y5g= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= diff --git a/internal/docker/client.go b/internal/docker/client.go index 4ed034d7..adf3928c 100644 --- a/internal/docker/client.go +++ b/internal/docker/client.go @@ -16,7 +16,7 @@ import ( "github.com/rs/zerolog/log" "github.com/yusing/godoxy/agent/pkg/agent" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/task" + "github.com/yusing/goutils/task" ) // TODO: implement reconnect here. diff --git a/internal/docker/container.go b/internal/docker/container.go index 6f4664cc..d0c187ef 100644 --- a/internal/docker/container.go +++ b/internal/docker/container.go @@ -14,10 +14,10 @@ import ( "github.com/docker/docker/api/types/container" "github.com/docker/go-connections/nat" "github.com/yusing/godoxy/agent/pkg/agent" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/serialization" "github.com/yusing/godoxy/internal/types" "github.com/yusing/godoxy/internal/utils" + gperr "github.com/yusing/goutils/errs" ) var DummyContainer = new(types.Container) @@ -84,7 +84,7 @@ func FromDocker(c *container.Summary, dockerHost string) (res *types.Container) if res.PrivateHostname == "" && res.PublicHostname == "" && res.Running { addError(res, ErrNoNetwork) } - return + return res } func IsBlacklisted(c *types.Container) bool { diff --git a/internal/docker/container_test.go b/internal/docker/container_test.go index 3eb68a70..3dddd829 100644 --- a/internal/docker/container_test.go +++ b/internal/docker/container_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/docker/docker/api/types/container" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestContainerExplicit(t *testing.T) { @@ -37,7 +37,7 @@ func TestContainerExplicit(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := FromDocker(&container.Summary{Names: []string{"test"}, State: "test", Labels: tt.labels}, "") - ExpectEqual(t, c.IsExplicit, tt.isExplicit) + expect.Equal(t, c.IsExplicit, tt.isExplicit) }) } } @@ -74,7 +74,7 @@ func TestContainerHostNetworkMode(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := FromDocker(tt.container, "") - ExpectEqual(t, c.IsHostNetworkMode, tt.isHostNetworkMode) + expect.Equal(t, c.IsHostNetworkMode, tt.isHostNetworkMode) }) } } @@ -109,9 +109,9 @@ func TestImageNameParsing(t *testing.T) { t.Run(tt.full, func(t *testing.T) { helper := containerHelper{&container.Summary{Image: tt.full}} im := helper.parseImage() - ExpectEqual(t, im.Author, tt.author) - ExpectEqual(t, im.Name, tt.image) - ExpectEqual(t, im.Tag, tt.tag) + expect.Equal(t, im.Author, tt.author) + expect.Equal(t, im.Name, tt.image) + expect.Equal(t, im.Tag, tt.tag) }) } } diff --git a/internal/docker/label.go b/internal/docker/label.go index 21c4391f..057efe17 100644 --- a/internal/docker/label.go +++ b/internal/docker/label.go @@ -5,8 +5,8 @@ import ( "strings" "github.com/goccy/go-yaml" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/types" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" ) diff --git a/internal/entrypoint/entrypoint.go b/internal/entrypoint/entrypoint.go index 61cd2b76..e4bd7c54 100644 --- a/internal/entrypoint/entrypoint.go +++ b/internal/entrypoint/entrypoint.go @@ -11,8 +11,8 @@ import ( "github.com/yusing/godoxy/internal/net/gphttp/middleware" "github.com/yusing/godoxy/internal/net/gphttp/middleware/errorpage" "github.com/yusing/godoxy/internal/route/routes" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" + "github.com/yusing/goutils/task" ) type Entrypoint struct { @@ -56,15 +56,15 @@ func (ep *Entrypoint) SetMiddlewares(mws []map[string]any) error { func (ep *Entrypoint) SetAccessLogger(parent task.Parent, cfg *accesslog.RequestLoggerConfig) (err error) { if cfg == nil { ep.accessLogger = nil - return + return err } ep.accessLogger, err = accesslog.NewAccessLogger(parent, cfg) if err != nil { - return + return err } log.Debug().Msg("entrypoint access logger created") - return + return err } func (ep *Entrypoint) ServeHTTP(w http.ResponseWriter, r *http.Request) { diff --git a/internal/entrypoint/entrypoint_benchmark_test.go b/internal/entrypoint/entrypoint_benchmark_test.go index f1c0d555..3739f9b2 100644 --- a/internal/entrypoint/entrypoint_benchmark_test.go +++ b/internal/entrypoint/entrypoint_benchmark_test.go @@ -12,8 +12,8 @@ import ( "github.com/yusing/godoxy/internal/route" "github.com/yusing/godoxy/internal/route/routes" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" + "github.com/yusing/goutils/task" ) type noopResponseWriter struct { @@ -24,10 +24,12 @@ type noopResponseWriter struct { func (w *noopResponseWriter) Header() http.Header { return http.Header{} } + func (w *noopResponseWriter) Write(b []byte) (int, error) { w.written = b return len(b), nil } + func (w *noopResponseWriter) WriteHeader(statusCode int) { w.statusCode = statusCode } @@ -45,7 +47,7 @@ func (t noopTransport) RoundTrip(req *http.Request) (*http.Response, error) { func BenchmarkEntrypointReal(b *testing.B) { var ep Entrypoint - var req = http.Request{ + req := http.Request{ Method: "GET", URL: &url.URL{Path: "/", RawPath: "/"}, Host: "test.domain.tld", @@ -107,7 +109,7 @@ func BenchmarkEntrypointReal(b *testing.B) { func BenchmarkEntrypoint(b *testing.B) { var ep Entrypoint - var req = http.Request{ + req := http.Request{ Method: "GET", URL: &url.URL{Path: "/", RawPath: "/"}, Host: "test.domain.tld", diff --git a/internal/entrypoint/entrypoint_test.go b/internal/entrypoint/entrypoint_test.go index 666af96b..51a1b6b4 100644 --- a/internal/entrypoint/entrypoint_test.go +++ b/internal/entrypoint/entrypoint_test.go @@ -6,7 +6,7 @@ import ( "github.com/yusing/godoxy/internal/route" "github.com/yusing/godoxy/internal/route/routes" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) var ep = NewEntrypoint() diff --git a/internal/gperr/README.md b/internal/gperr/README.md deleted file mode 100644 index 1ee390e4..00000000 --- a/internal/gperr/README.md +++ /dev/null @@ -1,106 +0,0 @@ -# gperr - -gperr is an error interface that supports nested structure and subject highlighting. - -## Usage - -### gperr.Error - -The error interface. - -### gperr.New - -Like `errors.New`, but returns a `gperr.Error`. - -### gperr.Wrap - -Like `fmt.Errorf("%s: %w", message, err)`, but returns a `gperr.Error`. - -### gperr.Error.Subject - -Returns a new error with the subject prepended to the error message. The main subject is highlighted. - -```go -err := gperr.New("error message") -err = err.Subject("bar") -err = err.Subject("foo") -``` - -Output: - -foo > bar: error message - -### gperr.Error.Subjectf - -Like `gperr.Error.Subject`, but formats the subject with `fmt.Sprintf`. - -### gperr.PrependSubject - -Prepends the subject to the error message like `gperr.Error.Subject`. - -```go -err := gperr.New("error message") -err = gperr.PrependSubject(err, "foo") -err = gperr.PrependSubject(err, "bar") -``` - -Output: - -bar > foo: error message - -### gperr.Error.With - -Adds a new error to the error chain. - -```go -err := gperr.New("error message") -err = err.With(gperr.New("inner error")) -err = err.With(gperr.New("inner error 2").With(gperr.New("inner inner error"))) -``` - -Output: - -``` -error message: - • inner error - • inner error 2 - • inner inner error -``` - -### gperr.Error.Withf - -Like `gperr.Error.With`, but formats the error with `fmt.Errorf`. - -### gperr.Error.Is - -Returns true if the error is equal to the given error. - -### gperr.Builder - -A builder for `gperr.Error`. - -```go -builder := gperr.NewBuilder("foo") -builder.Add(gperr.New("error message")) -builder.Addf("error message: %s", "foo") -builder.AddRange(gperr.New("error message 1"), gperr.New("error message 2")) -``` - -Output: - -``` -foo: - • error message - • error message: foo - • error message 1 - • error message 2 -``` - -### gperr.Builder.Build - -Builds a `gperr.Error` from the builder. - -## When to return gperr.Error - -- When you want to return multiple errors -- When the error has a subject diff --git a/internal/gperr/base.go b/internal/gperr/base.go deleted file mode 100644 index 6bdc457f..00000000 --- a/internal/gperr/base.go +++ /dev/null @@ -1,75 +0,0 @@ -package gperr - -import ( - "encoding/json" - "errors" - "fmt" -) - -// baseError is an immutable wrapper around an error. -// -//nolint:recvcheck -type baseError struct { - Err error `json:"err"` -} - -func (err *baseError) Unwrap() error { - return err.Err -} - -func (err *baseError) Is(other error) bool { - if other, ok := other.(*baseError); ok { - return errors.Is(err.Err, other.Err) - } - return errors.Is(err.Err, other) -} - -func (err baseError) Subject(subject string) Error { - err.Err = PrependSubject(subject, err.Err) - return &err -} - -func (err *baseError) Subjectf(format string, args ...any) Error { - if len(args) > 0 { - return err.Subject(fmt.Sprintf(format, args...)) - } - return err.Subject(format) -} - -func (err *baseError) With(extra error) Error { - if extra == nil { - return err - } - return &nestedError{&baseError{err.Err}, []error{extra}} -} - -func (err baseError) Withf(format string, args ...any) Error { - return &nestedError{&err, []error{fmt.Errorf(format, args...)}} -} - -func (err *baseError) Error() string { - return err.Err.Error() -} - -// MarshalJSON implements the json.Marshaler interface. -func (err *baseError) MarshalJSON() ([]byte, error) { - //nolint:errorlint - switch err := err.Err.(type) { - case Error, *withSubject: - return json.Marshal(err) - case json.Marshaler: - return err.MarshalJSON() - case interface{ MarshalText() ([]byte, error) }: - return err.MarshalText() - default: - return json.Marshal(err.Error()) - } -} - -func (err *baseError) Plain() []byte { - return Plain(err.Err) -} - -func (err *baseError) Markdown() []byte { - return Markdown(err.Err) -} diff --git a/internal/gperr/builder.go b/internal/gperr/builder.go deleted file mode 100644 index 21eca3ae..00000000 --- a/internal/gperr/builder.go +++ /dev/null @@ -1,161 +0,0 @@ -package gperr - -import ( - "fmt" - "sync" -) - -type noLock struct{} - -func (noLock) Lock() {} -func (noLock) Unlock() {} -func (noLock) RLock() {} -func (noLock) RUnlock() {} - -type rwLock interface { - sync.Locker - RLock() - RUnlock() -} - -type Builder struct { - about string - errs []error - rwLock -} - -// NewBuilder creates a new Builder. -// -// If about is not provided, the Builder will not have a subject -// and will expand when adding to another builder. -func NewBuilder(about ...string) *Builder { - if len(about) == 0 { - return &Builder{rwLock: noLock{}} - } - return &Builder{about: about[0], rwLock: noLock{}} -} - -func NewBuilderWithConcurrency(about ...string) *Builder { - if len(about) == 0 { - return &Builder{rwLock: new(sync.RWMutex)} - } - return &Builder{about: about[0], rwLock: new(sync.RWMutex)} -} - -func (b *Builder) EnableConcurrency() { - b.rwLock = new(sync.RWMutex) -} - -func (b *Builder) About() string { - return b.about -} - -func (b *Builder) HasError() bool { - // no need to lock, when this is called, the Builder is not used anymore - return len(b.errs) > 0 -} - -func (b *Builder) Error() Error { - if len(b.errs) == 0 { - return nil - } - if len(b.errs) == 1 && b.about == "" { - return wrap(b.errs[0]) - } - return &nestedError{Err: New(b.about), Extras: b.errs} -} - -func (b *Builder) String() string { - err := b.Error() - if err == nil { - return "" - } - return err.Error() -} - -// Add adds an error to the Builder. -// -// adding nil is no-op. -func (b *Builder) Add(err error) { - if err == nil { - return - } - - b.Lock() - defer b.Unlock() - - b.add(err) -} - -func (b *Builder) Adds(err string) { - b.Lock() - defer b.Unlock() - b.errs = append(b.errs, newError(err)) -} - -func (b *Builder) Addf(format string, args ...any) { - if len(args) > 0 { - b.Lock() - defer b.Unlock() - b.errs = append(b.errs, fmt.Errorf(format, args...)) - } else { - b.Adds(format) - } -} - -func (b *Builder) AddFrom(other *Builder, flatten bool) { - if other == nil || !other.HasError() { - return - } - - b.Lock() - defer b.Unlock() - if flatten { - b.errs = append(b.errs, other.errs...) - } else { - b.errs = append(b.errs, other.Error()) - } -} - -func (b *Builder) AddRange(errs ...error) { - nonNilErrs := make([]error, 0, len(errs)) - for _, err := range errs { - if err != nil { - nonNilErrs = append(nonNilErrs, err) - } - } - - b.Lock() - defer b.Unlock() - - for _, err := range nonNilErrs { - b.add(err) - } -} - -func (b *Builder) ForEach(fn func(error)) { - b.RLock() - errs := b.errs - b.RUnlock() - - for _, err := range errs { - fn(err) - } -} - -func (b *Builder) add(err error) { - switch err := err.(type) { //nolint:errorlint - case *baseError: - b.errs = append(b.errs, err.Err) - case *nestedError: - if err.Err == nil { - b.errs = append(b.errs, err.Extras...) - } else { - b.errs = append(b.errs, err) - } - case *MultilineError: - b.add(&err.nestedError) - default: - b.errs = append(b.errs, err) - } -} diff --git a/internal/gperr/builder_test.go b/internal/gperr/builder_test.go deleted file mode 100644 index 8413dcf6..00000000 --- a/internal/gperr/builder_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package gperr_test - -import ( - "context" - "errors" - "io" - "testing" - - . "github.com/yusing/godoxy/internal/gperr" - . "github.com/yusing/godoxy/internal/utils/testing" -) - -func TestBuilderEmpty(t *testing.T) { - eb := NewBuilder("foo") - ExpectTrue(t, errors.Is(eb.Error(), nil)) - ExpectFalse(t, eb.HasError()) -} - -func TestBuilderAddNil(t *testing.T) { - eb := NewBuilder("foo") - var err Error - for range 3 { - eb.Add(nil) - } - for range 3 { - eb.Add(err) - } - eb.AddRange(nil, nil, err) - ExpectFalse(t, eb.HasError()) - ExpectTrue(t, eb.Error() == nil) -} - -func TestBuilderIs(t *testing.T) { - eb := NewBuilder("foo") - eb.Add(context.Canceled) - eb.Add(io.ErrShortBuffer) - ExpectTrue(t, eb.HasError()) - ExpectError(t, io.ErrShortBuffer, eb.Error()) - ExpectError(t, context.Canceled, eb.Error()) -} - -func TestBuilderNested(t *testing.T) { - eb := NewBuilder("action failed") - eb.Add(New("Action 1").Withf("Inner: 1").Withf("Inner: 2")) - eb.Add(New("Action 2").Withf("Inner: 3")) - - got := eb.String() - expected := `action failed - • Action 1 - • Inner: 1 - • Inner: 2 - • Action 2 - • Inner: 3 -` - ExpectEqual(t, got, expected) -} diff --git a/internal/gperr/error.go b/internal/gperr/error.go deleted file mode 100644 index df94c925..00000000 --- a/internal/gperr/error.go +++ /dev/null @@ -1,43 +0,0 @@ -package gperr - -type Error interface { - error - - // Is is a wrapper for errors.Is when there is no sub-error. - // - // When there are sub-errors, they will also be checked. - Is(other error) bool - // With appends a sub-error to the error. - With(extra error) Error - // Withf is a wrapper for With(fmt.Errorf(format, args...)). - Withf(format string, args ...any) Error - // Subject prepends the given subject with a colon and space to the error message. - // - // If there is already a subject in the error message, the subject will be - // prepended to the existing subject with " > ". - // - // Subject empty string is ignored. - Subject(subject string) Error - // Subjectf is a wrapper for Subject(fmt.Sprintf(format, args...)). - Subjectf(format string, args ...any) Error - PlainError - MarkdownError -} - -type PlainError interface { - Plain() []byte -} - -type MarkdownError interface { - Markdown() []byte -} - -// this makes JSON marshaling work, -// as the builtin one doesn't. -// -//nolint:errname -type errStr string - -func (err errStr) Error() string { - return string(err) -} diff --git a/internal/gperr/error_test.go b/internal/gperr/error_test.go deleted file mode 100644 index f0919324..00000000 --- a/internal/gperr/error_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package gperr - -import ( - "errors" - "strings" - "testing" - - expect "github.com/yusing/godoxy/internal/utils/testing" - "github.com/yusing/goutils/strings/ansi" -) - -func TestBaseString(t *testing.T) { - expect.Equal(t, New("error").Error(), "error") -} - -func TestBaseWithSubject(t *testing.T) { - err := New("error") - withSubject := err.Subject("foo") - withSubjectf := err.Subjectf("%s %s", "foo", "bar") - - expect.ErrorIs(t, err, withSubject) - expect.Equal(t, ansi.StripANSI(withSubject.Error()), "foo: error") - expect.True(t, withSubject.Is(err)) - - expect.ErrorIs(t, err, withSubjectf) - expect.Equal(t, ansi.StripANSI(withSubjectf.Error()), "foo bar: error") - expect.True(t, withSubjectf.Is(err)) -} - -func TestBaseWithExtra(t *testing.T) { - err := New("error") - extra := New("bar").Subject("baz") - withExtra := err.With(extra) - - expect.True(t, withExtra.Is(extra)) - expect.True(t, withExtra.Is(err)) - - expect.True(t, errors.Is(withExtra, extra)) - expect.True(t, errors.Is(withExtra, err)) - - expect.True(t, strings.Contains(withExtra.Error(), err.Error())) - expect.True(t, strings.Contains(withExtra.Error(), extra.Error())) - expect.True(t, strings.Contains(withExtra.Error(), "baz")) -} - -func TestBaseUnwrap(t *testing.T) { - err := errors.New("err") - wrapped := Wrap(err) - - expect.ErrorIs(t, err, errors.Unwrap(wrapped)) -} - -func TestNestedUnwrap(t *testing.T) { - err := errors.New("err") - err2 := New("err2") - wrapped := Wrap(err).Subject("foo").With(err2.Subject("bar")) - - unwrapper, ok := wrapped.(interface{ Unwrap() []error }) - expect.True(t, ok) - - expect.ErrorIs(t, err, wrapped) - expect.ErrorIs(t, err2, wrapped) - expect.Equal(t, len(unwrapper.Unwrap()), 2) -} - -func TestErrorIs(t *testing.T) { - from := errors.New("error") - err := Wrap(from) - expect.ErrorIs(t, from, err) - - expect.True(t, err.Is(from)) - expect.False(t, err.Is(New("error"))) - - expect.True(t, errors.Is(err.Subject("foo"), from)) - expect.True(t, errors.Is(err.Withf("foo"), from)) - expect.True(t, errors.Is(err.Subject("foo").Withf("bar"), from)) -} - -func TestErrorImmutability(t *testing.T) { - err := New("err") - err2 := New("err2") - - for range 3 { - // t.Logf("%d: %v %T %s", i, errors.Unwrap(err), err, err) - _ = err.Subject("foo") - expect.False(t, strings.Contains(err.Error(), "foo")) - - _ = err.With(err2) - expect.False(t, strings.Contains(err.Error(), "extra")) - expect.False(t, err.Is(err2)) - - err = err.Subject("bar").Withf("baz") - expect.True(t, err != nil) - } -} - -func TestErrorWith(t *testing.T) { - err1 := New("err1") - err2 := New("err2") - - err3 := err1.With(err2) - - expect.True(t, err3.Is(err1)) - expect.True(t, err3.Is(err2)) - - _ = err2.Subject("foo") - - expect.True(t, err3.Is(err1)) - expect.True(t, err3.Is(err2)) - - // check if err3 is affected by err2.Subject - expect.False(t, strings.Contains(err3.Error(), "foo")) -} - -func TestErrorStringSimple(t *testing.T) { - errFailure := New("generic failure") - ne := errFailure.Subject("foo bar") - expect.Equal(t, ansi.StripANSI(ne.Error()), "foo bar: generic failure") - ne = ne.Subject("baz") - expect.Equal(t, ansi.StripANSI(ne.Error()), "baz > foo bar: generic failure") -} - -func TestErrorStringNested(t *testing.T) { - errFailure := New("generic failure") - inner := errFailure.Subject("inner"). - Withf("1"). - Withf("1") - inner2 := errFailure.Subject("inner2"). - Subject("action 2"). - Withf("2"). - Withf("2") - inner3 := errFailure.Subject("inner3"). - Subject("action 3"). - Withf("3"). - Withf("3") - ne := errFailure. - Subject("foo"). - Withf("bar"). - Withf("baz"). - With(inner). - With(inner.With(inner2.With(inner3))) - want := `foo: generic failure - • bar - • baz - • inner: generic failure - • 1 - • 1 - • inner: generic failure - • 1 - • 1 - • action 2 > inner2: generic failure - • 2 - • 2 - • action 3 > inner3: generic failure - • 3 - • 3 -` - expect.Equal(t, ansi.StripANSI(ne.Error()), want) -} diff --git a/internal/gperr/hint.go b/internal/gperr/hint.go deleted file mode 100644 index ddc59279..00000000 --- a/internal/gperr/hint.go +++ /dev/null @@ -1,43 +0,0 @@ -package gperr - -import "github.com/yusing/goutils/strings/ansi" - -type Hint struct { - Prefix string - Message string - Suffix string -} - -var _ PlainError = (*Hint)(nil) -var _ MarkdownError = (*Hint)(nil) - -func (h *Hint) Error() string { - return h.Prefix + ansi.Info(h.Message) + h.Suffix -} - -func (h *Hint) Plain() []byte { - return []byte(h.Prefix + h.Message + h.Suffix) -} - -func (h *Hint) Markdown() []byte { - return []byte(h.Prefix + "**" + h.Message + "**" + h.Suffix) -} - -func (h *Hint) MarshalText() ([]byte, error) { - return h.Plain(), nil -} - -func (h *Hint) String() string { - return h.Error() -} - -func DoYouMean(s string) error { - if s == "" { - return nil - } - return &Hint{ - Prefix: "Do you mean ", - Message: s, - Suffix: "?", - } -} diff --git a/internal/gperr/log.go b/internal/gperr/log.go deleted file mode 100644 index 1ace50ab..00000000 --- a/internal/gperr/log.go +++ /dev/null @@ -1,48 +0,0 @@ -package gperr - -import ( - "os" - - "github.com/rs/zerolog" - zerologlog "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/common" -) - -func log(msg string, err error, level zerolog.Level, logger ...*zerolog.Logger) { - var l *zerolog.Logger - if len(logger) > 0 { - l = logger[0] - } else { - l = &zerologlog.Logger - } - l.WithLevel(level).Msg(New(highlightANSI(msg)).With(err).Error()) - switch level { - case zerolog.FatalLevel: - os.Exit(1) - case zerolog.PanicLevel: - panic(err) - } -} - -func LogFatal(msg string, err error, logger ...*zerolog.Logger) { - if common.IsDebug { - LogPanic(msg, err, logger...) - } - log(msg, err, zerolog.FatalLevel, logger...) -} - -func LogError(msg string, err error, logger ...*zerolog.Logger) { - log(msg, err, zerolog.ErrorLevel, logger...) -} - -func LogWarn(msg string, err error, logger ...*zerolog.Logger) { - log(msg, err, zerolog.WarnLevel, logger...) -} - -func LogPanic(msg string, err error, logger ...*zerolog.Logger) { - log(msg, err, zerolog.PanicLevel, logger...) -} - -func LogDebug(msg string, err error, logger ...*zerolog.Logger) { - log(msg, err, zerolog.DebugLevel, logger...) -} diff --git a/internal/gperr/multiline.go b/internal/gperr/multiline.go deleted file mode 100644 index 35dfc973..00000000 --- a/internal/gperr/multiline.go +++ /dev/null @@ -1,55 +0,0 @@ -package gperr - -import ( - "fmt" - "reflect" -) - -type MultilineError struct { - nestedError -} - -func Multiline() *MultilineError { - return &MultilineError{} -} - -func (m *MultilineError) add(err error) { - if err == nil { - return - } - m.Extras = append(m.Extras, err) -} - -func (m *MultilineError) Addf(format string, args ...any) *MultilineError { - m.add(fmt.Errorf(format, args...)) - return m -} - -func (m *MultilineError) Adds(s string) *MultilineError { - m.add(newError(s)) - return m -} - -func (m *MultilineError) AddLines(lines ...any) *MultilineError { - v := reflect.ValueOf(lines) - if v.Kind() == reflect.Slice { - for i := range v.Len() { - switch v := v.Index(i).Interface().(type) { - case string: - m.add(newError(v)) - case error: - m.add(v) - default: - m.add(fmt.Errorf("%v", v)) - } - } - } - return m -} - -func (m *MultilineError) AddLinesString(lines ...string) *MultilineError { - for _, line := range lines { - m.add(newError(line)) - } - return m -} diff --git a/internal/gperr/multiline_test.go b/internal/gperr/multiline_test.go deleted file mode 100644 index c277a22f..00000000 --- a/internal/gperr/multiline_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package gperr - -import ( - "net" - "testing" - - expect "github.com/yusing/godoxy/internal/utils/testing" -) - -func TestWrapMultiline(t *testing.T) { - multiline := Multiline() - var wrapper error = wrap(multiline) - _, ok := wrapper.(*MultilineError) - if !ok { - t.Errorf("wrapper is not a MultilineError") - } -} - -func TestPrependSubjectMultiline(t *testing.T) { - multiline := Multiline() - multiline.Addf("line 1 %s", "test") - multiline.Adds("line 2") - multiline.AddLines([]any{1, "2", 3.0, net.IPv4(127, 0, 0, 1)}) - multiline.Subject("subject") - - builder := NewBuilder() - builder.Add(multiline) - expect.Equal(t, len(multiline.Extras), len(builder.errs)) -} diff --git a/internal/gperr/nested_error.go b/internal/gperr/nested_error.go deleted file mode 100644 index 888f3502..00000000 --- a/internal/gperr/nested_error.go +++ /dev/null @@ -1,152 +0,0 @@ -package gperr - -import ( - "errors" - "fmt" -) - -//nolint:recvcheck -type nestedError struct { - Err error `json:"err"` - Extras []error `json:"extras"` -} - -var emptyError = errStr("") - -func (err nestedError) Subject(subject string) Error { - if err.Err == nil { - err.Err = PrependSubject(subject, emptyError) - } else { - err.Err = PrependSubject(subject, err.Err) - } - return &err -} - -func (err *nestedError) Subjectf(format string, args ...any) Error { - if len(args) > 0 { - return err.Subject(fmt.Sprintf(format, args...)) - } - return err.Subject(format) -} - -func (err nestedError) With(extra error) Error { - if extra != nil { - err.Extras = append(err.Extras, extra) - } - return &err -} - -func (err nestedError) Withf(format string, args ...any) Error { - if len(args) > 0 { - err.Extras = append(err.Extras, fmt.Errorf(format, args...)) - } else { - err.Extras = append(err.Extras, newError(format)) - } - return &err -} - -func (err *nestedError) Unwrap() []error { - if err.Err == nil { - if len(err.Extras) == 0 { - return nil - } - return err.Extras - } - return append([]error{err.Err}, err.Extras...) -} - -func (err *nestedError) Is(other error) bool { - if errors.Is(err.Err, other) { - return true - } - for _, e := range err.Extras { - if errors.Is(e, other) { - return true - } - } - return false -} - -var nilError = newError("") -var bulletPrefix = []byte("• ") -var markdownBulletPrefix = []byte("- ") -var spaces = []byte(" ") - -type appendLineFunc func(buf []byte, err error, level int) []byte - -func (err *nestedError) fmtError(appendLine appendLineFunc) []byte { - if err == nil { - return appendLine(nil, nilError, 0) - } - if err.Err != nil { - buf := appendLine(nil, err.Err, 0) - if len(err.Extras) > 0 { - buf = append(buf, '\n') - buf = appendLines(buf, err.Extras, 1, appendLine) - } - return buf - } - return appendLines(nil, err.Extras, 0, appendLine) -} - -func (err *nestedError) Error() string { - return string(err.fmtError(appendLineNormal)) -} - -func (err *nestedError) Plain() []byte { - return err.fmtError(appendLinePlain) -} - -func (err *nestedError) Markdown() []byte { - return err.fmtError(appendLineMd) -} - -func appendLine(buf []byte, err error, level int, prefix []byte, format func(err error) []byte) []byte { - if err == nil { - return appendLine(buf, nilError, level, prefix, format) - } - if level == 0 { - return append(buf, format(err)...) - } - buf = append(buf, spaces[:2*level]...) - buf = append(buf, prefix...) - buf = append(buf, format(err)...) - return buf -} - -func appendLineNormal(buf []byte, err error, level int) []byte { - return appendLine(buf, err, level, bulletPrefix, Normal) -} - -func appendLinePlain(buf []byte, err error, level int) []byte { - return appendLine(buf, err, level, bulletPrefix, Plain) -} - -func appendLineMd(buf []byte, err error, level int) []byte { - return appendLine(buf, err, level, markdownBulletPrefix, Markdown) -} - -func appendLines(buf []byte, errs []error, level int, appendLine appendLineFunc) []byte { - if len(errs) == 0 { - return buf - } - for _, err := range errs { - switch err := wrap(err).(type) { - case *nestedError: - if err.Err != nil { - buf = appendLine(buf, err.Err, level) - buf = append(buf, '\n') - buf = appendLines(buf, err.Extras, level+1, appendLine) - } else { - buf = appendLines(buf, err.Extras, level, appendLine) - } - default: - if err == nil { - continue - } - buf = appendLine(buf, err, level) - buf = append(buf, '\n') - } - } - return buf -} diff --git a/internal/gperr/subject.go b/internal/gperr/subject.go deleted file mode 100644 index 088be5f6..00000000 --- a/internal/gperr/subject.go +++ /dev/null @@ -1,144 +0,0 @@ -package gperr - -import ( - "bytes" - "encoding/json" - "errors" - "slices" - - "github.com/yusing/goutils/strings/ansi" -) - -//nolint:errname -type withSubject struct { - Subjects []string - Err error - - pendingSubject string -} - -const subjectSep = " > " - -type highlightFunc func(subject string) string - -var _ PlainError = (*withSubject)(nil) -var _ MarkdownError = (*withSubject)(nil) - -func highlightANSI(subject string) string { - return ansi.HighlightRed + subject + ansi.Reset -} - -func highlightMarkdown(subject string) string { - return "**" + subject + "**" -} - -func noHighlight(subject string) string { - return subject -} - -func PrependSubject(subject string, err error) error { - if err == nil { - return nil - } - - //nolint:errorlint - switch err := err.(type) { - case *withSubject: - return err.Prepend(subject) - case *wrappedError: - return &wrappedError{ - Err: PrependSubject(subject, err.Err), - Message: err.Message, - } - case Error: - return err.Subject(subject) - } - return &withSubject{[]string{subject}, err, ""} -} - -func (err *withSubject) Prepend(subject string) *withSubject { - if subject == "" { - return err - } - - clone := *err - switch subject[0] { - case '[', '(', '{': - // since prepend is called in depth-first order, - // the subject of the index is not yet seen - // add it when the next subject is seen - clone.pendingSubject += subject - default: - clone.Subjects = append(clone.Subjects, subject) - if clone.pendingSubject != "" { - clone.Subjects[len(clone.Subjects)-1] = subject + clone.pendingSubject - clone.pendingSubject = "" - } - } - return &clone -} - -func (err *withSubject) Is(other error) bool { - return errors.Is(other, err.Err) -} - -func (err *withSubject) Unwrap() error { - return err.Err -} - -func (err *withSubject) Error() string { - return string(err.fmtError(highlightANSI)) -} - -func (err *withSubject) Plain() []byte { - return err.fmtError(noHighlight) -} - -func (err *withSubject) Markdown() []byte { - return err.fmtError(highlightMarkdown) -} - -func (err *withSubject) fmtError(highlight highlightFunc) []byte { - // subject is in reversed order - size := 0 - errStr := err.Err.Error() - subjects := err.Subjects - if err.pendingSubject != "" { - subjects = append(subjects, err.pendingSubject) - } - var buf bytes.Buffer - for _, s := range subjects { - size += len(s) - } - n := len(subjects) - buf.Grow(size + 2 + n*len(subjectSep) + len(errStr) + len(highlight(""))) - - for i := n - 1; i > 0; i-- { - buf.WriteString(subjects[i]) - buf.WriteString(subjectSep) - } - buf.WriteString(highlight(subjects[0])) - if errStr != "" { - buf.WriteString(": ") - buf.WriteString(errStr) - } - return buf.Bytes() -} - -// MarshalJSON implements the json.Marshaler interface. -func (err *withSubject) MarshalJSON() ([]byte, error) { - subjects := slices.Clone(err.Subjects) - slices.Reverse(subjects) - reversed := struct { - Subjects []string `json:"subjects"` - Err error `json:"err"` - }{ - Subjects: subjects, - Err: err.Err, - } - if err.pendingSubject != "" { - reversed.Subjects = append(reversed.Subjects, err.pendingSubject) - } - - return json.Marshal(reversed) -} diff --git a/internal/gperr/utils.go b/internal/gperr/utils.go deleted file mode 100644 index b39127b9..00000000 --- a/internal/gperr/utils.go +++ /dev/null @@ -1,133 +0,0 @@ -package gperr - -import ( - "fmt" -) - -func newError(message string) error { - return errStr(message) -} - -func New(message string) Error { - if message == "" { - return nil - } - return &baseError{newError(message)} -} - -func Errorf(format string, args ...any) Error { - return &baseError{fmt.Errorf(format, args...)} -} - -// Wrap wraps message in front of the error message. -func Wrap(err error, message ...string) Error { - if err == nil { - return nil - } - if len(message) == 0 || message[0] == "" { - return wrap(err) - } - //nolint:errorlint - switch err := err.(type) { - case *baseError: - err.Err = &wrappedError{err.Err, message[0]} - return err - case *nestedError: - err.Err = &wrappedError{err.Err, message[0]} - return err - } - return &baseError{&wrappedError{err, message[0]}} -} - -func Unwrap(err error) Error { - //nolint:errorlint - switch err := err.(type) { - case interface{ Unwrap() []error }: - return &nestedError{Extras: err.Unwrap()} - case interface{ Unwrap() error }: - return &baseError{err.Unwrap()} - default: - return &baseError{err} - } -} - -func wrap(err error) Error { - if err == nil { - return nil - } - //nolint:errorlint - switch err := err.(type) { - case Error: - return err - } - return &baseError{err} -} - -func Join(errors ...error) Error { - n := 0 - for _, err := range errors { - if err != nil { - n++ - } - } - if n == 0 { - return nil - } - errs := make([]error, n) - i := 0 - for _, err := range errors { - if err != nil { - errs[i] = err - i++ - } - } - return &nestedError{Extras: errs} -} - -func JoinLines(main error, errors ...string) Error { - errs := make([]error, len(errors)) - for i, err := range errors { - if err == "" { - continue - } - errs[i] = newError(err) - } - return &nestedError{Err: main, Extras: errs} -} - -func Collect[T any, Err error, Arg any, Func func(Arg) (T, Err)](eb *Builder, fn Func, arg Arg) T { - result, err := fn(arg) - eb.Add(err) - return result -} - -func Normal(err error) []byte { - if err == nil { - return nil - } - return []byte(err.Error()) -} - -func Plain(err error) []byte { - if err == nil { - return nil - } - if p, ok := err.(PlainError); ok { - return p.Plain() - } - return []byte(err.Error()) -} - -func Markdown(err error) []byte { - if err == nil { - return nil - } - switch err := err.(type) { - case MarkdownError: - return err.Markdown() - case interface{ Unwrap() []error }: - return appendLines(nil, err.Unwrap(), 0, appendLineMd) - default: - return []byte(err.Error()) - } -} diff --git a/internal/gperr/utils_test.go b/internal/gperr/utils_test.go deleted file mode 100644 index b7bab9c3..00000000 --- a/internal/gperr/utils_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package gperr - -import ( - "testing" -) - -type testErr struct{} - -func (e testErr) Error() string { - return "test error" -} - -func (e testErr) Plain() []byte { - return []byte("test error") -} - -func (e testErr) Markdown() []byte { - return []byte("**test error**") -} - -type testMultiErr struct { - errors []error -} - -func (e testMultiErr) Error() string { - return Join(e.errors...).Error() -} - -func (e testMultiErr) Unwrap() []error { - return e.errors -} - -func TestFormatting(t *testing.T) { - err := testErr{} - plain := Plain(err) - if string(plain) != "test error" { - t.Errorf("expected test error, got %s", string(plain)) - } - md := Markdown(err) - if string(md) != "**test error**" { - t.Errorf("expected test error, got %s", string(md)) - } -} - -func TestMultiError(t *testing.T) { - err := testMultiErr{[]error{testErr{}, testErr{}}} - plain := Plain(err) - if string(plain) != "test error\ntest error\n" { - t.Errorf("expected test error, got %s", string(plain)) - } - md := Markdown(err) - if string(md) != "**test error**\n**test error**\n" { - t.Errorf("expected test error, got %s", string(md)) - } -} diff --git a/internal/gperr/wrapped.go b/internal/gperr/wrapped.go deleted file mode 100644 index 810d54ac..00000000 --- a/internal/gperr/wrapped.go +++ /dev/null @@ -1,34 +0,0 @@ -package gperr - -import ( - "errors" - "fmt" -) - -type wrappedError struct { - Err error - Message string -} - -var _ PlainError = (*wrappedError)(nil) -var _ MarkdownError = (*wrappedError)(nil) - -func (e *wrappedError) Error() string { - return fmt.Sprintf("%s: %s", e.Message, e.Err.Error()) -} - -func (e *wrappedError) Plain() []byte { - return fmt.Appendf(nil, "%s: %s", e.Message, e.Err.Error()) -} - -func (e *wrappedError) Markdown() []byte { - return fmt.Appendf(nil, "**%s**: %s", e.Message, e.Err.Error()) -} - -func (e *wrappedError) Unwrap() error { - return e.Err -} - -func (e *wrappedError) Is(target error) bool { - return errors.Is(e.Err, target) -} diff --git a/internal/homepage/homepage_test.go b/internal/homepage/homepage_test.go index 6bf6c1d2..482c7370 100644 --- a/internal/homepage/homepage_test.go +++ b/internal/homepage/homepage_test.go @@ -4,7 +4,8 @@ import ( "testing" . "github.com/yusing/godoxy/internal/homepage" - . "github.com/yusing/godoxy/internal/utils/testing" + + expect "github.com/yusing/goutils/testing" ) func TestOverrideItem(t *testing.T) { @@ -33,7 +34,7 @@ func TestOverrideItem(t *testing.T) { overrides.Initialize() overrides.OverrideItem(a.Alias, want) got := a.GetOverride() - ExpectEqual(t, got, Item{ + expect.Equal(t, got, Item{ ItemConfig: want, Alias: a.Alias, }) @@ -58,8 +59,8 @@ func TestOverrideItem_PreservesURL(t *testing.T) { overrides.OverrideItem(a.Alias, wantCfg) got := a.GetOverride() - ExpectEqual(t, got.URL, "http://origin.local") - ExpectEqual(t, got.Name, "Overridden") + expect.Equal(t, got.URL, "http://origin.local") + expect.Equal(t, got.Name, "Overridden") } func TestVisibilityFavoriteAndSortOrders(t *testing.T) { @@ -81,11 +82,11 @@ func TestVisibilityFavoriteAndSortOrders(t *testing.T) { overrides.SetFavSortOrder(a.Alias, 2) got := a.GetOverride() - ExpectEqual(t, got.Show, false) - ExpectEqual(t, got.Favorite, true) - ExpectEqual(t, got.SortOrder, 5) - ExpectEqual(t, got.AllSortOrder, 9) - ExpectEqual(t, got.FavSortOrder, 2) + expect.Equal(t, got.Show, false) + expect.Equal(t, got.Favorite, true) + expect.Equal(t, got.SortOrder, 5) + expect.Equal(t, got.AllSortOrder, 9) + expect.Equal(t, got.FavSortOrder, 2) } func TestCategoryDefaultedWhenEmpty(t *testing.T) { @@ -97,7 +98,7 @@ func TestCategoryDefaultedWhenEmpty(t *testing.T) { }, } got := a.GetOverride() - ExpectEqual(t, got.Category, CategoryOthers) + expect.Equal(t, got.Category, CategoryOthers) } func TestOverrideItems_Bulk(t *testing.T) { @@ -128,9 +129,9 @@ func TestOverrideItems_Bulk(t *testing.T) { ga := a.GetOverride() gb := b.GetOverride() - ExpectEqual(t, ga.Name, "A*") - ExpectEqual(t, ga.Category, "AX") - ExpectEqual(t, gb.Name, "B*") - ExpectEqual(t, gb.Category, "BY") - ExpectEqual(t, gb.Show, false) + expect.Equal(t, ga.Name, "A*") + expect.Equal(t, ga.Category, "AX") + expect.Equal(t, gb.Name, "B*") + expect.Equal(t, gb.Category, "BY") + expect.Equal(t, gb.Show, false) } diff --git a/internal/homepage/icon_cache.go b/internal/homepage/icon_cache.go index 78414e0a..838f350b 100644 --- a/internal/homepage/icon_cache.go +++ b/internal/homepage/icon_cache.go @@ -9,9 +9,9 @@ import ( "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" "github.com/yusing/godoxy/internal/jsonstore" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/utils" "github.com/yusing/godoxy/internal/utils/atomic" + "github.com/yusing/goutils/task" ) type cacheEntry struct { diff --git a/internal/homepage/icon_url.go b/internal/homepage/icon_url.go index 9ee07e33..b07463df 100644 --- a/internal/homepage/icon_url.go +++ b/internal/homepage/icon_url.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/homepage/icon_url_test.go b/internal/homepage/icon_url_test.go index 944da27c..3ba4b8a7 100644 --- a/internal/homepage/icon_url_test.go +++ b/internal/homepage/icon_url_test.go @@ -4,7 +4,7 @@ import ( "testing" . "github.com/yusing/godoxy/internal/homepage" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func strPtr(s string) *string { diff --git a/internal/homepage/integrations/qbittorrent/client.go b/internal/homepage/integrations/qbittorrent/client.go index fd973aa7..3b225ee0 100644 --- a/internal/homepage/integrations/qbittorrent/client.go +++ b/internal/homepage/integrations/qbittorrent/client.go @@ -7,8 +7,8 @@ import ( "net/http" "net/url" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/homepage/widgets" + gperr "github.com/yusing/goutils/errs" ) type Client struct { diff --git a/internal/homepage/list_icons.go b/internal/homepage/list_icons.go index f3cc0819..ddb12b4c 100644 --- a/internal/homepage/list_icons.go +++ b/internal/homepage/list_icons.go @@ -15,8 +15,8 @@ import ( "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" "github.com/yusing/godoxy/internal/serialization" - "github.com/yusing/godoxy/internal/task" strutils "github.com/yusing/goutils/strings" + "github.com/yusing/goutils/task" ) type ( diff --git a/internal/homepage/widgets/http.go b/internal/homepage/widgets/http.go index 4655eec0..f4b71982 100644 --- a/internal/homepage/widgets/http.go +++ b/internal/homepage/widgets/http.go @@ -4,7 +4,7 @@ import ( "net/http" "time" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) var HTTPClient = &http.Client{ diff --git a/internal/homepage/widgets/widgets.go b/internal/homepage/widgets/widgets.go index 6ff24268..5ee440ea 100644 --- a/internal/homepage/widgets/widgets.go +++ b/internal/homepage/widgets/widgets.go @@ -3,8 +3,8 @@ package widgets import ( "context" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/serialization" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/idlewatcher/health.go b/internal/idlewatcher/health.go index 73e67f2e..49a7bab4 100644 --- a/internal/idlewatcher/health.go +++ b/internal/idlewatcher/health.go @@ -3,10 +3,10 @@ package idlewatcher import ( "time" - "github.com/yusing/godoxy/internal/gperr" idlewatcher "github.com/yusing/godoxy/internal/idlewatcher/types" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) // Start implements health.HealthMonitor. diff --git a/internal/idlewatcher/provider/docker.go b/internal/idlewatcher/provider/docker.go index 8302627f..51ab7ee3 100644 --- a/internal/idlewatcher/provider/docker.go +++ b/internal/idlewatcher/provider/docker.go @@ -5,10 +5,10 @@ import ( "github.com/docker/docker/api/types/container" "github.com/yusing/godoxy/internal/docker" - "github.com/yusing/godoxy/internal/gperr" idlewatcher "github.com/yusing/godoxy/internal/idlewatcher/types" "github.com/yusing/godoxy/internal/types" "github.com/yusing/godoxy/internal/watcher" + gperr "github.com/yusing/goutils/errs" ) type DockerProvider struct { diff --git a/internal/idlewatcher/provider/proxmox.go b/internal/idlewatcher/provider/proxmox.go index 8a0c24bb..b3ac35d2 100644 --- a/internal/idlewatcher/provider/proxmox.go +++ b/internal/idlewatcher/provider/proxmox.go @@ -5,12 +5,12 @@ import ( "strconv" "time" - "github.com/yusing/godoxy/internal/gperr" idlewatcher "github.com/yusing/godoxy/internal/idlewatcher/types" "github.com/yusing/godoxy/internal/proxmox" "github.com/yusing/godoxy/internal/types" "github.com/yusing/godoxy/internal/watcher" "github.com/yusing/godoxy/internal/watcher/events" + gperr "github.com/yusing/goutils/errs" ) type ProxmoxProvider struct { diff --git a/internal/idlewatcher/types/container_status.go b/internal/idlewatcher/types/container_status.go index d392aadf..c2f13b76 100644 --- a/internal/idlewatcher/types/container_status.go +++ b/internal/idlewatcher/types/container_status.go @@ -1,6 +1,6 @@ package idlewatcher -import "github.com/yusing/godoxy/internal/gperr" +import gperr "github.com/yusing/goutils/errs" type ContainerStatus string diff --git a/internal/idlewatcher/types/provider.go b/internal/idlewatcher/types/provider.go index 6ac12a1a..66af96a4 100644 --- a/internal/idlewatcher/types/provider.go +++ b/internal/idlewatcher/types/provider.go @@ -3,9 +3,9 @@ package idlewatcher import ( "context" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/types" "github.com/yusing/godoxy/internal/watcher/events" + gperr "github.com/yusing/goutils/errs" ) type Provider interface { diff --git a/internal/idlewatcher/watcher.go b/internal/idlewatcher/watcher.go index c73cbdb4..8adb3be3 100644 --- a/internal/idlewatcher/watcher.go +++ b/internal/idlewatcher/watcher.go @@ -12,18 +12,18 @@ import ( "github.com/rs/zerolog/log" "github.com/yusing/ds/ordered" "github.com/yusing/godoxy/internal/docker" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/idlewatcher/provider" idlewatcher "github.com/yusing/godoxy/internal/idlewatcher/types" nettypes "github.com/yusing/godoxy/internal/net/types" "github.com/yusing/godoxy/internal/route/routes" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" U "github.com/yusing/godoxy/internal/utils" "github.com/yusing/godoxy/internal/utils/atomic" "github.com/yusing/godoxy/internal/watcher/events" "github.com/yusing/godoxy/internal/watcher/health/monitor" + gperr "github.com/yusing/goutils/errs" "github.com/yusing/goutils/http/reverseproxy" + "github.com/yusing/goutils/task" "golang.org/x/sync/errgroup" "golang.org/x/sync/singleflight" ) diff --git a/internal/jsonstore/jsonstore.go b/internal/jsonstore/jsonstore.go index aaa2e6c7..d264cf6d 100644 --- a/internal/jsonstore/jsonstore.go +++ b/internal/jsonstore/jsonstore.go @@ -10,9 +10,9 @@ import ( "github.com/puzpuzpuz/xsync/v4" "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/serialization" - "github.com/yusing/godoxy/internal/task" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) type namespace string diff --git a/internal/logging/accesslog/access_logger.go b/internal/logging/accesslog/access_logger.go index 334a4607..f17b20e8 100644 --- a/internal/logging/accesslog/access_logger.go +++ b/internal/logging/accesslog/access_logger.go @@ -9,12 +9,12 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/gperr" maxmind "github.com/yusing/godoxy/internal/maxmind/types" - "github.com/yusing/godoxy/internal/task" + gperr "github.com/yusing/goutils/errs" ioutils "github.com/yusing/goutils/io" strutils "github.com/yusing/goutils/strings" "github.com/yusing/goutils/synk" + "github.com/yusing/goutils/task" "golang.org/x/time/rate" ) diff --git a/internal/logging/accesslog/access_logger_test.go b/internal/logging/accesslog/access_logger_test.go index 8b5c291c..eca91336 100644 --- a/internal/logging/accesslog/access_logger_test.go +++ b/internal/logging/accesslog/access_logger_test.go @@ -9,9 +9,9 @@ import ( "time" . "github.com/yusing/godoxy/internal/logging/accesslog" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/utils" - expect "github.com/yusing/godoxy/internal/utils/testing" + "github.com/yusing/goutils/task" + expect "github.com/yusing/goutils/testing" ) const ( diff --git a/internal/logging/accesslog/back_scanner_test.go b/internal/logging/accesslog/back_scanner_test.go index 08cab2fa..d06c5ffe 100644 --- a/internal/logging/accesslog/back_scanner_test.go +++ b/internal/logging/accesslog/back_scanner_test.go @@ -9,9 +9,10 @@ import ( "testing" "github.com/spf13/afero" - "github.com/yusing/godoxy/internal/task" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" + strutils "github.com/yusing/goutils/strings" + "github.com/yusing/goutils/task" ) func TestBackScanner(t *testing.T) { diff --git a/internal/logging/accesslog/config.go b/internal/logging/accesslog/config.go index a066aabb..eeb575af 100644 --- a/internal/logging/accesslog/config.go +++ b/internal/logging/accesslog/config.go @@ -3,8 +3,8 @@ package accesslog import ( "time" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/serialization" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/logging/accesslog/config_test.go b/internal/logging/accesslog/config_test.go index 0f5e00d8..33c7036c 100644 --- a/internal/logging/accesslog/config_test.go +++ b/internal/logging/accesslog/config_test.go @@ -6,7 +6,7 @@ import ( "github.com/yusing/godoxy/internal/docker" . "github.com/yusing/godoxy/internal/logging/accesslog" "github.com/yusing/godoxy/internal/serialization" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestNewConfig(t *testing.T) { diff --git a/internal/logging/accesslog/fields_test.go b/internal/logging/accesslog/fields_test.go index cef9a7c5..5d21bcd0 100644 --- a/internal/logging/accesslog/fields_test.go +++ b/internal/logging/accesslog/fields_test.go @@ -4,7 +4,7 @@ import ( "testing" . "github.com/yusing/godoxy/internal/logging/accesslog" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) // Cookie header should be removed, diff --git a/internal/logging/accesslog/file_logger_test.go b/internal/logging/accesslog/file_logger_test.go index 68c9a5eb..3d4d9781 100644 --- a/internal/logging/accesslog/file_logger_test.go +++ b/internal/logging/accesslog/file_logger_test.go @@ -6,9 +6,8 @@ import ( "sync" "testing" - expect "github.com/yusing/godoxy/internal/utils/testing" - - "github.com/yusing/godoxy/internal/task" + "github.com/yusing/goutils/task" + expect "github.com/yusing/goutils/testing" ) func TestConcurrentFileLoggersShareSameAccessLogIO(t *testing.T) { diff --git a/internal/logging/accesslog/filter.go b/internal/logging/accesslog/filter.go index 0659904b..03ba7bf6 100644 --- a/internal/logging/accesslog/filter.go +++ b/internal/logging/accesslog/filter.go @@ -5,8 +5,8 @@ import ( "net/http" "strings" - "github.com/yusing/godoxy/internal/gperr" nettypes "github.com/yusing/godoxy/internal/net/types" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" ) diff --git a/internal/logging/accesslog/filter_test.go b/internal/logging/accesslog/filter_test.go index 995ff895..35bbcae4 100644 --- a/internal/logging/accesslog/filter_test.go +++ b/internal/logging/accesslog/filter_test.go @@ -7,8 +7,8 @@ import ( . "github.com/yusing/godoxy/internal/logging/accesslog" nettypes "github.com/yusing/godoxy/internal/net/types" - expect "github.com/yusing/godoxy/internal/utils/testing" strutils "github.com/yusing/goutils/strings" + expect "github.com/yusing/goutils/testing" ) func TestStatusCodeFilter(t *testing.T) { diff --git a/internal/logging/accesslog/retention.go b/internal/logging/accesslog/retention.go index d5bd4e40..f941696d 100644 --- a/internal/logging/accesslog/retention.go +++ b/internal/logging/accesslog/retention.go @@ -4,7 +4,7 @@ import ( "fmt" "strconv" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" ) @@ -70,7 +70,7 @@ func (r *Retention) Parse(v string) (err error) { if !r.IsValid() { return ErrZeroValue } - return + return err } func (r *Retention) String() string { diff --git a/internal/logging/accesslog/retention_test.go b/internal/logging/accesslog/retention_test.go index cacabad8..2f1adbd6 100644 --- a/internal/logging/accesslog/retention_test.go +++ b/internal/logging/accesslog/retention_test.go @@ -4,7 +4,7 @@ import ( "testing" . "github.com/yusing/godoxy/internal/logging/accesslog" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestParseRetention(t *testing.T) { diff --git a/internal/logging/accesslog/rotate.go b/internal/logging/accesslog/rotate.go index d81d43f6..536e02ac 100644 --- a/internal/logging/accesslog/rotate.go +++ b/internal/logging/accesslog/rotate.go @@ -6,8 +6,8 @@ import ( "time" "github.com/rs/zerolog" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/utils" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" "github.com/yusing/goutils/synk" ) @@ -251,14 +251,14 @@ func rotateLogFileBySize(file supportRotate, config *Retention) (result *RotateR // otherwise it returns zero time. func ParseLogTime(line []byte) (t time.Time) { if len(line) == 0 { - return + return t } if timeStr := ExtractTime(line); timeStr != nil { t, _ = time.Parse(LogTimeFormat, string(timeStr)) // ignore error - return + return t } - return + return t } var timeJSON = []byte(`"time":"`) @@ -272,8 +272,8 @@ func ExtractTime(line []byte) []byte { switch line[0] { case '{': // JSON format if i := bytes.Index(line, timeJSON); i != -1 { - var jsonStart = i + len(`"time":"`) - var jsonEnd = i + len(`"time":"`) + len(LogTimeFormat) + jsonStart := i + len(`"time":"`) + jsonEnd := i + len(`"time":"`) + len(LogTimeFormat) if len(line) < jsonEnd { return nil } diff --git a/internal/logging/accesslog/rotate_test.go b/internal/logging/accesslog/rotate_test.go index f3c7bf04..e74e6567 100644 --- a/internal/logging/accesslog/rotate_test.go +++ b/internal/logging/accesslog/rotate_test.go @@ -7,10 +7,10 @@ import ( "time" . "github.com/yusing/godoxy/internal/logging/accesslog" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/utils" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" strutils "github.com/yusing/goutils/strings" + "github.com/yusing/goutils/task" ) var ( diff --git a/internal/logging/accesslog/status_code_range.go b/internal/logging/accesslog/status_code_range.go index 07ba7974..9c26d987 100644 --- a/internal/logging/accesslog/status_code_range.go +++ b/internal/logging/accesslog/status_code_range.go @@ -3,7 +3,7 @@ package accesslog import ( "strconv" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" ) diff --git a/internal/logging/memlogger/mem_logger.go b/internal/logging/memlogger/mem_logger.go index 6798312d..77f2d04d 100644 --- a/internal/logging/memlogger/mem_logger.go +++ b/internal/logging/memlogger/mem_logger.go @@ -61,11 +61,11 @@ func (m *memLogger) Write(p []byte) (n int, err error) { pos, err := m.writeBuf(p) if err != nil { // not logging the error here, it will cause Run to be called again = infinite loop - return + return n, err } m.notifyWS(pos, n) - return + return n, err } func (m *memLogger) ServeHTTP(c *gin.Context) { @@ -149,7 +149,7 @@ func (m *memLogger) writeBuf(b []byte) (pos int, err error) { defer m.Unlock() pos = m.Len() _, err = m.Buffer.Write(b) - return + return pos, err } func (m *memLogger) events() (logs <-chan []byte, cancel func()) { diff --git a/internal/maxmind/instance.go b/internal/maxmind/instance.go index 2848693a..056417c4 100644 --- a/internal/maxmind/instance.go +++ b/internal/maxmind/instance.go @@ -5,9 +5,9 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/notif" - "github.com/yusing/godoxy/internal/task" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) var instance *MaxMind diff --git a/internal/maxmind/maxmind.go b/internal/maxmind/maxmind.go index 63572239..e6ceb8fb 100644 --- a/internal/maxmind/maxmind.go +++ b/internal/maxmind/maxmind.go @@ -15,9 +15,9 @@ import ( "github.com/oschwald/maxminddb-golang" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" maxmind "github.com/yusing/godoxy/internal/maxmind/types" - "github.com/yusing/godoxy/internal/task" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) /* diff --git a/internal/maxmind/maxmind_test.go b/internal/maxmind/maxmind_test.go index 4d6acfc7..0c59675d 100644 --- a/internal/maxmind/maxmind_test.go +++ b/internal/maxmind/maxmind_test.go @@ -10,7 +10,7 @@ import ( "github.com/oschwald/maxminddb-golang" maxmind "github.com/yusing/godoxy/internal/maxmind/types" - "github.com/yusing/godoxy/internal/task" + "github.com/yusing/goutils/task" ) func testCfg() *MaxMind { diff --git a/internal/maxmind/types/config.go b/internal/maxmind/types/config.go index 15f44eac..4fa21987 100644 --- a/internal/maxmind/types/config.go +++ b/internal/maxmind/types/config.go @@ -3,7 +3,7 @@ package maxmind import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/metrics/period/poller.go b/internal/metrics/period/poller.go index e9fe4662..241085eb 100644 --- a/internal/metrics/period/poller.go +++ b/internal/metrics/period/poller.go @@ -11,9 +11,9 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/gperr" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/utils/atomic" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) type ( diff --git a/internal/metrics/systeminfo/system_info.go b/internal/metrics/systeminfo/system_info.go index ddc833a1..a489e7a4 100644 --- a/internal/metrics/systeminfo/system_info.go +++ b/internal/metrics/systeminfo/system_info.go @@ -16,8 +16,8 @@ import ( "github.com/shirou/gopsutil/v4/sensors" "github.com/shirou/gopsutil/v4/warning" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/metrics/period" + gperr "github.com/yusing/goutils/errs" ) // json tags are left for tests diff --git a/internal/metrics/systeminfo/system_info_test.go b/internal/metrics/systeminfo/system_info_test.go index 805150d3..d6bc1d4e 100644 --- a/internal/metrics/systeminfo/system_info_test.go +++ b/internal/metrics/systeminfo/system_info_test.go @@ -10,96 +10,98 @@ import ( "github.com/shirou/gopsutil/v4/mem" "github.com/shirou/gopsutil/v4/net" "github.com/shirou/gopsutil/v4/sensors" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) // Create test data -var cpuAvg = 45.67 -var testInfo = &SystemInfo{ - Timestamp: 123456, - CPUAverage: &cpuAvg, - Memory: &mem.VirtualMemoryStat{ - Total: 16000000000, - Available: 8000000000, - Used: 8000000000, - UsedPercent: 50.0, - }, - Disks: map[string]*disk.UsageStat{ - "sda": { - Path: "/", - Fstype: "ext4", - Total: 500000000000, - Free: 250000000000, - Used: 250000000000, +var ( + cpuAvg = 45.67 + testInfo = &SystemInfo{ + Timestamp: 123456, + CPUAverage: &cpuAvg, + Memory: &mem.VirtualMemoryStat{ + Total: 16000000000, + Available: 8000000000, + Used: 8000000000, UsedPercent: 50.0, }, - "nvme0n1": { - Path: "/", - Fstype: "zfs", - Total: 500000000000, - Free: 250000000000, - Used: 250000000000, - UsedPercent: 50.0, + Disks: map[string]*disk.UsageStat{ + "sda": { + Path: "/", + Fstype: "ext4", + Total: 500000000000, + Free: 250000000000, + Used: 250000000000, + UsedPercent: 50.0, + }, + "nvme0n1": { + Path: "/", + Fstype: "zfs", + Total: 500000000000, + Free: 250000000000, + Used: 250000000000, + UsedPercent: 50.0, + }, }, - }, - DisksIO: map[string]*disk.IOCountersStat{ - "media": { - Name: "media", - ReadBytes: 1000000, - WriteBytes: 2000000, - ReadSpeed: 100.5, - WriteSpeed: 200.5, - Iops: 1000, + DisksIO: map[string]*disk.IOCountersStat{ + "media": { + Name: "media", + ReadBytes: 1000000, + WriteBytes: 2000000, + ReadSpeed: 100.5, + WriteSpeed: 200.5, + Iops: 1000, + }, + "nvme0n1": { + Name: "nvme0n1", + ReadBytes: 1000000, + WriteBytes: 2000000, + ReadSpeed: 100.5, + WriteSpeed: 200.5, + Iops: 1000, + }, }, - "nvme0n1": { - Name: "nvme0n1", - ReadBytes: 1000000, - WriteBytes: 2000000, - ReadSpeed: 100.5, - WriteSpeed: 200.5, - Iops: 1000, + Network: &net.IOCountersStat{ + BytesSent: 5000000, + BytesRecv: 10000000, + UploadSpeed: 1024.5, + DownloadSpeed: 2048.5, }, - }, - Network: &net.IOCountersStat{ - BytesSent: 5000000, - BytesRecv: 10000000, - UploadSpeed: 1024.5, - DownloadSpeed: 2048.5, - }, - Sensors: []sensors.TemperatureStat{ - { - SensorKey: "cpu_temp", - Temperature: 30.0, - High: 40.0, - Critical: 50.0, + Sensors: []sensors.TemperatureStat{ + { + SensorKey: "cpu_temp", + Temperature: 30.0, + High: 40.0, + Critical: 50.0, + }, + { + SensorKey: "gpu_temp", + Temperature: 40.0, + High: 50.0, + Critical: 60.0, + }, }, - { - SensorKey: "gpu_temp", - Temperature: 40.0, - High: 50.0, - Critical: 60.0, - }, - }, -} + } +) func TestSystemInfo(t *testing.T) { // Test marshaling data, err := json.Marshal(testInfo) - ExpectNoError(t, err) + expect.NoError(t, err) // Test unmarshaling back var decoded SystemInfo err = json.Unmarshal(data, &decoded) - ExpectNoError(t, err) + expect.NoError(t, err) // Compare original and decoded - ExpectEqual(t, decoded.Timestamp, testInfo.Timestamp) - ExpectEqual(t, *decoded.CPUAverage, *testInfo.CPUAverage) - ExpectEqual(t, decoded.Memory, testInfo.Memory) - ExpectEqual(t, decoded.Disks, testInfo.Disks) - ExpectEqual(t, decoded.DisksIO, testInfo.DisksIO) - ExpectEqual(t, decoded.Network, testInfo.Network) - ExpectEqual(t, decoded.Sensors, testInfo.Sensors) + expect.Equal(t, decoded.Timestamp, testInfo.Timestamp) + expect.Equal(t, *decoded.CPUAverage, *testInfo.CPUAverage) + expect.Equal(t, decoded.Memory, testInfo.Memory) + expect.Equal(t, decoded.Disks, testInfo.Disks) + expect.Equal(t, decoded.DisksIO, testInfo.DisksIO) + expect.Equal(t, decoded.Network, testInfo.Network) + expect.Equal(t, decoded.Sensors, testInfo.Sensors) // Test nil fields nilInfo := &SystemInfo{ @@ -107,18 +109,18 @@ func TestSystemInfo(t *testing.T) { } data, err = json.Marshal(nilInfo) - ExpectNoError(t, err) + expect.NoError(t, err) var decodedNil SystemInfo err = json.Unmarshal(data, &decodedNil) - ExpectNoError(t, err) + expect.NoError(t, err) - ExpectEqual(t, decodedNil.Timestamp, nilInfo.Timestamp) - ExpectTrue(t, decodedNil.CPUAverage == nil) - ExpectTrue(t, decodedNil.Memory == nil) - ExpectTrue(t, decodedNil.Disks == nil) - ExpectTrue(t, decodedNil.Network == nil) - ExpectTrue(t, decodedNil.Sensors == nil) + expect.Equal(t, decodedNil.Timestamp, nilInfo.Timestamp) + expect.True(t, decodedNil.CPUAverage == nil) + expect.True(t, decodedNil.Memory == nil) + expect.True(t, decodedNil.Disks == nil) + expect.True(t, decodedNil.Network == nil) + expect.True(t, decodedNil.Sensors == nil) } func TestSerialize(t *testing.T) { @@ -130,15 +132,15 @@ func TestSerialize(t *testing.T) { t.Run(string(query), func(t *testing.T) { _, result := aggregate(entries, url.Values{"aggregate": []string{string(query)}}) s, err := result.MarshalJSON() - ExpectNoError(t, err) + expect.NoError(t, err) var v []map[string]any - ExpectNoError(t, json.Unmarshal(s, &v)) - ExpectEqual(t, len(v), len(result.Entries)) + expect.NoError(t, json.Unmarshal(s, &v)) + expect.Equal(t, len(v), len(result.Entries)) for i, m := range v { for k, v := range m { // some int64 values are converted to float64 on json.Unmarshal vv := reflect.ValueOf(result.Entries[i][k]) - ExpectEqual(t, reflect.ValueOf(v).Convert(vv.Type()).Interface(), vv.Interface()) + expect.Equal(t, reflect.ValueOf(v).Convert(vv.Type()).Interface(), vv.Interface()) } } }) diff --git a/internal/metrics/uptime/uptime.go b/internal/metrics/uptime/uptime.go index 03217b39..08793f95 100644 --- a/internal/metrics/uptime/uptime.go +++ b/internal/metrics/uptime/uptime.go @@ -4,9 +4,8 @@ import ( "context" "encoding/json" "net/url" - "time" - "slices" + "time" "github.com/lithammer/fuzzysearch/fuzzy" config "github.com/yusing/godoxy/internal/config/types" diff --git a/internal/net/gphttp/content_type_test.go b/internal/net/gphttp/content_type_test.go index 827c5d69..aa167ea2 100644 --- a/internal/net/gphttp/content_type_test.go +++ b/internal/net/gphttp/content_type_test.go @@ -4,38 +4,38 @@ import ( "net/http" "testing" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestContentTypes(t *testing.T) { - ExpectTrue(t, GetContentType(http.Header{"Content-Type": {"text/html"}}).IsHTML()) - ExpectTrue(t, GetContentType(http.Header{"Content-Type": {"text/html; charset=utf-8"}}).IsHTML()) - ExpectTrue(t, GetContentType(http.Header{"Content-Type": {"application/xhtml+xml"}}).IsHTML()) - ExpectFalse(t, GetContentType(http.Header{"Content-Type": {"text/plain"}}).IsHTML()) + expect.True(t, GetContentType(http.Header{"Content-Type": {"text/html"}}).IsHTML()) + expect.True(t, GetContentType(http.Header{"Content-Type": {"text/html; charset=utf-8"}}).IsHTML()) + expect.True(t, GetContentType(http.Header{"Content-Type": {"application/xhtml+xml"}}).IsHTML()) + expect.False(t, GetContentType(http.Header{"Content-Type": {"text/plain"}}).IsHTML()) - ExpectTrue(t, GetContentType(http.Header{"Content-Type": {"application/json"}}).IsJSON()) - ExpectTrue(t, GetContentType(http.Header{"Content-Type": {"application/json; charset=utf-8"}}).IsJSON()) - ExpectFalse(t, GetContentType(http.Header{"Content-Type": {"text/html"}}).IsJSON()) + expect.True(t, GetContentType(http.Header{"Content-Type": {"application/json"}}).IsJSON()) + expect.True(t, GetContentType(http.Header{"Content-Type": {"application/json; charset=utf-8"}}).IsJSON()) + expect.False(t, GetContentType(http.Header{"Content-Type": {"text/html"}}).IsJSON()) - ExpectTrue(t, GetContentType(http.Header{"Content-Type": {"text/plain"}}).IsPlainText()) - ExpectTrue(t, GetContentType(http.Header{"Content-Type": {"text/plain; charset=utf-8"}}).IsPlainText()) - ExpectFalse(t, GetContentType(http.Header{"Content-Type": {"text/html"}}).IsPlainText()) + expect.True(t, GetContentType(http.Header{"Content-Type": {"text/plain"}}).IsPlainText()) + expect.True(t, GetContentType(http.Header{"Content-Type": {"text/plain; charset=utf-8"}}).IsPlainText()) + expect.False(t, GetContentType(http.Header{"Content-Type": {"text/html"}}).IsPlainText()) } func TestAcceptContentTypes(t *testing.T) { - ExpectTrue(t, GetAccept(http.Header{"Accept": {"text/html", "text/plain"}}).AcceptPlainText()) - ExpectTrue(t, GetAccept(http.Header{"Accept": {"text/html", "text/plain; charset=utf-8"}}).AcceptPlainText()) - ExpectTrue(t, GetAccept(http.Header{"Accept": {"text/html", "text/plain"}}).AcceptHTML()) - ExpectTrue(t, GetAccept(http.Header{"Accept": {"application/json"}}).AcceptJSON()) - ExpectTrue(t, GetAccept(http.Header{"Accept": {"*/*"}}).AcceptPlainText()) - ExpectTrue(t, GetAccept(http.Header{"Accept": {"*/*"}}).AcceptHTML()) - ExpectTrue(t, GetAccept(http.Header{"Accept": {"*/*"}}).AcceptJSON()) - ExpectTrue(t, GetAccept(http.Header{"Accept": {"text/*"}}).AcceptPlainText()) - ExpectTrue(t, GetAccept(http.Header{"Accept": {"text/*"}}).AcceptHTML()) + expect.True(t, GetAccept(http.Header{"Accept": {"text/html", "text/plain"}}).AcceptPlainText()) + expect.True(t, GetAccept(http.Header{"Accept": {"text/html", "text/plain; charset=utf-8"}}).AcceptPlainText()) + expect.True(t, GetAccept(http.Header{"Accept": {"text/html", "text/plain"}}).AcceptHTML()) + expect.True(t, GetAccept(http.Header{"Accept": {"application/json"}}).AcceptJSON()) + expect.True(t, GetAccept(http.Header{"Accept": {"*/*"}}).AcceptPlainText()) + expect.True(t, GetAccept(http.Header{"Accept": {"*/*"}}).AcceptHTML()) + expect.True(t, GetAccept(http.Header{"Accept": {"*/*"}}).AcceptJSON()) + expect.True(t, GetAccept(http.Header{"Accept": {"text/*"}}).AcceptPlainText()) + expect.True(t, GetAccept(http.Header{"Accept": {"text/*"}}).AcceptHTML()) - ExpectFalse(t, GetAccept(http.Header{"Accept": {"text/plain"}}).AcceptHTML()) - ExpectFalse(t, GetAccept(http.Header{"Accept": {"text/plain; charset=utf-8"}}).AcceptHTML()) - ExpectFalse(t, GetAccept(http.Header{"Accept": {"text/html"}}).AcceptPlainText()) - ExpectFalse(t, GetAccept(http.Header{"Accept": {"text/html"}}).AcceptJSON()) - ExpectFalse(t, GetAccept(http.Header{"Accept": {"text/*"}}).AcceptJSON()) + expect.False(t, GetAccept(http.Header{"Accept": {"text/plain"}}).AcceptHTML()) + expect.False(t, GetAccept(http.Header{"Accept": {"text/plain; charset=utf-8"}}).AcceptHTML()) + expect.False(t, GetAccept(http.Header{"Accept": {"text/html"}}).AcceptPlainText()) + expect.False(t, GetAccept(http.Header{"Accept": {"text/html"}}).AcceptJSON()) + expect.False(t, GetAccept(http.Header{"Accept": {"text/*"}}).AcceptJSON()) } diff --git a/internal/net/gphttp/loadbalancer/ip_hash.go b/internal/net/gphttp/loadbalancer/ip_hash.go index a71f8e29..1abce638 100644 --- a/internal/net/gphttp/loadbalancer/ip_hash.go +++ b/internal/net/gphttp/loadbalancer/ip_hash.go @@ -6,9 +6,9 @@ import ( "net/http" "sync" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/net/gphttp/middleware" "github.com/yusing/godoxy/internal/types" + gperr "github.com/yusing/goutils/errs" ) type ipHash struct { diff --git a/internal/net/gphttp/loadbalancer/loadbalancer.go b/internal/net/gphttp/loadbalancer/loadbalancer.go index 7f67f743..14c87789 100644 --- a/internal/net/gphttp/loadbalancer/loadbalancer.go +++ b/internal/net/gphttp/loadbalancer/loadbalancer.go @@ -8,11 +8,11 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/gperr" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" "github.com/yusing/godoxy/internal/utils/pool" + gperr "github.com/yusing/goutils/errs" "github.com/yusing/goutils/http/httpheaders" + "github.com/yusing/goutils/task" ) // TODO: stats of each server. diff --git a/internal/net/gphttp/loadbalancer/loadbalancer_test.go b/internal/net/gphttp/loadbalancer/loadbalancer_test.go index dda958c6..430cd7c7 100644 --- a/internal/net/gphttp/loadbalancer/loadbalancer_test.go +++ b/internal/net/gphttp/loadbalancer/loadbalancer_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/yusing/godoxy/internal/types" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestRebalance(t *testing.T) { @@ -15,7 +15,7 @@ func TestRebalance(t *testing.T) { lb.AddServer(TestNewServer(0)) } lb.rebalance() - ExpectEqual(t, lb.sumWeight, maxWeight) + expect.Equal(t, lb.sumWeight, maxWeight) }) t.Run("less", func(t *testing.T) { lb := New(new(types.LoadBalancerConfig)) @@ -26,7 +26,7 @@ func TestRebalance(t *testing.T) { lb.AddServer(TestNewServer(float64(maxWeight) * .1)) lb.rebalance() // t.Logf("%s", U.Must(json.MarshalIndent(lb.pool, "", " "))) - ExpectEqual(t, lb.sumWeight, maxWeight) + expect.Equal(t, lb.sumWeight, maxWeight) }) t.Run("more", func(t *testing.T) { lb := New(new(types.LoadBalancerConfig)) @@ -39,6 +39,6 @@ func TestRebalance(t *testing.T) { lb.AddServer(TestNewServer(float64(maxWeight) * .1)) lb.rebalance() // t.Logf("%s", U.Must(json.MarshalIndent(lb.pool, "", " "))) - ExpectEqual(t, lb.sumWeight, maxWeight) + expect.Equal(t, lb.sumWeight, maxWeight) }) } diff --git a/internal/net/gphttp/middleware/bypass_test.go b/internal/net/gphttp/middleware/bypass_test.go index 98126767..c7131d77 100644 --- a/internal/net/gphttp/middleware/bypass_test.go +++ b/internal/net/gphttp/middleware/bypass_test.go @@ -14,9 +14,9 @@ import ( . "github.com/yusing/godoxy/internal/net/gphttp/middleware" "github.com/yusing/godoxy/internal/route" routeTypes "github.com/yusing/godoxy/internal/route/types" - "github.com/yusing/godoxy/internal/task" - expect "github.com/yusing/godoxy/internal/utils/testing" "github.com/yusing/goutils/http/reverseproxy" + "github.com/yusing/goutils/task" + expect "github.com/yusing/goutils/testing" ) func noOpHandler(w http.ResponseWriter, r *http.Request) {} diff --git a/internal/net/gphttp/middleware/captcha/hcaptcha.go b/internal/net/gphttp/middleware/captcha/hcaptcha.go index 1adc18b1..e6da96d8 100644 --- a/internal/net/gphttp/middleware/captcha/hcaptcha.go +++ b/internal/net/gphttp/middleware/captcha/hcaptcha.go @@ -12,7 +12,7 @@ import ( _ "embed" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type HcaptchaProvider struct { diff --git a/internal/net/gphttp/middleware/captcha/provider.go b/internal/net/gphttp/middleware/captcha/provider.go index de3f9970..e8c2d470 100644 --- a/internal/net/gphttp/middleware/captcha/provider.go +++ b/internal/net/gphttp/middleware/captcha/provider.go @@ -4,7 +4,7 @@ import ( "net/http" "time" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type Provider interface { @@ -16,6 +16,4 @@ type Provider interface { FormHTML() string } -var ( - ErrCaptchaVerificationFailed = gperr.New("captcha verification failed") -) +var ErrCaptchaVerificationFailed = gperr.New("captcha verification failed") diff --git a/internal/net/gphttp/middleware/cidr_whitelist_test.go b/internal/net/gphttp/middleware/cidr_whitelist_test.go index 8aef7c1f..9de55033 100644 --- a/internal/net/gphttp/middleware/cidr_whitelist_test.go +++ b/internal/net/gphttp/middleware/cidr_whitelist_test.go @@ -7,9 +7,9 @@ import ( "strings" "testing" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/serialization" - . "github.com/yusing/godoxy/internal/utils/testing" + gperr "github.com/yusing/goutils/errs" + expect "github.com/yusing/goutils/testing" ) //go:embed test_data/cidr_whitelist_test.yml @@ -23,32 +23,32 @@ func TestCIDRWhitelistValidation(t *testing.T) { "allow": []string{"192.168.2.100/32"}, "message": testMessage, }) - ExpectNoError(t, err) + expect.NoError(t, err) _, err = CIDRWhiteList.New(OptionsRaw{ "allow": []string{"192.168.2.100/32"}, "message": testMessage, "status": 403, }) - ExpectNoError(t, err) + expect.NoError(t, err) _, err = CIDRWhiteList.New(OptionsRaw{ "allow": []string{"192.168.2.100/32"}, "message": testMessage, "status_code": 403, }) - ExpectNoError(t, err) + expect.NoError(t, err) }) t.Run("missing allow", func(t *testing.T) { _, err := CIDRWhiteList.New(OptionsRaw{ "message": testMessage, }) - ExpectError(t, serialization.ErrValidationError, err) + expect.ErrorIs(t, serialization.ErrValidationError, err) }) t.Run("invalid cidr", func(t *testing.T) { _, err := CIDRWhiteList.New(OptionsRaw{ "allow": []string{"192.168.2.100/123"}, "message": testMessage, }) - ExpectErrorT[*net.ParseError](t, err) + expect.ErrorT[*net.ParseError](t, err) }) t.Run("invalid status code", func(t *testing.T) { _, err := CIDRWhiteList.New(OptionsRaw{ @@ -56,14 +56,14 @@ func TestCIDRWhitelistValidation(t *testing.T) { "status_code": 600, "message": testMessage, }) - ExpectError(t, serialization.ErrValidationError, err) + expect.ErrorIs(t, serialization.ErrValidationError, err) }) } func TestCIDRWhitelist(t *testing.T) { errs := gperr.NewBuilder("") mids := BuildMiddlewaresFromYAML("", testCIDRWhitelistCompose, errs) - ExpectNoError(t, errs.Error()) + expect.NoError(t, errs.Error()) deny = mids["deny@file"] accept = mids["accept@file"] if deny == nil || accept == nil { @@ -74,9 +74,9 @@ func TestCIDRWhitelist(t *testing.T) { t.Parallel() for range 10 { result, err := newMiddlewareTest(deny, nil) - ExpectNoError(t, err) - ExpectEqual(t, result.ResponseStatus, cidrWhitelistDefaults.StatusCode) - ExpectEqual(t, strings.TrimSpace(string(result.Data)), cidrWhitelistDefaults.Message) + expect.NoError(t, err) + expect.Equal(t, result.ResponseStatus, cidrWhitelistDefaults.StatusCode) + expect.Equal(t, strings.TrimSpace(string(result.Data)), cidrWhitelistDefaults.Message) } }) @@ -84,8 +84,8 @@ func TestCIDRWhitelist(t *testing.T) { t.Parallel() for range 10 { result, err := newMiddlewareTest(accept, nil) - ExpectNoError(t, err) - ExpectEqual(t, result.ResponseStatus, http.StatusOK) + expect.NoError(t, err) + expect.Equal(t, result.ResponseStatus, http.StatusOK) } }) } diff --git a/internal/net/gphttp/middleware/cloudflare_real_ip.go b/internal/net/gphttp/middleware/cloudflare_real_ip.go index 1214f099..88abd828 100644 --- a/internal/net/gphttp/middleware/cloudflare_real_ip.go +++ b/internal/net/gphttp/middleware/cloudflare_real_ip.go @@ -63,14 +63,14 @@ func (cri *cloudflareRealIP) before(w http.ResponseWriter, r *http.Request) bool func tryFetchCFCIDR() (cfCIDRs []*nettypes.CIDR) { if time.Since(cfCIDRsLastUpdate.Load()) < cfCIDRsUpdateInterval { - return + return cfCIDRs } cfCIDRsMu.Lock() defer cfCIDRsMu.Unlock() if time.Since(cfCIDRsLastUpdate.Load()) < cfCIDRsUpdateInterval { - return + return cfCIDRs } if common.IsTest { @@ -93,7 +93,7 @@ func tryFetchCFCIDR() (cfCIDRs []*nettypes.CIDR) { cfCIDRsLastUpdate.Store(time.Now()) log.Info().Msg("cloudflare CIDR range updated") - return + return cfCIDRs } func fetchUpdateCFIPRange(endpoint string, cfCIDRs *[]*nettypes.CIDR) error { diff --git a/internal/net/gphttp/middleware/errorpage/error_page.go b/internal/net/gphttp/middleware/errorpage/error_page.go index c3afc158..6a576afa 100644 --- a/internal/net/gphttp/middleware/errorpage/error_page.go +++ b/internal/net/gphttp/middleware/errorpage/error_page.go @@ -9,11 +9,11 @@ import ( "github.com/puzpuzpuz/xsync/v4" "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/utils" "github.com/yusing/godoxy/internal/watcher" "github.com/yusing/godoxy/internal/watcher/events" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) const errPagesBasePath = common.ErrorPagesBasePath @@ -42,7 +42,7 @@ func GetErrorPageByStatus(statusCode int) (content []byte, ok bool) { if !ok && statusCode != 404 { return fileContentMap.Load("404.html") } - return + return content, ok } func loadContent() { diff --git a/internal/net/gphttp/middleware/middleware.go b/internal/net/gphttp/middleware/middleware.go index 3100698a..fefcac7f 100644 --- a/internal/net/gphttp/middleware/middleware.go +++ b/internal/net/gphttp/middleware/middleware.go @@ -10,9 +10,9 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/gperr" gphttp "github.com/yusing/godoxy/internal/net/gphttp" "github.com/yusing/godoxy/internal/serialization" + gperr "github.com/yusing/goutils/errs" "github.com/yusing/goutils/http/reverseproxy" ) @@ -207,10 +207,10 @@ func PatchReverseProxy(rp *ReverseProxy, middlewaresMap map[string]OptionsRaw) ( var middlewares []*Middleware middlewares, err = compileMiddlewares(middlewaresMap) if err != nil { - return + return err } patchReverseProxy(rp, middlewares) - return + return err } func patchReverseProxy(rp *ReverseProxy, middlewares []*Middleware) { diff --git a/internal/net/gphttp/middleware/middleware_builder.go b/internal/net/gphttp/middleware/middleware_builder.go index 7264e830..f5a14c08 100644 --- a/internal/net/gphttp/middleware/middleware_builder.go +++ b/internal/net/gphttp/middleware/middleware_builder.go @@ -7,7 +7,7 @@ import ( "sort" "github.com/goccy/go-yaml" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) var ErrMissingMiddlewareUse = gperr.New("missing middleware 'use' field") diff --git a/internal/net/gphttp/middleware/middleware_builder_test.go b/internal/net/gphttp/middleware/middleware_builder_test.go index fee87995..2233fe3c 100644 --- a/internal/net/gphttp/middleware/middleware_builder_test.go +++ b/internal/net/gphttp/middleware/middleware_builder_test.go @@ -5,8 +5,8 @@ import ( "encoding/json" "testing" - "github.com/yusing/godoxy/internal/gperr" - . "github.com/yusing/godoxy/internal/utils/testing" + gperr "github.com/yusing/goutils/errs" + expect "github.com/yusing/goutils/testing" ) //go:embed test_data/middleware_compose.yml @@ -15,8 +15,8 @@ var testMiddlewareCompose []byte func TestBuild(t *testing.T) { errs := gperr.NewBuilder("") middlewares := BuildMiddlewaresFromYAML("", testMiddlewareCompose, errs) - ExpectNoError(t, errs.Error()) - Must(json.MarshalIndent(middlewares, "", " ")) + expect.NoError(t, errs.Error()) + expect.Must(json.MarshalIndent(middlewares, "", " ")) // t.Log(string(data)) // TODO: test } diff --git a/internal/net/gphttp/middleware/middleware_chain.go b/internal/net/gphttp/middleware/middleware_chain.go index 360497d1..ad589a17 100644 --- a/internal/net/gphttp/middleware/middleware_chain.go +++ b/internal/net/gphttp/middleware/middleware_chain.go @@ -3,7 +3,7 @@ package middleware import ( "net/http" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type middlewareChain struct { diff --git a/internal/net/gphttp/middleware/middleware_test.go b/internal/net/gphttp/middleware/middleware_test.go index 8c003025..4f289f45 100644 --- a/internal/net/gphttp/middleware/middleware_test.go +++ b/internal/net/gphttp/middleware/middleware_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) type testPriority struct { @@ -28,10 +28,10 @@ func TestMiddlewarePriority(t *testing.T) { "priority": p, "value": i, }) - ExpectNoError(t, err) + expect.NoError(t, err) chain[i] = mid } res, err := newMiddlewaresTest(chain, nil) - ExpectNoError(t, err) - ExpectEqual(t, strings.Join(res.ResponseHeaders["Test-Value"], ","), "3,0,1,2") + expect.NoError(t, err) + expect.Equal(t, strings.Join(res.ResponseHeaders["Test-Value"], ","), "3,0,1,2") } diff --git a/internal/net/gphttp/middleware/middlewares.go b/internal/net/gphttp/middleware/middlewares.go index 56e7342e..7360f7f7 100644 --- a/internal/net/gphttp/middleware/middlewares.go +++ b/internal/net/gphttp/middleware/middlewares.go @@ -7,8 +7,8 @@ import ( "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/utils" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" ) diff --git a/internal/net/gphttp/middleware/modify_html_test.go b/internal/net/gphttp/middleware/modify_html_test.go index c17bd970..213f536c 100644 --- a/internal/net/gphttp/middleware/modify_html_test.go +++ b/internal/net/gphttp/middleware/modify_html_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestInjectCSS(t *testing.T) { diff --git a/internal/net/gphttp/middleware/modify_request_test.go b/internal/net/gphttp/middleware/modify_request_test.go index 85ceb3d2..e383610c 100644 --- a/internal/net/gphttp/middleware/modify_request_test.go +++ b/internal/net/gphttp/middleware/modify_request_test.go @@ -8,7 +8,7 @@ import ( "testing" nettypes "github.com/yusing/godoxy/internal/net/types" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestModifyRequest(t *testing.T) { @@ -44,10 +44,10 @@ func TestModifyRequest(t *testing.T) { t.Run("set_options", func(t *testing.T) { mr, err := ModifyRequest.New(opts) - ExpectNoError(t, err) - ExpectEqual(t, mr.impl.(*modifyRequest).SetHeaders, opts["set_headers"].(map[string]string)) - ExpectEqual(t, mr.impl.(*modifyRequest).AddHeaders, opts["add_headers"].(map[string]string)) - ExpectEqual(t, mr.impl.(*modifyRequest).HideHeaders, opts["hide_headers"].([]string)) + expect.NoError(t, err) + expect.Equal(t, mr.impl.(*modifyRequest).SetHeaders, opts["set_headers"].(map[string]string)) + expect.Equal(t, mr.impl.(*modifyRequest).AddHeaders, opts["add_headers"].(map[string]string)) + expect.Equal(t, mr.impl.(*modifyRequest).HideHeaders, opts["hide_headers"].([]string)) }) t.Run("request_headers", func(t *testing.T) { @@ -62,38 +62,38 @@ func TestModifyRequest(t *testing.T) { "Content-Type": []string{"application/json"}, }, }) - ExpectNoError(t, err) - ExpectEqual(t, result.RequestHeaders.Get("User-Agent"), "go-proxy/v0.5.0") - ExpectEqual(t, result.RequestHeaders.Get("Host"), "test.example.com") - ExpectTrue(t, slices.Contains(result.RequestHeaders.Values("Accept-Encoding"), "test-value")) - ExpectEqual(t, result.RequestHeaders.Get("Accept"), "") + expect.NoError(t, err) + expect.Equal(t, result.RequestHeaders.Get("User-Agent"), "go-proxy/v0.5.0") + expect.Equal(t, result.RequestHeaders.Get("Host"), "test.example.com") + expect.True(t, slices.Contains(result.RequestHeaders.Values("Accept-Encoding"), "test-value")) + expect.Equal(t, result.RequestHeaders.Get("Accept"), "") - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Method"), "GET") - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Scheme"), reqURL.Scheme) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Host"), reqURL.Hostname()) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Port"), reqURL.Port()) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Addr"), reqURL.Host) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Path"), reqURL.Path) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Query"), reqURL.RawQuery) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Url"), reqURL.String()) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Uri"), reqURL.RequestURI()) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Content-Type"), "application/json") - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Content-Length"), "100") + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Method"), "GET") + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Scheme"), reqURL.Scheme) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Host"), reqURL.Hostname()) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Port"), reqURL.Port()) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Addr"), reqURL.Host) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Path"), reqURL.Path) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Query"), reqURL.RawQuery) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Url"), reqURL.String()) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Uri"), reqURL.RequestURI()) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Content-Type"), "application/json") + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Content-Length"), "100") remoteHost, remotePort, _ := net.SplitHostPort(result.RemoteAddr) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Remote-Host"), remoteHost) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Remote-Port"), remotePort) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Remote-Addr"), result.RemoteAddr) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Remote-Host"), remoteHost) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Remote-Port"), remotePort) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Remote-Addr"), result.RemoteAddr) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Upstream-Scheme"), upstreamURL.Scheme) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Upstream-Host"), upstreamURL.Hostname()) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Upstream-Port"), upstreamURL.Port()) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Upstream-Addr"), upstreamURL.Host) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Upstream-Url"), upstreamURL.String()) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Upstream-Scheme"), upstreamURL.Scheme) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Upstream-Host"), upstreamURL.Hostname()) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Upstream-Port"), upstreamURL.Port()) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Upstream-Addr"), upstreamURL.Host) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Upstream-Url"), upstreamURL.String()) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Header-Content-Type"), "application/json") + expect.Equal(t, result.RequestHeaders.Get("X-Test-Header-Content-Type"), "application/json") - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Arg-Arg_1"), "b") + expect.Equal(t, result.RequestHeaders.Get("X-Test-Arg-Arg_1"), "b") }) t.Run("add_prefix", func(t *testing.T) { @@ -137,8 +137,8 @@ func TestModifyRequest(t *testing.T) { reqURL: reqURL, upstreamURL: upstreamURL, }) - ExpectNoError(t, err) - ExpectEqual(t, result.RequestHeaders.Get("X-Test-Req-Path"), tt.expectedPath) + expect.NoError(t, err) + expect.Equal(t, result.RequestHeaders.Get("X-Test-Req-Path"), tt.expectedPath) }) } }) diff --git a/internal/net/gphttp/middleware/modify_response_test.go b/internal/net/gphttp/middleware/modify_response_test.go index ea90a525..45ba6e51 100644 --- a/internal/net/gphttp/middleware/modify_response_test.go +++ b/internal/net/gphttp/middleware/modify_response_test.go @@ -8,7 +8,7 @@ import ( "testing" nettypes "github.com/yusing/godoxy/internal/net/types" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestModifyResponse(t *testing.T) { @@ -47,10 +47,10 @@ func TestModifyResponse(t *testing.T) { t.Run("set_options", func(t *testing.T) { mr, err := ModifyResponse.New(opts) - ExpectNoError(t, err) - ExpectEqual(t, mr.impl.(*modifyResponse).SetHeaders, opts["set_headers"].(map[string]string)) - ExpectEqual(t, mr.impl.(*modifyResponse).AddHeaders, opts["add_headers"].(map[string]string)) - ExpectEqual(t, mr.impl.(*modifyResponse).HideHeaders, opts["hide_headers"].([]string)) + expect.NoError(t, err) + expect.Equal(t, mr.impl.(*modifyResponse).SetHeaders, opts["set_headers"].(map[string]string)) + expect.Equal(t, mr.impl.(*modifyResponse).AddHeaders, opts["add_headers"].(map[string]string)) + expect.Equal(t, mr.impl.(*modifyResponse).HideHeaders, opts["hide_headers"].([]string)) }) t.Run("response_headers", func(t *testing.T) { @@ -70,39 +70,39 @@ func TestModifyResponse(t *testing.T) { respBody: bytes.Repeat([]byte("a"), 50), respStatus: http.StatusOK, }) - ExpectNoError(t, err) - ExpectTrue(t, slices.Contains(result.ResponseHeaders.Values("Accept-Encoding"), "test-value")) - ExpectEqual(t, result.ResponseHeaders.Get("Accept"), "") + expect.NoError(t, err) + expect.True(t, slices.Contains(result.ResponseHeaders.Values("Accept-Encoding"), "test-value")) + expect.Equal(t, result.ResponseHeaders.Get("Accept"), "") - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Resp-Status"), "200") - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Resp-Content-Type"), "application/json") - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Resp-Content-Length"), "50") - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Resp-Header-Content-Type"), "application/json") + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Resp-Status"), "200") + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Resp-Content-Type"), "application/json") + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Resp-Content-Length"), "50") + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Resp-Header-Content-Type"), "application/json") - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Method"), http.MethodGet) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Scheme"), reqURL.Scheme) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Host"), reqURL.Hostname()) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Port"), reqURL.Port()) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Addr"), reqURL.Host) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Path"), reqURL.Path) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Query"), reqURL.RawQuery) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Url"), reqURL.String()) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Uri"), reqURL.RequestURI()) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Content-Type"), "application/json") - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Req-Content-Length"), "100") + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Method"), http.MethodGet) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Scheme"), reqURL.Scheme) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Host"), reqURL.Hostname()) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Port"), reqURL.Port()) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Addr"), reqURL.Host) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Path"), reqURL.Path) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Query"), reqURL.RawQuery) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Url"), reqURL.String()) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Uri"), reqURL.RequestURI()) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Content-Type"), "application/json") + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Req-Content-Length"), "100") remoteHost, remotePort, _ := net.SplitHostPort(result.RemoteAddr) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Remote-Host"), remoteHost) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Remote-Port"), remotePort) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Remote-Addr"), result.RemoteAddr) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Remote-Host"), remoteHost) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Remote-Port"), remotePort) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Remote-Addr"), result.RemoteAddr) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Upstream-Scheme"), upstreamURL.Scheme) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Upstream-Host"), upstreamURL.Hostname()) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Upstream-Port"), upstreamURL.Port()) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Upstream-Addr"), upstreamURL.Host) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Upstream-Url"), upstreamURL.String()) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Upstream-Scheme"), upstreamURL.Scheme) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Upstream-Host"), upstreamURL.Hostname()) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Upstream-Port"), upstreamURL.Port()) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Upstream-Addr"), upstreamURL.Host) + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Upstream-Url"), upstreamURL.String()) - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Header-Content-Type"), "application/json") - ExpectEqual(t, result.ResponseHeaders.Get("X-Test-Arg-Arg_1"), "b") + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Header-Content-Type"), "application/json") + expect.Equal(t, result.ResponseHeaders.Get("X-Test-Arg-Arg_1"), "b") }) } diff --git a/internal/net/gphttp/middleware/oidc.go b/internal/net/gphttp/middleware/oidc.go index 54d8d25c..bf21a7cb 100644 --- a/internal/net/gphttp/middleware/oidc.go +++ b/internal/net/gphttp/middleware/oidc.go @@ -8,7 +8,7 @@ import ( "sync/atomic" "github.com/yusing/godoxy/internal/auth" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type oidcMiddleware struct { diff --git a/internal/net/gphttp/middleware/oidc_test.go b/internal/net/gphttp/middleware/oidc_test.go index 93ab7260..69481827 100644 --- a/internal/net/gphttp/middleware/oidc_test.go +++ b/internal/net/gphttp/middleware/oidc_test.go @@ -3,7 +3,7 @@ package middleware import ( "testing" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestOIDCMiddlewarePerRouteConfig(t *testing.T) { @@ -16,20 +16,20 @@ func TestOIDCMiddlewarePerRouteConfig(t *testing.T) { Scopes: "openid,profile,email,groups", } - ExpectEqual(t, middleware.AllowedUsers, []string{"custom-user"}) - ExpectEqual(t, middleware.AllowedGroups, []string{"custom-group"}) - ExpectEqual(t, middleware.ClientID, "custom-client-id") - ExpectEqual(t, middleware.ClientSecret, "custom-client-secret") - ExpectEqual(t, middleware.Scopes, "openid,profile,email,groups") + expect.Equal(t, middleware.AllowedUsers, []string{"custom-user"}) + expect.Equal(t, middleware.AllowedGroups, []string{"custom-group"}) + expect.Equal(t, middleware.ClientID, "custom-client-id") + expect.Equal(t, middleware.ClientSecret, "custom-client-secret") + expect.Equal(t, middleware.Scopes, "openid,profile,email,groups") }) t.Run("middleware struct handles empty values", func(t *testing.T) { middleware := &oidcMiddleware{} - ExpectEqual(t, middleware.AllowedUsers, nil) - ExpectEqual(t, middleware.AllowedGroups, nil) - ExpectEqual(t, middleware.ClientID, "") - ExpectEqual(t, middleware.ClientSecret, "") - ExpectEqual(t, middleware.Scopes, "") + expect.Equal(t, middleware.AllowedUsers, nil) + expect.Equal(t, middleware.AllowedGroups, nil) + expect.Equal(t, middleware.ClientID, "") + expect.Equal(t, middleware.ClientSecret, "") + expect.Equal(t, middleware.Scopes, "") }) } diff --git a/internal/net/gphttp/middleware/rate_limit_test.go b/internal/net/gphttp/middleware/rate_limit_test.go index 35af0c53..d24818a8 100644 --- a/internal/net/gphttp/middleware/rate_limit_test.go +++ b/internal/net/gphttp/middleware/rate_limit_test.go @@ -4,7 +4,7 @@ import ( "net/http" "testing" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestRateLimit(t *testing.T) { @@ -15,13 +15,13 @@ func TestRateLimit(t *testing.T) { } rl, err := RateLimiter.New(opts) - ExpectNoError(t, err) + expect.NoError(t, err) for range 10 { result, err := newMiddlewareTest(rl, nil) - ExpectNoError(t, err) - ExpectEqual(t, result.ResponseStatus, http.StatusOK) + expect.NoError(t, err) + expect.Equal(t, result.ResponseStatus, http.StatusOK) } result, err := newMiddlewareTest(rl, nil) - ExpectNoError(t, err) - ExpectEqual(t, result.ResponseStatus, http.StatusTooManyRequests) + expect.NoError(t, err) + expect.Equal(t, result.ResponseStatus, http.StatusTooManyRequests) } diff --git a/internal/net/gphttp/middleware/real_ip_test.go b/internal/net/gphttp/middleware/real_ip_test.go index 38a6952e..b539642c 100644 --- a/internal/net/gphttp/middleware/real_ip_test.go +++ b/internal/net/gphttp/middleware/real_ip_test.go @@ -7,8 +7,8 @@ import ( "testing" nettypes "github.com/yusing/godoxy/internal/net/types" - . "github.com/yusing/godoxy/internal/utils/testing" "github.com/yusing/goutils/http/httpheaders" + expect "github.com/yusing/goutils/testing" ) func TestSetRealIPOpts(t *testing.T) { @@ -41,11 +41,11 @@ func TestSetRealIPOpts(t *testing.T) { } ri, err := RealIP.New(opts) - ExpectNoError(t, err) - ExpectEqual(t, ri.impl.(*realIP).Header, optExpected.Header) - ExpectEqual(t, ri.impl.(*realIP).Recursive, optExpected.Recursive) + expect.NoError(t, err) + expect.Equal(t, ri.impl.(*realIP).Header, optExpected.Header) + expect.Equal(t, ri.impl.(*realIP).Recursive, optExpected.Recursive) for i, CIDR := range ri.impl.(*realIP).From { - ExpectEqual(t, CIDR.String(), optExpected.From[i].String()) + expect.Equal(t, CIDR.String(), optExpected.From[i].String()) } } @@ -62,15 +62,15 @@ func TestSetRealIP(t *testing.T) { "set_headers": map[string]string{testHeader: testRealIP}, } realip, err := RealIP.New(opts) - ExpectNoError(t, err) + expect.NoError(t, err) mr, err := ModifyRequest.New(optsMr) - ExpectNoError(t, err) + expect.NoError(t, err) mid := NewMiddlewareChain("test", []*Middleware{mr, realip}) result, err := newMiddlewareTest(mid, nil) - ExpectNoError(t, err) - ExpectEqual(t, result.ResponseStatus, http.StatusOK) - ExpectEqual(t, strings.Split(result.RemoteAddr, ":")[0], testRealIP) + expect.NoError(t, err) + expect.Equal(t, result.ResponseStatus, http.StatusOK) + expect.Equal(t, strings.Split(result.RemoteAddr, ":")[0], testRealIP) } diff --git a/internal/net/gphttp/middleware/redirect_http_test.go b/internal/net/gphttp/middleware/redirect_http_test.go index d8ccca85..0a2dc0f7 100644 --- a/internal/net/gphttp/middleware/redirect_http_test.go +++ b/internal/net/gphttp/middleware/redirect_http_test.go @@ -5,22 +5,22 @@ import ( "testing" nettypes "github.com/yusing/godoxy/internal/net/types" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestRedirectToHTTPs(t *testing.T) { result, err := newMiddlewareTest(RedirectHTTP, &testArgs{ reqURL: nettypes.MustParseURL("http://example.com"), }) - ExpectNoError(t, err) - ExpectEqual(t, result.ResponseStatus, http.StatusPermanentRedirect) - ExpectEqual(t, result.ResponseHeaders.Get("Location"), "https://example.com") + expect.NoError(t, err) + expect.Equal(t, result.ResponseStatus, http.StatusPermanentRedirect) + expect.Equal(t, result.ResponseHeaders.Get("Location"), "https://example.com") } func TestNoRedirect(t *testing.T) { result, err := newMiddlewareTest(RedirectHTTP, &testArgs{ reqURL: nettypes.MustParseURL("https://example.com"), }) - ExpectNoError(t, err) - ExpectEqual(t, result.ResponseStatus, http.StatusOK) + expect.NoError(t, err) + expect.Equal(t, result.ResponseStatus, http.StatusOK) } diff --git a/internal/net/gphttp/middleware/test_utils.go b/internal/net/gphttp/middleware/test_utils.go index 2e8128ba..e3226c6a 100644 --- a/internal/net/gphttp/middleware/test_utils.go +++ b/internal/net/gphttp/middleware/test_utils.go @@ -10,9 +10,8 @@ import ( "net/http/httptest" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" nettypes "github.com/yusing/godoxy/internal/net/types" - . "github.com/yusing/godoxy/internal/utils/testing" + gperr "github.com/yusing/goutils/errs" "github.com/yusing/goutils/http/reverseproxy" ) @@ -96,13 +95,13 @@ type testArgs struct { func (args *testArgs) setDefaults() { if args.reqURL == nil { - args.reqURL = Must(nettypes.ParseURL("https://example.com")) + args.reqURL = nettypes.MustParseURL("https://example.com") } if args.reqMethod == "" { args.reqMethod = http.MethodGet } if args.upstreamURL == nil { - args.upstreamURL = Must(nettypes.ParseURL("https://10.0.0.1:8443")) // dummy url, no actual effect + args.upstreamURL = nettypes.MustParseURL("https://10.0.0.1:8443") // dummy url, no actual effect } if args.respHeaders == nil { args.respHeaders = http.Header{} diff --git a/internal/net/gphttp/middleware/themed.go b/internal/net/gphttp/middleware/themed.go index bcc4b6ba..32032473 100644 --- a/internal/net/gphttp/middleware/themed.go +++ b/internal/net/gphttp/middleware/themed.go @@ -10,7 +10,7 @@ import ( _ "embed" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type themed struct { diff --git a/internal/net/gphttp/serve_mux.go b/internal/net/gphttp/serve_mux.go index 902c0e2a..7b5f1089 100644 --- a/internal/net/gphttp/serve_mux.go +++ b/internal/net/gphttp/serve_mux.go @@ -17,7 +17,7 @@ func (mux ServeMux) Handle(pattern string, handler http.Handler) (err error) { } }() mux.ServeMux.Handle(pattern, handler) - return + return err } func (mux ServeMux) HandleFunc(pattern string, handler http.HandlerFunc) (err error) { @@ -27,5 +27,5 @@ func (mux ServeMux) HandleFunc(pattern string, handler http.HandlerFunc) (err er } }() mux.ServeMux.HandleFunc(pattern, handler) - return + return err } diff --git a/internal/net/gphttp/server/server.go b/internal/net/gphttp/server/server.go index 020ff153..fb0d15cf 100644 --- a/internal/net/gphttp/server/server.go +++ b/internal/net/gphttp/server/server.go @@ -16,7 +16,7 @@ import ( "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/acl" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/task" + "github.com/yusing/goutils/task" ) type CertProvider interface { @@ -173,7 +173,7 @@ func WithProxyProtocolSupport(value bool) ServerStartOption { func Start[Server httpServer](parent task.Parent, srv Server, optFns ...ServerStartOption) (port int) { if srv == nil { - return + return port } var opts ServerStartOptions @@ -200,7 +200,7 @@ func Start[Server httpServer](parent task.Parent, srv Server, optFns ...ServerSt l, err := lc.Listen(task.Context(), "tcp", srv.Addr) if err != nil { HandleError(opts.logger, err, "failed to listen on port") - return + return port } port = l.Addr().(*net.TCPAddr).Port if opts.proxyProto { @@ -224,7 +224,7 @@ func Start[Server httpServer](parent task.Parent, srv Server, optFns ...ServerSt l, err := lc.ListenPacket(task.Context(), "udp", srv.Addr) if err != nil { HandleError(opts.logger, err, "failed to listen on port") - return + return port } port = l.LocalAddr().(*net.UDPAddr).Port for _, wrapper := range opts.udpWrappers { diff --git a/internal/net/types/cidr.go b/internal/net/types/cidr.go index d9959a74..d0f4e87c 100644 --- a/internal/net/types/cidr.go +++ b/internal/net/types/cidr.go @@ -10,7 +10,7 @@ type CIDR net.IPNet func ParseCIDR(v string) (cidr CIDR, err error) { err = cidr.Parse(v) - return + return cidr, err } func (cidr *CIDR) Parse(v string) error { diff --git a/internal/notif/base.go b/internal/notif/base.go index 896c0b7f..30e4a169 100644 --- a/internal/notif/base.go +++ b/internal/notif/base.go @@ -6,7 +6,7 @@ import ( "net/url" "strings" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type ProviderBase struct { diff --git a/internal/notif/body.go b/internal/notif/body.go index e47f7afb..a1252c95 100644 --- a/internal/notif/body.go +++ b/internal/notif/body.go @@ -5,7 +5,7 @@ import ( "encoding/json" "strings" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/notif/config.go b/internal/notif/config.go index 8b1dde37..c4838067 100644 --- a/internal/notif/config.go +++ b/internal/notif/config.go @@ -1,8 +1,8 @@ package notif import ( - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/serialization" + gperr "github.com/yusing/goutils/errs" ) type NotificationConfig struct { diff --git a/internal/notif/config_test.go b/internal/notif/config_test.go index 3093c8f7..67f04d5d 100644 --- a/internal/notif/config_test.go +++ b/internal/notif/config_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/yusing/godoxy/internal/serialization" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestNotificationConfig(t *testing.T) { @@ -183,11 +183,11 @@ func TestNotificationConfig(t *testing.T) { provider := tt.cfg["provider"] err := serialization.MapUnmarshalValidate(tt.cfg, &cfg) if tt.wantErr { - ExpectHasError(t, err) + expect.NotNil(t, err) } else { - ExpectNoError(t, err) - ExpectEqual(t, provider.(string), cfg.ProviderName) - ExpectEqual(t, cfg.Provider, tt.expected) + expect.NoError(t, err) + expect.Equal(t, provider.(string), cfg.ProviderName) + expect.Equal(t, cfg.Provider, tt.expected) } }) } diff --git a/internal/notif/dispatcher.go b/internal/notif/dispatcher.go index 503e83f0..756fc413 100644 --- a/internal/notif/dispatcher.go +++ b/internal/notif/dispatcher.go @@ -8,8 +8,8 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/task" F "github.com/yusing/godoxy/internal/utils/functional" + "github.com/yusing/goutils/task" ) type ( diff --git a/internal/notif/ntfy.go b/internal/notif/ntfy.go index da566b53..5f2c3b7e 100644 --- a/internal/notif/ntfy.go +++ b/internal/notif/ntfy.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/rs/zerolog" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) // See https://docs.ntfy.sh/publish diff --git a/internal/notif/providers.go b/internal/notif/providers.go index 894cd134..bfab08f2 100644 --- a/internal/notif/providers.go +++ b/internal/notif/providers.go @@ -8,8 +8,8 @@ import ( "net/http" "time" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/serialization" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/notif/webhook.go b/internal/notif/webhook.go index 40ed7084..4f073d99 100644 --- a/internal/notif/webhook.go +++ b/internal/notif/webhook.go @@ -7,7 +7,7 @@ import ( "net/http" "strings" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type Webhook struct { diff --git a/internal/proxmox/config.go b/internal/proxmox/config.go index 0d287fb5..b0feba2d 100644 --- a/internal/proxmox/config.go +++ b/internal/proxmox/config.go @@ -9,8 +9,8 @@ import ( "time" "github.com/luthermonson/go-proxmox" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/net/gphttp" + gperr "github.com/yusing/goutils/errs" ) type Config struct { diff --git a/internal/route/common.go b/internal/route/common.go index 4bd12972..a1f1a785 100644 --- a/internal/route/common.go +++ b/internal/route/common.go @@ -1,9 +1,9 @@ package route import ( - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/route/routes" "github.com/yusing/godoxy/internal/types" + gperr "github.com/yusing/goutils/errs" ) func checkExists(r types.Route) gperr.Error { diff --git a/internal/route/fileserver.go b/internal/route/fileserver.go index 3126d366..e3f3c55d 100644 --- a/internal/route/fileserver.go +++ b/internal/route/fileserver.go @@ -5,13 +5,13 @@ import ( "path" "path/filepath" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/logging/accesslog" gphttp "github.com/yusing/godoxy/internal/net/gphttp" "github.com/yusing/godoxy/internal/net/gphttp/middleware" "github.com/yusing/godoxy/internal/route/routes" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/watcher/health/monitor" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) type ( diff --git a/internal/route/fileserver_test.go b/internal/route/fileserver_test.go index c2bb5732..caa0144a 100644 --- a/internal/route/fileserver_test.go +++ b/internal/route/fileserver_test.go @@ -10,26 +10,26 @@ import ( "path/filepath" "testing" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestPathTraversalAttack(t *testing.T) { tmp := t.TempDir() root := filepath.Join(tmp, "static") - if err := os.Mkdir(root, 0755); err != nil { + if err := os.Mkdir(root, 0o755); err != nil { t.Fatalf("Failed to create root directory: %v", err) } // Create a file inside the root validPath := "test.txt" validContent := "test content" - if err := os.WriteFile(filepath.Join(root, validPath), []byte(validContent), 0644); err != nil { + if err := os.WriteFile(filepath.Join(root, validPath), []byte(validContent), 0o644); err != nil { t.Fatalf("Failed to create test file: %v", err) } // create one at .. secretFile := "secret.txt" - if err := os.WriteFile(filepath.Join(tmp, secretFile), []byte(validContent), 0644); err != nil { + if err := os.WriteFile(filepath.Join(tmp, secretFile), []byte(validContent), 0o644); err != nil { t.Fatalf("Failed to create test file: %v", err) } @@ -108,7 +108,7 @@ func TestPathTraversalAttack(t *testing.T) { t.Errorf("Expected status 404 or 400, got %d in url %s", resp.StatusCode, u.String()) } - u = Must(url.Parse(ts.URL + "/" + p)) + u = expect.Must(url.Parse(ts.URL + "/" + p)) resp, err = http.DefaultClient.Do(&http.Request{ Method: http.MethodGet, URL: u, diff --git a/internal/route/port_selection.go b/internal/route/port_selection.go index b248025b..eb5afadb 100644 --- a/internal/route/port_selection.go +++ b/internal/route/port_selection.go @@ -67,7 +67,7 @@ func getSchemePortByImageName(imageName string) (scheme string, port int, ok boo if port, ok := ImageNamePortMapTCP[imageName]; ok { return "tcp", port, true } - return + return scheme, port, ok } func getSchemePortByAlias(alias string) (scheme string, port int, ok bool) { @@ -77,5 +77,5 @@ func getSchemePortByAlias(alias string) (scheme string, port int, ok bool) { if port, ok := AliasPortMapHTTPS[alias]; ok { return "https", port, true } - return + return scheme, port, ok } diff --git a/internal/route/provider/agent.go b/internal/route/provider/agent.go index f4e4f4d8..0d35532b 100644 --- a/internal/route/provider/agent.go +++ b/internal/route/provider/agent.go @@ -3,9 +3,9 @@ package provider import ( "github.com/rs/zerolog" "github.com/yusing/godoxy/agent/pkg/agent" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/route" "github.com/yusing/godoxy/internal/watcher" + gperr "github.com/yusing/goutils/errs" ) type AgentProvider struct { diff --git a/internal/route/provider/docker.go b/internal/route/provider/docker.go index 680af79f..8ceecf9f 100755 --- a/internal/route/provider/docker.go +++ b/internal/route/provider/docker.go @@ -10,11 +10,11 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/docker" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/route" "github.com/yusing/godoxy/internal/serialization" "github.com/yusing/godoxy/internal/types" "github.com/yusing/godoxy/internal/watcher" + gperr "github.com/yusing/goutils/errs" ) type DockerProvider struct { diff --git a/internal/route/provider/docker_labels_test.go b/internal/route/provider/docker_labels_test.go index f5b27c9f..bb7e4b54 100644 --- a/internal/route/provider/docker_labels_test.go +++ b/internal/route/provider/docker_labels_test.go @@ -6,7 +6,7 @@ import ( "github.com/docker/docker/api/types/container" "github.com/goccy/go-yaml" "github.com/yusing/godoxy/internal/docker" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" _ "embed" ) @@ -18,7 +18,7 @@ func TestParseDockerLabels(t *testing.T) { var provider DockerProvider labels := make(map[string]string) - ExpectNoError(t, yaml.Unmarshal(testDockerLabelsYAML, &labels)) + expect.NoError(t, yaml.Unmarshal(testDockerLabelsYAML, &labels)) routes, err := provider.routesFromContainerLabels( docker.FromDocker(&container.Summary{ @@ -30,7 +30,7 @@ func TestParseDockerLabels(t *testing.T) { }, }, "/var/run/docker.sock"), ) - ExpectNoError(t, err) - ExpectTrue(t, routes.Contains("app")) - ExpectTrue(t, routes.Contains("app1")) + expect.NoError(t, err) + expect.True(t, routes.Contains("app")) + expect.True(t, routes.Contains("app1")) } diff --git a/internal/route/provider/docker_test.go b/internal/route/provider/docker_test.go index 83dbc416..34ae657c 100644 --- a/internal/route/provider/docker_test.go +++ b/internal/route/provider/docker_test.go @@ -10,7 +10,7 @@ import ( D "github.com/yusing/godoxy/internal/docker" "github.com/yusing/godoxy/internal/route" T "github.com/yusing/godoxy/internal/route/types" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) var dummyNames = []string{"/a"} diff --git a/internal/route/provider/event_handler.go b/internal/route/provider/event_handler.go index 0bd29102..eacd5670 100644 --- a/internal/route/provider/event_handler.go +++ b/internal/route/provider/event_handler.go @@ -1,12 +1,12 @@ package provider import ( - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/route" provider "github.com/yusing/godoxy/internal/route/provider/types" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/watcher" eventsPkg "github.com/yusing/godoxy/internal/watcher/events" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) type EventHandler struct { diff --git a/internal/route/provider/file.go b/internal/route/provider/file.go index b373567f..bc4b1d8d 100644 --- a/internal/route/provider/file.go +++ b/internal/route/provider/file.go @@ -8,10 +8,10 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/route" "github.com/yusing/godoxy/internal/serialization" W "github.com/yusing/godoxy/internal/watcher" + gperr "github.com/yusing/goutils/errs" ) type FileProvider struct { @@ -44,12 +44,12 @@ func removeXPrefix(m map[string]any) gperr.Error { func validate(data []byte) (routes route.Routes, err gperr.Error) { err = serialization.UnmarshalValidateYAMLIntercept(data, &routes, removeXPrefix) - return + return routes, err } func Validate(data []byte) (err gperr.Error) { _, err = validate(data) - return + return err } func (p *FileProvider) String() string { diff --git a/internal/route/provider/file_test.go b/internal/route/provider/file_test.go index f37d36a7..e51e7b90 100644 --- a/internal/route/provider/file_test.go +++ b/internal/route/provider/file_test.go @@ -5,7 +5,7 @@ import ( _ "embed" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) //go:embed all_fields.yaml @@ -13,5 +13,5 @@ var testAllFieldsYAML []byte func TestFile(t *testing.T) { _, err := validate(testAllFieldsYAML) - ExpectNoError(t, err) + expect.NoError(t, err) } diff --git a/internal/route/provider/provider.go b/internal/route/provider/provider.go index 05099f4a..61e25c26 100644 --- a/internal/route/provider/provider.go +++ b/internal/route/provider/provider.go @@ -13,14 +13,14 @@ import ( "github.com/yusing/godoxy/agent/pkg/agent" "github.com/yusing/godoxy/internal/common" "github.com/yusing/godoxy/internal/docker" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/route" provider "github.com/yusing/godoxy/internal/route/provider/types" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" W "github.com/yusing/godoxy/internal/watcher" "github.com/yusing/godoxy/internal/watcher/events" "github.com/yusing/goutils/env" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) type ( @@ -66,7 +66,7 @@ func NewFileProvider(filename string) (p *Provider, err error) { return nil, err } p.watcher = p.NewWatcher() - return + return p, err } func NewDockerProvider(name string, dockerHost string) *Provider { @@ -146,7 +146,7 @@ func (p *Provider) Start(parent task.Parent) gperr.Error { func (p *Provider) LoadRoutes() (err gperr.Error) { p.routes, err = p.loadRoutes() - return + return err } func (p *Provider) NumRoutes() int { diff --git a/internal/route/reverse_proxy.go b/internal/route/reverse_proxy.go index a97011d1..6cee411d 100755 --- a/internal/route/reverse_proxy.go +++ b/internal/route/reverse_proxy.go @@ -6,7 +6,6 @@ import ( "github.com/yusing/godoxy/agent/pkg/agent" "github.com/yusing/godoxy/agent/pkg/agentproxy" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/homepage" "github.com/yusing/godoxy/internal/idlewatcher" "github.com/yusing/godoxy/internal/logging/accesslog" @@ -15,11 +14,12 @@ import ( "github.com/yusing/godoxy/internal/net/gphttp/middleware" nettypes "github.com/yusing/godoxy/internal/net/types" "github.com/yusing/godoxy/internal/route/routes" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" "github.com/yusing/godoxy/internal/watcher/health/monitor" "github.com/yusing/godoxy/pkg" + gperr "github.com/yusing/goutils/errs" "github.com/yusing/goutils/http/reverseproxy" + "github.com/yusing/goutils/task" ) type ReveseProxyRoute struct { diff --git a/internal/route/route.go b/internal/route/route.go index 2fafe066..bae72fe7 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -12,14 +12,14 @@ import ( "github.com/rs/zerolog/log" "github.com/yusing/godoxy/agent/pkg/agent" "github.com/yusing/godoxy/internal/docker" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/homepage" netutils "github.com/yusing/godoxy/internal/net" nettypes "github.com/yusing/godoxy/internal/net/types" "github.com/yusing/godoxy/internal/proxmox" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" + "github.com/yusing/goutils/task" "github.com/yusing/godoxy/internal/common" config "github.com/yusing/godoxy/internal/config/types" @@ -721,5 +721,5 @@ func preferredPort(portMapping map[int]container.Port) (res int) { res = port } } - return + return res } diff --git a/internal/route/route_test.go b/internal/route/route_test.go index b19a5ee1..63ce73d6 100644 --- a/internal/route/route_test.go +++ b/internal/route/route_test.go @@ -7,7 +7,7 @@ import ( "github.com/yusing/godoxy/internal/common" route "github.com/yusing/godoxy/internal/route/types" "github.com/yusing/godoxy/internal/types" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestRouteValidate(t *testing.T) { diff --git a/internal/route/rules/do.go b/internal/route/rules/do.go index 4936d20d..1eae30c0 100644 --- a/internal/route/rules/do.go +++ b/internal/route/rules/do.go @@ -6,9 +6,9 @@ import ( "strconv" "strings" - "github.com/yusing/godoxy/internal/gperr" gphttp "github.com/yusing/godoxy/internal/net/gphttp" nettypes "github.com/yusing/godoxy/internal/net/types" + gperr "github.com/yusing/goutils/errs" "github.com/yusing/goutils/http/reverseproxy" strutils "github.com/yusing/goutils/strings" ) diff --git a/internal/route/rules/do_test.go b/internal/route/rules/do_test.go index 87c19f29..16b84efc 100644 --- a/internal/route/rules/do_test.go +++ b/internal/route/rules/do_test.go @@ -3,7 +3,7 @@ package rules import ( "testing" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestParseCommands(t *testing.T) { @@ -131,9 +131,9 @@ func TestParseCommands(t *testing.T) { cmd := Command{} err := cmd.Parse(tt.input) if tt.wantErr != nil { - ExpectError(t, tt.wantErr, err) + expect.ErrorIs(t, tt.wantErr, err) } else { - ExpectNoError(t, err) + expect.NoError(t, err) } }) } diff --git a/internal/route/rules/errors.go b/internal/route/rules/errors.go index bae209f1..789e85d7 100644 --- a/internal/route/rules/errors.go +++ b/internal/route/rules/errors.go @@ -1,7 +1,7 @@ package rules import ( - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) var ( diff --git a/internal/route/rules/on.go b/internal/route/rules/on.go index 3149588a..ad2f6447 100644 --- a/internal/route/rules/on.go +++ b/internal/route/rules/on.go @@ -2,14 +2,13 @@ package rules import ( "net/http" + "slices" "strings" - "slices" - "github.com/gobwas/glob" - "github.com/yusing/godoxy/internal/gperr" nettypes "github.com/yusing/godoxy/internal/net/types" "github.com/yusing/godoxy/internal/route/routes" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" ) @@ -248,8 +247,10 @@ var checkers = map[string]struct { }, } -var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1} -var andSeps = [256]uint8{'&': 1, '\n': 1} +var ( + asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1} + andSeps = [256]uint8{'&': 1, '\n': 1} +) func indexAnd(s string) int { for i, c := range s { diff --git a/internal/route/rules/on_internal_test.go b/internal/route/rules/on_internal_test.go index 9fb349c8..2d8ed89a 100644 --- a/internal/route/rules/on_internal_test.go +++ b/internal/route/rules/on_internal_test.go @@ -3,8 +3,8 @@ package rules import ( "testing" - "github.com/yusing/godoxy/internal/gperr" - expect "github.com/yusing/godoxy/internal/utils/testing" + gperr "github.com/yusing/goutils/errs" + expect "github.com/yusing/goutils/testing" ) func TestSplitAnd(t *testing.T) { diff --git a/internal/route/rules/on_test.go b/internal/route/rules/on_test.go index 32af7b90..3061926c 100644 --- a/internal/route/rules/on_test.go +++ b/internal/route/rules/on_test.go @@ -10,7 +10,7 @@ import ( "github.com/yusing/godoxy/internal/route" "github.com/yusing/godoxy/internal/route/routes" . "github.com/yusing/godoxy/internal/route/rules" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" "golang.org/x/crypto/bcrypt" ) diff --git a/internal/route/rules/parser.go b/internal/route/rules/parser.go index c3a48931..ac04a2ff 100644 --- a/internal/route/rules/parser.go +++ b/internal/route/rules/parser.go @@ -4,7 +4,7 @@ import ( "bytes" "unicode" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) var escapedChars = map[rune]rune{ @@ -57,7 +57,7 @@ func parse(v string) (subject string, args []string, err gperr.Error) { buf.WriteRune(ch) } else { err = ErrUnsupportedEscapeChar.Subjectf("\\%c", r) - return + return subject, args, err } escaped = false continue @@ -93,5 +93,5 @@ func parse(v string) (subject string, args []string, err gperr.Error) { } else { flush(false) } - return + return subject, args, err } diff --git a/internal/route/rules/parser_test.go b/internal/route/rules/parser_test.go index b8cb054c..0ac3ec7d 100644 --- a/internal/route/rules/parser_test.go +++ b/internal/route/rules/parser_test.go @@ -4,8 +4,8 @@ import ( "strconv" "testing" - "github.com/yusing/godoxy/internal/gperr" - . "github.com/yusing/godoxy/internal/utils/testing" + gperr "github.com/yusing/goutils/errs" + expect "github.com/yusing/goutils/testing" ) func TestParser(t *testing.T) { @@ -68,15 +68,15 @@ func TestParser(t *testing.T) { t.Run(tt.name, func(t *testing.T) { subject, args, err := parse(tt.input) if tt.wantErr != nil { - ExpectError(t, tt.wantErr, err) + expect.ErrorIs(t, tt.wantErr, err) return } // t.Log(subject, args, err) - ExpectNoError(t, err) - ExpectEqual(t, subject, tt.subject) - ExpectEqual(t, len(args), len(tt.args)) + expect.NoError(t, err) + expect.Equal(t, subject, tt.subject) + expect.Equal(t, len(args), len(tt.args)) for i, arg := range args { - ExpectEqual(t, arg, tt.args[i]) + expect.Equal(t, arg, tt.args[i]) } }) } @@ -89,7 +89,7 @@ func TestParser(t *testing.T) { for i, test := range tests { t.Run(strconv.Itoa(i), func(t *testing.T) { _, _, err := parse(test) - ExpectError(t, ErrUnterminatedQuotes, err) + expect.ErrorIs(t, ErrUnterminatedQuotes, err) }) } }) diff --git a/internal/route/rules/rules.go b/internal/route/rules/rules.go index 540cbc54..f90ce5c5 100644 --- a/internal/route/rules/rules.go +++ b/internal/route/rules/rules.go @@ -130,5 +130,5 @@ func (rule *Rule) Check(cached Cache, r *http.Request) bool { func (rule *Rule) Handle(cached Cache, w http.ResponseWriter, r *http.Request) (proceed bool) { proceed = rule.Do.exec.Handle(cached, w, r) - return + return proceed } diff --git a/internal/route/rules/rules_test.go b/internal/route/rules/rules_test.go index c620bc0b..1bc93ff6 100644 --- a/internal/route/rules/rules_test.go +++ b/internal/route/rules/rules_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/yusing/godoxy/internal/serialization" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestParseRule(t *testing.T) { @@ -29,18 +29,18 @@ func TestParseRule(t *testing.T) { Rules Rules } err := serialization.MapUnmarshalValidate(serialization.SerializedObject{"rules": test}, &rules) - ExpectNoError(t, err) - ExpectEqual(t, len(rules.Rules), len(test)) - ExpectEqual(t, rules.Rules[0].Name, "test") - ExpectEqual(t, rules.Rules[0].On.String(), "method POST") - ExpectEqual(t, rules.Rules[0].Do.String(), "error 403 Forbidden") + expect.NoError(t, err) + expect.Equal(t, len(rules.Rules), len(test)) + expect.Equal(t, rules.Rules[0].Name, "test") + expect.Equal(t, rules.Rules[0].On.String(), "method POST") + expect.Equal(t, rules.Rules[0].Do.String(), "error 403 Forbidden") - ExpectEqual(t, rules.Rules[1].Name, "auth") - ExpectEqual(t, rules.Rules[1].On.String(), `basic_auth "username" "password" | basic_auth username2 "password2" | basic_auth "username3" "password3"`) - ExpectEqual(t, rules.Rules[1].Do.String(), "bypass") + expect.Equal(t, rules.Rules[1].Name, "auth") + expect.Equal(t, rules.Rules[1].On.String(), `basic_auth "username" "password" | basic_auth username2 "password2" | basic_auth "username3" "password3"`) + expect.Equal(t, rules.Rules[1].Do.String(), "bypass") - ExpectEqual(t, rules.Rules[2].Name, "default") - ExpectEqual(t, rules.Rules[2].Do.String(), "require_basic_auth any_realm") + expect.Equal(t, rules.Rules[2].Name, "default") + expect.Equal(t, rules.Rules[2].Do.String(), "require_basic_auth any_realm") } // TODO: real tests. diff --git a/internal/route/rules/validate.go b/internal/route/rules/validate.go index 389c49c4..0736089f 100644 --- a/internal/route/rules/validate.go +++ b/internal/route/rules/validate.go @@ -8,9 +8,9 @@ import ( "strings" "github.com/gobwas/glob" - "github.com/yusing/godoxy/internal/gperr" gphttp "github.com/yusing/godoxy/internal/net/gphttp" nettypes "github.com/yusing/godoxy/internal/net/types" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/route/stream.go b/internal/route/stream.go index 82a69db8..a1f98f0c 100755 --- a/internal/route/stream.go +++ b/internal/route/stream.go @@ -7,14 +7,14 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/idlewatcher" nettypes "github.com/yusing/godoxy/internal/net/types" "github.com/yusing/godoxy/internal/route/routes" "github.com/yusing/godoxy/internal/route/stream" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" "github.com/yusing/godoxy/internal/watcher/health/monitor" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) // TODO: support stream load balance. diff --git a/internal/route/stream/tcp_tcp.go b/internal/route/stream/tcp_tcp.go index d32ab4ec..a260b92e 100644 --- a/internal/route/stream/tcp_tcp.go +++ b/internal/route/stream/tcp_tcp.go @@ -168,12 +168,12 @@ type wrapperConn struct { func (w *wrapperConn) Read(b []byte) (n int, err error) { n, err = w.Conn.Read(b) if err != nil { - return + return n, err } if w.onRead != nil { if err = w.onRead(w.ctx); err != nil { - return + return n, err } } - return + return n, err } diff --git a/internal/route/types/http_config.go b/internal/route/types/http_config.go index 3a975539..03a65dde 100644 --- a/internal/route/types/http_config.go +++ b/internal/route/types/http_config.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type HTTPConfig struct { diff --git a/internal/route/types/http_config_test.go b/internal/route/types/http_config_test.go index 310f5243..b11b22ed 100644 --- a/internal/route/types/http_config_test.go +++ b/internal/route/types/http_config_test.go @@ -7,7 +7,7 @@ import ( . "github.com/yusing/godoxy/internal/route" route "github.com/yusing/godoxy/internal/route/types" "github.com/yusing/godoxy/internal/serialization" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestHTTPConfigDeserialize(t *testing.T) { diff --git a/internal/route/types/port.go b/internal/route/types/port.go index 8d88b82b..01f79013 100644 --- a/internal/route/types/port.go +++ b/internal/route/types/port.go @@ -3,7 +3,7 @@ package route import ( "strconv" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" ) diff --git a/internal/route/types/scheme.go b/internal/route/types/scheme.go index ca59be1a..1b2e33e4 100644 --- a/internal/route/types/scheme.go +++ b/internal/route/types/scheme.go @@ -1,7 +1,7 @@ package route import ( - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type Scheme string diff --git a/internal/serialization/serialization.go b/internal/serialization/serialization.go index 99eb536d..7da99008 100644 --- a/internal/serialization/serialization.go +++ b/internal/serialization/serialization.go @@ -13,8 +13,8 @@ import ( "github.com/go-playground/validator/v10" "github.com/goccy/go-yaml" "github.com/puzpuzpuz/xsync/v4" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/utils" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" ) @@ -146,7 +146,7 @@ func dive(dst reflect.Value) (v reflect.Value, t reflect.Type, err gperr.Error) if dst.IsNil() { if !dst.CanSet() { err = gperr.Errorf("dive: dst is %w and is not settable", ErrNilValue) - return + return v, t, err } dst.Set(New(dstT.Elem())) } @@ -437,20 +437,20 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe } if dst.Kind() == reflect.String { dst.SetString(src) - return + return convertible, convErr } switch dstT { case reflect.TypeFor[time.Duration](): if src == "" { dst.Set(reflect.Zero(dstT)) - return + return convertible, convErr } d, err := time.ParseDuration(src) if err != nil { return true, gperr.Wrap(err) } dst.Set(reflect.ValueOf(d)) - return + return convertible, convErr default: } if dstKind := dst.Kind(); isIntFloat(dstKind) { @@ -470,7 +470,7 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe return true, gperr.Wrap(err) } dst.Set(reflect.ValueOf(i).Convert(dstT)) - return + return convertible, convErr } // check if (*T).Convertor is implemented if parser, ok := dst.Addr().Interface().(strutils.Parser); ok { @@ -496,7 +496,7 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe if errs.HasError() { return true, errs.Error() } - return + return convertible, convErr } sl := make([]any, 0) err := yaml.Unmarshal([]byte(src), &sl) diff --git a/internal/serialization/serialization_test.go b/internal/serialization/serialization_test.go index c63d986a..61c27748 100644 --- a/internal/serialization/serialization_test.go +++ b/internal/serialization/serialization_test.go @@ -8,7 +8,7 @@ import ( "github.com/goccy/go-yaml" "github.com/stretchr/testify/require" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestDeserialize(t *testing.T) { @@ -43,8 +43,8 @@ func TestDeserialize(t *testing.T) { t.Run("deserialize", func(t *testing.T) { var s2 S err := MapUnmarshalValidate(testStructSerialized, &s2) - ExpectNoError(t, err) - ExpectEqual(t, s2, testStruct) + expect.NoError(t, err) + expect.Equal(t, s2, testStruct) }) } @@ -63,16 +63,16 @@ func TestDeserializeAnonymousField(t *testing.T) { // all, anon := extractFields(reflect.TypeOf(s2)) // t.Fatalf("anon %v, all %v", anon, all) err := MapUnmarshalValidate(map[string]any{"a": 1, "b": 2, "c": 3}, &s) - ExpectNoError(t, err) - ExpectEqual(t, s.A, 1) - ExpectEqual(t, s.B, 2) - ExpectEqual(t, s.C, 3) + expect.NoError(t, err) + expect.Equal(t, s.A, 1) + expect.Equal(t, s.B, 2) + expect.Equal(t, s.C, 3) err = MapUnmarshalValidate(map[string]any{"a": 1, "b": 2, "c": 3}, &s2) - ExpectNoError(t, err) - ExpectEqual(t, s2.A, 1) - ExpectEqual(t, s2.B, 2) - ExpectEqual(t, s2.C, 3) + expect.NoError(t, err) + expect.Equal(t, s2.A, 1) + expect.Equal(t, s2.B, 2) + expect.Equal(t, s2.C, 3) } func TestPointerPrimitives(t *testing.T) { @@ -90,44 +90,44 @@ func TestPointerPrimitives(t *testing.T) { var test testType err := MapUnmarshalValidate(map[string]any{"b": true, "i8": int8(127), "i16": int16(127), "i32": int32(127), "i64": int64(127), "u8": uint8(127), "u16": uint16(127), "u32": uint32(127), "u64": uint64(127)}, &test) - ExpectNoError(t, err) - ExpectEqual(t, *test.B, true) - ExpectEqual(t, *test.I8, int8(127)) - ExpectEqual(t, *test.I16, int16(127)) - ExpectEqual(t, *test.I32, int32(127)) - ExpectEqual(t, *test.I64, int64(127)) - ExpectEqual(t, *test.U8, uint8(127)) - ExpectEqual(t, *test.U16, uint16(127)) - ExpectEqual(t, *test.U32, uint32(127)) - ExpectEqual(t, *test.U64, uint64(127)) + expect.NoError(t, err) + expect.Equal(t, *test.B, true) + expect.Equal(t, *test.I8, int8(127)) + expect.Equal(t, *test.I16, int16(127)) + expect.Equal(t, *test.I32, int32(127)) + expect.Equal(t, *test.I64, int64(127)) + expect.Equal(t, *test.U8, uint8(127)) + expect.Equal(t, *test.U16, uint16(127)) + expect.Equal(t, *test.U32, uint32(127)) + expect.Equal(t, *test.U64, uint64(127)) // zero values err = MapUnmarshalValidate(map[string]any{"b": false, "i8": int8(0), "i16": int16(0), "i32": int32(0), "i64": int64(0), "u8": uint8(0), "u16": uint16(0), "u32": uint32(0), "u64": uint64(0)}, &test) - ExpectNoError(t, err) - ExpectEqual(t, *test.B, false) - ExpectEqual(t, *test.I8, int8(0)) - ExpectEqual(t, *test.I16, int16(0)) - ExpectEqual(t, *test.I32, int32(0)) - ExpectEqual(t, *test.I64, int64(0)) - ExpectEqual(t, *test.U8, uint8(0)) - ExpectEqual(t, *test.U16, uint16(0)) - ExpectEqual(t, *test.U32, uint32(0)) - ExpectEqual(t, *test.U64, uint64(0)) + expect.NoError(t, err) + expect.Equal(t, *test.B, false) + expect.Equal(t, *test.I8, int8(0)) + expect.Equal(t, *test.I16, int16(0)) + expect.Equal(t, *test.I32, int32(0)) + expect.Equal(t, *test.I64, int64(0)) + expect.Equal(t, *test.U8, uint8(0)) + expect.Equal(t, *test.U16, uint16(0)) + expect.Equal(t, *test.U32, uint32(0)) + expect.Equal(t, *test.U64, uint64(0)) // nil values err = MapUnmarshalValidate(map[string]any{"b": true, "i8": int8(127), "i16": int16(127), "i32": int32(127), "i64": int64(127), "u8": uint8(127), "u16": uint16(127), "u32": uint32(127), "u64": uint64(127)}, &test) - ExpectNoError(t, err) + expect.NoError(t, err) err = MapUnmarshalValidate(map[string]any{"b": nil, "i8": nil, "i16": nil, "i32": nil, "i64": nil, "u8": nil, "u16": nil, "u32": nil, "u64": nil}, &test) - ExpectNoError(t, err) - ExpectEqual(t, test.B, nil) - ExpectEqual(t, test.I8, nil) - ExpectEqual(t, test.I16, nil) - ExpectEqual(t, test.I32, nil) - ExpectEqual(t, test.I64, nil) - ExpectEqual(t, test.U8, nil) - ExpectEqual(t, test.U16, nil) - ExpectEqual(t, test.U32, nil) - ExpectEqual(t, test.U64, nil) + expect.NoError(t, err) + expect.Equal(t, test.B, nil) + expect.Equal(t, test.I8, nil) + expect.Equal(t, test.I16, nil) + expect.Equal(t, test.I32, nil) + expect.Equal(t, test.I64, nil) + expect.Equal(t, test.U8, nil) + expect.Equal(t, test.U16, nil) + expect.Equal(t, test.U32, nil) + expect.Equal(t, test.U64, nil) } func TestStringIntConvert(t *testing.T) { @@ -146,44 +146,44 @@ func TestStringIntConvert(t *testing.T) { ok, err := ConvertString(s, reflect.ValueOf(&test.i8)) - ExpectTrue(t, ok) - ExpectNoError(t, err) - ExpectEqual(t, test.i8, int8(127)) + expect.True(t, ok) + expect.NoError(t, err) + expect.Equal(t, test.i8, int8(127)) ok, err = ConvertString(s, reflect.ValueOf(&test.i16)) - ExpectTrue(t, ok) - ExpectNoError(t, err) - ExpectEqual(t, test.i16, int16(127)) + expect.True(t, ok) + expect.NoError(t, err) + expect.Equal(t, test.i16, int16(127)) ok, err = ConvertString(s, reflect.ValueOf(&test.i32)) - ExpectTrue(t, ok) - ExpectNoError(t, err) - ExpectEqual(t, test.i32, int32(127)) + expect.True(t, ok) + expect.NoError(t, err) + expect.Equal(t, test.i32, int32(127)) ok, err = ConvertString(s, reflect.ValueOf(&test.i64)) - ExpectTrue(t, ok) - ExpectNoError(t, err) - ExpectEqual(t, test.i64, int64(127)) + expect.True(t, ok) + expect.NoError(t, err) + expect.Equal(t, test.i64, int64(127)) ok, err = ConvertString(s, reflect.ValueOf(&test.u8)) - ExpectTrue(t, ok) - ExpectNoError(t, err) - ExpectEqual(t, test.u8, uint8(127)) + expect.True(t, ok) + expect.NoError(t, err) + expect.Equal(t, test.u8, uint8(127)) ok, err = ConvertString(s, reflect.ValueOf(&test.u16)) - ExpectTrue(t, ok) - ExpectNoError(t, err) - ExpectEqual(t, test.u16, uint16(127)) + expect.True(t, ok) + expect.NoError(t, err) + expect.Equal(t, test.u16, uint16(127)) ok, err = ConvertString(s, reflect.ValueOf(&test.u32)) - ExpectTrue(t, ok) - ExpectNoError(t, err) - ExpectEqual(t, test.u32, uint32(127)) + expect.True(t, ok) + expect.NoError(t, err) + expect.Equal(t, test.u32, uint32(127)) ok, err = ConvertString(s, reflect.ValueOf(&test.u64)) - ExpectTrue(t, ok) - ExpectNoError(t, err) - ExpectEqual(t, test.u64, uint64(127)) + expect.True(t, ok) + expect.NoError(t, err) + expect.Equal(t, test.u64, uint64(127)) } type testModel struct { @@ -199,33 +199,33 @@ type testType struct { func (c *testType) Parse(v string) (err error) { c.bar = v c.foo, err = strconv.Atoi(v) - return + return err } func TestConvertor(t *testing.T) { t.Run("valid", func(t *testing.T) { m := new(testModel) - ExpectNoError(t, MapUnmarshalValidate(map[string]any{"Test": "123"}, m)) + expect.NoError(t, MapUnmarshalValidate(map[string]any{"Test": "123"}, m)) - ExpectEqual(t, m.Test.foo, 123) - ExpectEqual(t, m.Test.bar, "123") + expect.Equal(t, m.Test.foo, 123) + expect.Equal(t, m.Test.bar, "123") }) t.Run("int_to_string", func(t *testing.T) { m := new(testModel) - ExpectNoError(t, MapUnmarshalValidate(map[string]any{"Test": "123"}, m)) + expect.NoError(t, MapUnmarshalValidate(map[string]any{"Test": "123"}, m)) - ExpectEqual(t, m.Test.foo, 123) - ExpectEqual(t, m.Test.bar, "123") + expect.Equal(t, m.Test.foo, 123) + expect.Equal(t, m.Test.bar, "123") - ExpectNoError(t, MapUnmarshalValidate(map[string]any{"Baz": 123}, m)) - ExpectEqual(t, m.Baz, "123") + expect.NoError(t, MapUnmarshalValidate(map[string]any{"Baz": 123}, m)) + expect.Equal(t, m.Baz, "123") }) t.Run("invalid", func(t *testing.T) { m := new(testModel) err := MapUnmarshalValidate(map[string]any{"Test": struct{ a int }{1}}, m) - ExpectError(t, ErrUnsupportedConversion, err) + expect.ErrorIs(t, ErrUnsupportedConversion, err) }) t.Run("set_empty", func(t *testing.T) { @@ -233,8 +233,8 @@ func TestConvertor(t *testing.T) { Test: testType{1, "2"}, Baz: "3", } - ExpectNoError(t, MapUnmarshalValidate(map[string]any{"Test": nil, "Baz": nil}, &m)) - ExpectEqual(t, m, testModel{}) + expect.NoError(t, MapUnmarshalValidate(map[string]any{"Test": nil, "Baz": nil}, &m)) + expect.Equal(t, m, testModel{}) }) } @@ -242,23 +242,23 @@ func TestStringToSlice(t *testing.T) { t.Run("comma_separated", func(t *testing.T) { dst := make([]string, 0) convertible, err := ConvertString("a,b,c", reflect.ValueOf(&dst)) - ExpectTrue(t, convertible) - ExpectNoError(t, err) - ExpectEqual(t, dst, []string{"a", "b", "c"}) + expect.True(t, convertible) + expect.NoError(t, err) + expect.Equal(t, dst, []string{"a", "b", "c"}) }) t.Run("yaml-like", func(t *testing.T) { dst := make([]string, 0) convertible, err := ConvertString("- a\n- b\n- c", reflect.ValueOf(&dst)) - ExpectTrue(t, convertible) - ExpectNoError(t, err) - ExpectEqual(t, dst, []string{"a", "b", "c"}) + expect.True(t, convertible) + expect.NoError(t, err) + expect.Equal(t, dst, []string{"a", "b", "c"}) }) t.Run("single-line-yaml-like", func(t *testing.T) { dst := make([]string, 0) convertible, err := ConvertString("- a", reflect.ValueOf(&dst)) - ExpectTrue(t, convertible) - ExpectNoError(t, err) - ExpectEqual(t, dst, []string{"a"}) + expect.True(t, convertible) + expect.NoError(t, err) + expect.Equal(t, dst, []string{"a"}) }) } @@ -280,9 +280,9 @@ func TestStringToMap(t *testing.T) { t.Run("yaml-like", func(t *testing.T) { dst := make(map[string]string) convertible, err := ConvertString(" a: b\n c: d", reflect.ValueOf(&dst)) - ExpectTrue(t, convertible) - ExpectNoError(t, err) - ExpectEqual(t, dst, map[string]string{"a": "b", "c": "d"}) + expect.True(t, convertible) + expect.NoError(t, err) + expect.Equal(t, dst, map[string]string{"a": "b", "c": "d"}) }) } @@ -307,9 +307,9 @@ func TestStringToStruct(t *testing.T) { B int }{} convertible, err := ConvertString(" A: a\n B: 123", reflect.ValueOf(&dst)) - ExpectTrue(t, convertible) - ExpectNoError(t, err) - ExpectEqual(t, dst, struct { + expect.True(t, convertible) + expect.NoError(t, err) + expect.Equal(t, dst, struct { A string B int }{"a", 123}) diff --git a/internal/serialization/time_test.go b/internal/serialization/time_test.go index ce1c4f87..fabb12bc 100644 --- a/internal/serialization/time_test.go +++ b/internal/serialization/time_test.go @@ -5,7 +5,7 @@ import ( "time" "github.com/stretchr/testify/require" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) // NOTE: -ldflags=-checklinkname=0 is required to test this function diff --git a/internal/serialization/validation.go b/internal/serialization/validation.go index 1ace564e..058fa9a0 100644 --- a/internal/serialization/validation.go +++ b/internal/serialization/validation.go @@ -2,7 +2,7 @@ package serialization import ( "github.com/go-playground/validator/v10" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) var validate = validator.New() diff --git a/internal/task/debug.go b/internal/task/debug.go deleted file mode 100644 index d4f0cd0c..00000000 --- a/internal/task/debug.go +++ /dev/null @@ -1,66 +0,0 @@ -package task - -import ( - "fmt" - - "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/gperr" -) - -// debug only. -func listStuckedCallbacks(t *Task) []string { - callbacks := make([]string, 0) - if t.onFinish != nil { - for c := range t.onFinish.Range { - callbacks = append(callbacks, c.about) - } - } - if t.onCancel != nil { - for c := range t.onCancel.Range { - callbacks = append(callbacks, c.about) - } - } - if t.children != nil { - for c := range t.children.Range { - callbacks = append(callbacks, listStuckedCallbacks(c)...) - } - } - return callbacks -} - -// debug only. -func listStuckedChildren(t *Task) []string { - if t.children != nil { - children := make([]string, 0) - for c := range t.children.Range { - children = append(children, c.String()) - children = append(children, listStuckedCallbacks(c)...) - } - return children - } - return nil -} - -func (t *Task) reportStucked() { - callbacks := listStuckedCallbacks(t) - children := listStuckedChildren(t) - if len(callbacks) == 0 && len(children) == 0 { - return - } - fmtOutput := gperr.NewBuilder(fmt.Sprintf("%s stucked callbacks: %d, stucked children: %d", t.String(), len(callbacks), len(children))) - if len(callbacks) > 0 { - callbackBuilder := gperr.NewBuilder("callbacks") - for _, c := range callbacks { - callbackBuilder.Adds(c) - } - fmtOutput.Add(callbackBuilder.Error()) - } - if len(children) > 0 { - childrenBuilder := gperr.NewBuilder("children") - for _, c := range children { - childrenBuilder.Adds(c) - } - fmtOutput.Add(childrenBuilder.Error()) - } - log.Warn().Msg(fmtOutput.String()) -} diff --git a/internal/task/task.go b/internal/task/task.go deleted file mode 100644 index 69e154ea..00000000 --- a/internal/task/task.go +++ /dev/null @@ -1,246 +0,0 @@ -package task - -import ( - "context" - "sync" - "time" - - "github.com/yusing/godoxy/internal/gperr" -) - -type ( - TaskStarter interface { - // Start starts the object that implements TaskStarter, - // and returns an error if it fails to start. - // - // callerSubtask.Finish must be called when start fails or the object is finished. - Start(parent Parent) gperr.Error - Task() *Task - } - TaskFinisher interface { - Finish(reason any) - } - Callback struct { - fn func() - about string - } - // Task controls objects' lifetime. - // - // Objects that uses a Task should implement the TaskStarter and the TaskFinisher interface. - // - // Use Task.Finish to stop all subtasks of the Task. - Task struct { - parent *Task - name string - ctx context.Context - cancel context.CancelCauseFunc - done chan struct{} - finishCalled bool - onCancel *withWg[*Callback] - onFinish *withWg[*Callback] - children *withWg[*Task] - - mu sync.Mutex - } - Parent interface { - Context() context.Context - // Subtask returns a new subtask with the given name, derived from the parent's context. - // - // This should not be called after Finish is called on the task or its parent task. - Subtask(name string, needFinish bool) *Task - Name() string - Finish(reason any) - OnCancel(name string, f func()) - } -) - -const taskTimeout = 3 * time.Second - -func (t *Task) Context() context.Context { - return t.ctx -} - -func (t *Task) Name() string { - return t.name -} - -// String returns the full name of the task. -func (t *Task) String() string { - return t.fullName() -} - -// MarshalText implements encoding.TextMarshaler. -func (t *Task) MarshalText() ([]byte, error) { - return []byte(t.fullName()), nil -} - -// Finish marks the task as finished, with the given reason (if any). -func (t *Task) Finish(reason any) { - t.finish(reason, false) -} - -// FinishCause returns the reason / error that caused the task to be finished. -func (t *Task) FinishCause() error { - return context.Cause(t.ctx) -} - -// FinishAndWait cancel all subtasks and wait for them to finish, -// then marks the task as finished, with the given reason (if any). -func (t *Task) FinishAndWait(reason any) { - t.finish(reason, true) -} - -// OnFinished calls fn when the task is canceled and all subtasks are finished. -// -// It should not be called after Finish is called. -func (t *Task) OnFinished(about string, fn func()) { - if !t.needFinish() { - t.OnCancel(about, fn) - return - } - - t.mu.Lock() - if t.onFinish == nil { - t.onFinish = newWithWg[*Callback]() - t.mu.Unlock() - - go func() { - <-t.ctx.Done() - <-t.done - for cb := range t.onFinish.Range { - go func(cb *Callback) { - invokeWithRecover(cb) - t.onFinish.Delete(cb) - }(cb) - } - }() - } else { - t.mu.Unlock() - } - - t.onFinish.Add(&Callback{fn: fn, about: about}) -} - -// OnCancel calls fn when the task is canceled. -// -// It should not be called after Finish is called. -func (t *Task) OnCancel(about string, fn func()) { - t.mu.Lock() - if t.onCancel == nil { - t.onCancel = newWithWg[*Callback]() - t.mu.Unlock() - - go func() { - <-t.ctx.Done() - for cb := range t.onCancel.Range { - go func(cb *Callback) { - invokeWithRecover(cb) - t.onCancel.Delete(cb) - }(cb) - } - }() - } else { - t.mu.Unlock() - } - - t.onCancel.Add(&Callback{fn: fn, about: about}) -} - -// Subtask returns a new subtask with the given name, derived from the parent's context. -// -// This should not be called after Finish is called on the task or its parent task. -func (t *Task) Subtask(name string, needFinish bool) *Task { - t.mu.Lock() - if t.children == nil { - t.children = newWithWg[*Task]() - t.mu.Unlock() - } else { - t.mu.Unlock() - } - - child := &Task{ - name: name, - parent: t, - } - - t.children.Add(child) - - child.ctx, child.cancel = context.WithCancelCause(t.ctx) - - if needFinish { - child.done = make(chan struct{}) - } else { - child.done = closedCh - go func() { - <-child.ctx.Done() - child.Finish(t.FinishCause()) - }() - } - - logStarted(child) - return child -} - -func (t *Task) finish(reason any, wait bool) { - t.mu.Lock() - if t.finishCalled { - t.mu.Unlock() - // wait but not report stucked (again) - t.waitFinish(taskTimeout) - return - } - - t.finishCalled = true - t.mu.Unlock() - - if t.needFinish() { - close(t.done) - } - - t.cancel(fmtCause(reason)) - if wait && !t.waitFinish(taskTimeout) { - t.reportStucked() - } - if t != root { - t.parent.children.Delete(t) - } - logFinished(t) -} - -func (t *Task) waitFinish(timeout time.Duration) bool { - if t.children == nil && t.onCancel == nil && t.onFinish == nil { - return true - } - done := make(chan struct{}) - go func() { - if t.children != nil { - t.children.Wait() - } - if t.onCancel != nil { - t.onCancel.Wait() - } - if t.onFinish != nil { - t.onFinish.Wait() - } - <-t.done - close(done) - }() - timeoutCh := time.After(timeout) - select { - case <-done: - return true - case <-timeoutCh: - return false - } -} - -func (t *Task) fullName() string { - if t.parent == root { - return t.name - } - return t.parent.fullName() + "." + t.name -} - -func (t *Task) needFinish() bool { - return t.done != closedCh -} diff --git a/internal/task/task_debug.go b/internal/task/task_debug.go deleted file mode 100644 index 873853e9..00000000 --- a/internal/task/task_debug.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build debug - -package task - -import ( - "runtime/debug" - - "github.com/rs/zerolog/log" -) - -func panicWithDebugStack() { - panic(string(debug.Stack())) -} - -func logStarted(t *Task) { - log.Info().Msg("task " + t.String() + " started") -} - -func logFinished(t *Task) { - log.Info().Msg("task " + t.String() + " finished") -} diff --git a/internal/task/task_prod.go b/internal/task/task_prod.go deleted file mode 100644 index 90a18a8b..00000000 --- a/internal/task/task_prod.go +++ /dev/null @@ -1,15 +0,0 @@ -//go:build !debug - -package task - -func panicWithDebugStack() { - // do nothing -} - -func logStarted(t *Task) { - // do nothing -} - -func logFinished(t *Task) { - // do nothing -} diff --git a/internal/task/task_test.go b/internal/task/task_test.go deleted file mode 100644 index 8501c43c..00000000 --- a/internal/task/task_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package task - -import ( - "context" - "sync" - "testing" - "time" - - expect "github.com/yusing/godoxy/internal/utils/testing" -) - -func testTask() *Task { - return RootTask("test", true) -} - -func TestChildTaskCancellation(t *testing.T) { - t.Cleanup(testCleanup) - - parent := testTask() - child := parent.Subtask("", true) - - go func() { - defer child.Finish(nil) - for { - select { - case <-child.Context().Done(): - return - default: - continue - } - } - }() - - parent.Finish(nil) // should also cancel child - - select { - case <-child.Context().Done(): - expect.ErrorIs(t, context.Canceled, child.Context().Err()) - default: - t.Fatal("subTask context was not canceled as expected") - } -} - -func TestTaskStuck(t *testing.T) { - t.Cleanup(testCleanup) - task := testTask() - task.OnCancel("second", func() { - time.Sleep(time.Second) - }) - done := make(chan struct{}) - go func() { - task.FinishAndWait(nil) - close(done) - }() - time.Sleep(time.Millisecond * 100) - select { - case <-done: - t.Fatal("task finished unexpectedly") - default: - } - time.Sleep(time.Second) - select { - case <-done: - default: - t.Fatal("task did not finish") - } -} - -func TestTaskOnCancelOnFinished(t *testing.T) { - t.Cleanup(testCleanup) - task := testTask() - - var shouldTrueOnCancel bool - var shouldTrueOnFinish bool - - task.OnCancel("", func() { - shouldTrueOnCancel = true - }) - task.OnFinished("", func() { - shouldTrueOnFinish = true - }) - - expect.False(t, shouldTrueOnFinish) - task.FinishAndWait(nil) - expect.True(t, shouldTrueOnCancel) - expect.True(t, shouldTrueOnFinish) -} - -func TestCommonFlowWithGracefulShutdown(t *testing.T) { - t.Cleanup(testCleanup) - task := testTask() - - finished := false - - task.OnFinished("", func() { - finished = true - }) - - go func() { - defer task.FinishAndWait(nil) - for { - select { - case <-task.Context().Done(): - return - default: - continue - } - } - }() - - expect.NoError(t, gracefulShutdown(1*time.Second)) - expect.True(t, finished) - - expect.ErrorIs(t, ErrProgramExiting, context.Cause(task.Context())) - expect.ErrorIs(t, context.Canceled, task.Context().Err()) - expect.ErrorIs(t, ErrProgramExiting, task.FinishCause()) -} - -func TestTimeoutOnGracefulShutdown(t *testing.T) { - t.Cleanup(testCleanup) - _ = testTask() - - expect.ErrorIs(t, context.DeadlineExceeded, gracefulShutdown(time.Millisecond)) -} - -func TestFinishMultipleCalls(t *testing.T) { - t.Cleanup(testCleanup) - task := testTask() - var wg sync.WaitGroup - n := 20 - for range n { - wg.Go(func() { - task.Finish(nil) - }) - } - wg.Wait() -} - -func BenchmarkTasksNoFinish(b *testing.B) { - for b.Loop() { - task := RootTask("", false) - task.Subtask("", false).Finish(nil) - task.Finish(nil) - } -} - -func BenchmarkTasksNeedFinish(b *testing.B) { - for b.Loop() { - task := testTask() - task.Subtask("", true).Finish(nil) - task.Finish(nil) - } -} - -func BenchmarkContextWithCancel(b *testing.B) { - for b.Loop() { - task, taskCancel := context.WithCancelCause(b.Context()) - taskCancel(nil) - <-task.Done() - } -} diff --git a/internal/task/utils.go b/internal/task/utils.go deleted file mode 100644 index 9135e5f5..00000000 --- a/internal/task/utils.go +++ /dev/null @@ -1,117 +0,0 @@ -package task - -import ( - "context" - "errors" - "fmt" - "os" - "os/signal" - "syscall" - "time" - - "github.com/rs/zerolog/log" -) - -var ErrProgramExiting = errors.New("program exiting") - -var root *Task - -var closedCh = make(chan struct{}) - -func init() { - close(closedCh) - initRoot() -} - -func initRoot() { - ctx, cancel := context.WithCancelCause(context.Background()) - root = &Task{ - name: "root", - ctx: ctx, - cancel: cancel, - done: closedCh, - } - root.parent = root -} - -func testCleanup() { - root.cancel(nil) - initRoot() -} - -// RootTask returns a new Task with the given name, derived from the root context. -// -//go:inline -func RootTask(name string, needFinish bool) *Task { - return root.Subtask(name, needFinish) -} - -func RootContext() context.Context { - return root.Context() -} - -func RootContextCanceled() <-chan struct{} { - return root.Context().Done() -} - -func OnProgramExit(about string, fn func()) { - root.OnCancel(about, fn) -} - -// WaitExit waits for a signal to shutdown the program, and then waits for all tasks to finish, up to the given timeout. -// -// If the timeout is exceeded, it prints a list of all tasks that were -// still running when the timeout was reached, and their current tree -// of subtasks. -func WaitExit(shutdownTimeout int) { - sig := make(chan os.Signal, 1) - signal.Notify(sig, syscall.SIGINT) - signal.Notify(sig, syscall.SIGTERM) - signal.Notify(sig, syscall.SIGHUP) - - // wait for signal - <-sig - - // gracefully shutdown - log.Info().Msg("shutting down") - if err := gracefulShutdown(time.Second * time.Duration(shutdownTimeout)); err != nil { - root.reportStucked() - } -} - -// gracefulShutdown waits for all tasks to finish, up to the given timeout. -// -// If the timeout is exceeded, it prints a list of all tasks that were -// still running when the timeout was reached, and their current tree -// of subtasks. -func gracefulShutdown(timeout time.Duration) error { - root.Finish(ErrProgramExiting) - if !root.waitFinish(timeout) { - return context.DeadlineExceeded - } - return nil -} - -func invokeWithRecover(cb *Callback) { - defer func() { - if err := recover(); err != nil { - log.Err(fmtCause(err)).Str("callback", cb.about).Msg("panic") - panicWithDebugStack() - } - }() - cb.fn() -} - -//go:inline -func fmtCause(cause any) error { - switch cause := cause.(type) { - case nil: - return nil - case error: - return cause - case string: - return errors.New(cause) - default: - return fmt.Errorf("%v", cause) - } -} diff --git a/internal/task/with.go b/internal/task/with.go deleted file mode 100644 index bfb47ada..00000000 --- a/internal/task/with.go +++ /dev/null @@ -1,48 +0,0 @@ -package task - -import ( - "sync" - - "github.com/puzpuzpuz/xsync/v4" -) - -type withWg[T comparable] struct { - m *xsync.Map[T, struct{}] - wg sync.WaitGroup -} - -func newWithWg[T comparable]() *withWg[T] { - return &withWg[T]{ - m: xsync.NewMap[T, struct{}](), - } -} - -func (w *withWg[T]) Add(ele T) { - w.wg.Add(1) - w.m.Store(ele, struct{}{}) -} - -func (w *withWg[T]) AddWithoutWG(ele T) { - w.m.Store(ele, struct{}{}) -} - -func (w *withWg[T]) Delete(key T) { - w.wg.Done() - w.m.Delete(key) -} - -func (w *withWg[T]) DeleteWithoutWG(key T) { - w.m.Delete(key) -} - -func (w *withWg[T]) Wait() { - w.wg.Wait() -} - -func (w *withWg[T]) Range(yield func(T) bool) { - for ele := range w.m.Range { - if !yield(ele) { - break - } - } -} diff --git a/internal/types/docker.go b/internal/types/docker.go index bdd54de7..be40e795 100644 --- a/internal/types/docker.go +++ b/internal/types/docker.go @@ -6,8 +6,8 @@ import ( "github.com/docker/docker/api/types/container" "github.com/yusing/ds/ordered" "github.com/yusing/godoxy/agent/pkg/agent" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/utils" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/types/health.go b/internal/types/health.go index e99192db..c9bbc085 100644 --- a/internal/types/health.go +++ b/internal/types/health.go @@ -7,8 +7,8 @@ import ( "strconv" "time" - "github.com/yusing/godoxy/internal/task" strutils "github.com/yusing/goutils/strings" + "github.com/yusing/goutils/task" ) type ( diff --git a/internal/types/idlewatcher.go b/internal/types/idlewatcher.go index a850dd5d..8ebb876b 100644 --- a/internal/types/idlewatcher.go +++ b/internal/types/idlewatcher.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/types/idlewatcher_test.go b/internal/types/idlewatcher_test.go index aac0af8e..df7cafb4 100644 --- a/internal/types/idlewatcher_test.go +++ b/internal/types/idlewatcher_test.go @@ -3,7 +3,7 @@ package types import ( "testing" - expect "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestValidateStartEndpoint(t *testing.T) { diff --git a/internal/types/routes.go b/internal/types/routes.go index 7b5e701c..4feed2c7 100644 --- a/internal/types/routes.go +++ b/internal/types/routes.go @@ -6,9 +6,9 @@ import ( "github.com/yusing/godoxy/agent/pkg/agent" "github.com/yusing/godoxy/internal/homepage" nettypes "github.com/yusing/godoxy/internal/net/types" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/utils/pool" "github.com/yusing/goutils/http/reverseproxy" + "github.com/yusing/goutils/task" ) type ( diff --git a/internal/utils/atomic/std.go b/internal/utils/atomic/std.go index a57315ad..97bbf851 100644 --- a/internal/utils/atomic/std.go +++ b/internal/utils/atomic/std.go @@ -2,6 +2,8 @@ package atomic import "sync/atomic" -type Bool = atomic.Bool -type Int32 = atomic.Int32 -type Int64 = atomic.Int64 +type ( + Bool = atomic.Bool + Int32 = atomic.Int32 + Int64 = atomic.Int64 +) diff --git a/internal/utils/go.mod b/internal/utils/go.mod index 526fa67c..53f36808 100644 --- a/internal/utils/go.mod +++ b/internal/utils/go.mod @@ -5,8 +5,7 @@ go 1.25.1 require ( github.com/puzpuzpuz/xsync/v4 v4.2.0 github.com/rs/zerolog v1.34.0 - github.com/stretchr/testify v1.11.1 - github.com/yusing/goutils v0.2.1 + github.com/yusing/goutils v0.3.1 go.uber.org/atomic v1.11.0 ) @@ -15,6 +14,7 @@ require ( github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/stretchr/testify v1.11.1 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/text v0.29.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/internal/utils/go.sum b/internal/utils/go.sum index 923171bb..5fa2ba31 100644 --- a/internal/utils/go.sum +++ b/internal/utils/go.sum @@ -19,8 +19,8 @@ github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/yusing/goutils v0.2.1 h1:KjoCrNO0otthaPCZPfQY+5GKsqs5+J77CxP+TNHYa/Y= -github.com/yusing/goutils v0.2.1/go.mod h1:v6RZsMRdzcts4udSg0vqUIFvaD0OaUMPTwYJZ4XnQYo= +github.com/yusing/goutils v0.3.1 h1:xCPoZ/haI8ZJ0ZaPU4g6+okSPdBczs8o98tIZ/TbpsQ= +github.com/yusing/goutils v0.3.1/go.mod h1:meg9GcAU8yvBY21JgYjPuLsXD1Q5VdVHE32A4tG5Y5g= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/utils/ref_count_test.go b/internal/utils/ref_count_test.go index 7eae0492..a40cc75b 100644 --- a/internal/utils/ref_count_test.go +++ b/internal/utils/ref_count_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestRefCounterAddSub(t *testing.T) { @@ -19,7 +19,7 @@ func TestRefCounterAddSub(t *testing.T) { } wg.Wait() - ExpectEqual(t, int(rc.refCount), 0) + expect.Equal(t, int(rc.refCount), 0) select { case <-rc.Zero(): @@ -44,7 +44,7 @@ func TestRefCounterMultipleAddSub(t *testing.T) { }() } wg.Wait() - ExpectEqual(t, int(rc.refCount), numAdds+1) + expect.Equal(t, int(rc.refCount), numAdds+1) wg.Add(numSubs) for range numSubs { @@ -54,7 +54,7 @@ func TestRefCounterMultipleAddSub(t *testing.T) { }() } wg.Wait() - ExpectEqual(t, int(rc.refCount), numAdds+1-numSubs) + expect.Equal(t, int(rc.refCount), numAdds+1-numSubs) rc.Sub() select { diff --git a/internal/utils/slices_test.go b/internal/utils/slices_test.go index 31dd4406..c405cfda 100644 --- a/internal/utils/slices_test.go +++ b/internal/utils/slices_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - . "github.com/yusing/godoxy/internal/utils/testing" + expect "github.com/yusing/goutils/testing" ) func TestIntersect(t *testing.T) { @@ -19,7 +19,7 @@ func TestIntersect(t *testing.T) { result := Intersect(slice1, slice2) slices.Sort(result) slices.Sort(want) - ExpectEqual(t, result, want) + expect.Equal(t, result, want) }) t.Run("intersection", func(t *testing.T) { var ( @@ -30,7 +30,7 @@ func TestIntersect(t *testing.T) { result := Intersect(slice1, slice2) slices.Sort(result) slices.Sort(want) - ExpectEqual(t, result, want) + expect.Equal(t, result, want) }) }) t.Run("ints", func(t *testing.T) { @@ -43,7 +43,7 @@ func TestIntersect(t *testing.T) { result := Intersect(slice1, slice2) slices.Sort(result) slices.Sort(want) - ExpectEqual(t, result, want) + expect.Equal(t, result, want) }) t.Run("intersection", func(t *testing.T) { var ( @@ -54,7 +54,7 @@ func TestIntersect(t *testing.T) { result := Intersect(slice1, slice2) slices.Sort(result) slices.Sort(want) - ExpectEqual(t, result, want) + expect.Equal(t, result, want) }) }) t.Run("complex", func(t *testing.T) { @@ -75,7 +75,7 @@ func TestIntersect(t *testing.T) { slices.SortFunc(want, func(i T, j T) int { return strings.Compare(i.A, j.A) }) - ExpectEqual(t, result, want) + expect.Equal(t, result, want) }) t.Run("intersection", func(t *testing.T) { var ( @@ -90,7 +90,7 @@ func TestIntersect(t *testing.T) { slices.SortFunc(want, func(i T, j T) int { return strings.Compare(i.A, j.A) }) - ExpectEqual(t, result, want) + expect.Equal(t, result, want) }) }) } diff --git a/internal/utils/testing/expect.go b/internal/utils/testing/expect.go deleted file mode 100644 index cd4c37dd..00000000 --- a/internal/utils/testing/expect.go +++ /dev/null @@ -1,78 +0,0 @@ -package expect - -import ( - "os" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -var isTest = strings.HasSuffix(os.Args[0], ".test") - -func init() { - if isTest { - // force verbose output - os.Args = append([]string{os.Args[0], "-test.v"}, os.Args[1:]...) - } -} - -func Must[Result any](r Result, err error) Result { - if err != nil { - panic(err) - } - return r -} - -var ( - NoError = require.NoError - HasError = require.Error - True = require.True - False = require.False - Nil = require.Nil - NotNil = require.NotNil - ErrorContains = require.ErrorContains - Panics = require.Panics - Greater = require.Greater - Less = require.Less - GreaterOrEqual = require.GreaterOrEqual - LessOrEqual = require.LessOrEqual -) - -func ErrorIs(t *testing.T, expected error, err error, msgAndArgs ...any) { - t.Helper() - require.ErrorIs(t, err, expected, msgAndArgs...) -} - -func ErrorT[T error](t *testing.T, err error, msgAndArgs ...any) { - t.Helper() - var errAs T - require.ErrorAs(t, err, &errAs, msgAndArgs...) -} - -func Equal[T any](t *testing.T, got T, want T, msgAndArgs ...any) { - t.Helper() - require.EqualValues(t, want, got, msgAndArgs...) -} - -func NotEqual[T any](t *testing.T, got T, want T, msgAndArgs ...any) { - t.Helper() - require.NotEqual(t, want, got, msgAndArgs...) -} - -func Contains[T any](t *testing.T, got T, wants []T, msgAndArgs ...any) { - t.Helper() - require.Contains(t, wants, got, msgAndArgs...) -} - -func StringsContain(t *testing.T, got string, want string, msgAndArgs ...any) { - t.Helper() - require.Contains(t, got, want, msgAndArgs...) -} - -func Type[T any](t *testing.T, got any, msgAndArgs ...any) (_ T) { - t.Helper() - _, ok := got.(T) - require.True(t, ok, msgAndArgs...) - return got.(T) -} diff --git a/internal/utils/testing/log.go b/internal/utils/testing/log.go deleted file mode 100644 index bf662dbf..00000000 --- a/internal/utils/testing/log.go +++ /dev/null @@ -1,9 +0,0 @@ -package expect - -import "github.com/rs/zerolog" - -func init() { - if isTest { - zerolog.SetGlobalLevel(zerolog.DebugLevel) - } -} diff --git a/internal/utils/testing/testing.go b/internal/utils/testing/testing.go deleted file mode 100644 index 13411c3f..00000000 --- a/internal/utils/testing/testing.go +++ /dev/null @@ -1,55 +0,0 @@ -package expect - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func ExpectNoError(t *testing.T, err error) { - t.Helper() - require.NoError(t, err) -} - -func ExpectHasError(t *testing.T, err error) { - t.Helper() - require.Error(t, err) -} - -func ExpectError(t *testing.T, expected error, err error) { - t.Helper() - require.ErrorIs(t, err, expected) -} - -func ExpectErrorT[T error](t *testing.T, err error) { - t.Helper() - var errAs T - require.ErrorAs(t, err, &errAs) -} - -func ExpectEqual[T any](t *testing.T, got T, want T) { - t.Helper() - require.EqualValues(t, want, got) -} - -func ExpectContains[T any](t *testing.T, got T, wants []T) { - t.Helper() - require.Contains(t, wants, got) -} - -func ExpectTrue(t *testing.T, got bool) { - t.Helper() - require.True(t, got) -} - -func ExpectFalse(t *testing.T, got bool) { - t.Helper() - require.False(t, got) -} - -func ExpectType[T any](t *testing.T, got any) (_ T) { - t.Helper() - _, ok := got.(T) - require.True(t, ok) - return got.(T) -} diff --git a/internal/watcher/config_file_watcher.go b/internal/watcher/config_file_watcher.go index b31c3ea7..86cb9c8d 100644 --- a/internal/watcher/config_file_watcher.go +++ b/internal/watcher/config_file_watcher.go @@ -4,7 +4,7 @@ import ( "sync" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/task" + "github.com/yusing/goutils/task" ) var ( diff --git a/internal/watcher/directory_watcher.go b/internal/watcher/directory_watcher.go index 53ab758b..d491ac81 100644 --- a/internal/watcher/directory_watcher.go +++ b/internal/watcher/directory_watcher.go @@ -9,9 +9,9 @@ import ( "github.com/fsnotify/fsnotify" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/yusing/godoxy/internal/gperr" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/watcher/events" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) type DirWatcher struct { diff --git a/internal/watcher/docker_watcher.go b/internal/watcher/docker_watcher.go index 7c5c49eb..7a8a8fc2 100644 --- a/internal/watcher/docker_watcher.go +++ b/internal/watcher/docker_watcher.go @@ -10,8 +10,8 @@ import ( "github.com/docker/docker/client" "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/docker" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/watcher/events" + gperr "github.com/yusing/goutils/errs" ) type ( diff --git a/internal/watcher/events/event_queue.go b/internal/watcher/events/event_queue.go index eea1fbca..40002c47 100644 --- a/internal/watcher/events/event_queue.go +++ b/internal/watcher/events/event_queue.go @@ -5,8 +5,8 @@ import ( "time" "github.com/yusing/godoxy/internal/common" - "github.com/yusing/godoxy/internal/gperr" - "github.com/yusing/godoxy/internal/task" + gperr "github.com/yusing/goutils/errs" + "github.com/yusing/goutils/task" ) type ( diff --git a/internal/watcher/events/events.go b/internal/watcher/events/events.go index f20457a6..4fe137cd 100644 --- a/internal/watcher/events/events.go +++ b/internal/watcher/events/events.go @@ -72,7 +72,7 @@ var actionNameMap = func() (m map[Action]string) { for k, v := range fileActionNameMap { m[k] = v } - return + return m }() func (e Event) String() string { diff --git a/internal/watcher/file_watcher.go b/internal/watcher/file_watcher.go index 619f5376..c0563981 100644 --- a/internal/watcher/file_watcher.go +++ b/internal/watcher/file_watcher.go @@ -3,7 +3,7 @@ package watcher import ( "context" - "github.com/yusing/godoxy/internal/gperr" + gperr "github.com/yusing/goutils/errs" ) type fileWatcher struct { diff --git a/internal/watcher/health/monitor/agent_proxied.go b/internal/watcher/health/monitor/agent_proxied.go index a38a3e96..ded29e9f 100644 --- a/internal/watcher/health/monitor/agent_proxied.go +++ b/internal/watcher/health/monitor/agent_proxied.go @@ -78,5 +78,5 @@ func (mon *AgentProxiedMonitor) CheckHealth() (result types.HealthCheckResult, e // use godoxy to agent latency result.Latency = endTime.Sub(startTime) } - return + return result, err } diff --git a/internal/watcher/health/monitor/monitor.go b/internal/watcher/health/monitor/monitor.go index 3a5f019f..7cbc5e2c 100644 --- a/internal/watcher/health/monitor/monitor.go +++ b/internal/watcher/health/monitor/monitor.go @@ -11,12 +11,12 @@ import ( "github.com/rs/zerolog/log" "github.com/yusing/godoxy/internal/common" "github.com/yusing/godoxy/internal/docker" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/notif" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" "github.com/yusing/godoxy/internal/utils/atomic" + gperr "github.com/yusing/goutils/errs" strutils "github.com/yusing/goutils/strings" + "github.com/yusing/goutils/task" ) type ( diff --git a/internal/watcher/health/monitor/monitor_test.go b/internal/watcher/health/monitor/monitor_test.go index 6206064c..6129cf6c 100644 --- a/internal/watcher/health/monitor/monitor_test.go +++ b/internal/watcher/health/monitor/monitor_test.go @@ -9,8 +9,8 @@ import ( "github.com/rs/zerolog" "github.com/stretchr/testify/require" "github.com/yusing/godoxy/internal/notif" - "github.com/yusing/godoxy/internal/task" "github.com/yusing/godoxy/internal/types" + "github.com/yusing/goutils/task" ) // Test notification tracker diff --git a/internal/watcher/watcher.go b/internal/watcher/watcher.go index 45419e95..925d94ed 100644 --- a/internal/watcher/watcher.go +++ b/internal/watcher/watcher.go @@ -3,8 +3,8 @@ package watcher import ( "context" - "github.com/yusing/godoxy/internal/gperr" "github.com/yusing/godoxy/internal/watcher/events" + gperr "github.com/yusing/goutils/errs" ) type Event = events.Event diff --git a/pkg/version.go b/pkg/version.go index 7b42ee0b..8ca5e3b3 100644 --- a/pkg/version.go +++ b/pkg/version.go @@ -101,30 +101,30 @@ var versionRegex = regexp.MustCompile(`^v(\d+)\.(\d+)\.(\d+)(\-\w+)?$`) func ParseVersion(v string) (ver Version) { if v == "" { - return + return ver } if !versionRegex.MatchString(v) { // likely feature branch (e.g. feat/some-feature) - return + return ver } v = strings.Split(v, "-")[0] v = strings.TrimPrefix(v, "v") parts := strings.Split(v, ".") if len(parts) != 3 { - return + return ver } gen, err := strconv.Atoi(parts[0]) if err != nil { - return + return ver } major, err := strconv.Atoi(parts[1]) if err != nil { - return + return ver } minor, err := strconv.Atoi(parts[2]) if err != nil { - return + return ver } return Ver(gen, major, minor) }