jys 2 anni fa
parent
commit
ff6b88f8c4
10 ha cambiato i file con 326 aggiunte e 67 eliminazioni
  1. 10 1
      go.mod
  2. 10 0
      go.sum
  3. 32 0
      v2alpha/center_test.go
  4. 4 20
      v2alpha/code.go
  5. 38 0
      v2alpha/code_test.go
  6. 6 2
      v2alpha/errors.go
  7. 76 0
      v2alpha/errors_test.go
  8. 25 0
      v2alpha/option_test.go
  9. 4 2
      v2alpha/public.go
  10. 121 42
      v2alpha/public_test.go

+ 10 - 1
go.mod

@@ -2,4 +2,13 @@ module git.sxidc.com/service-supports/fserr
 
 go 1.20
 
-require github.com/pkg/errors v0.9.1
+require (
+	github.com/pkg/errors v0.9.1
+	github.com/stretchr/testify v1.8.3
+)
+
+require (
+	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/pmezard/go-difflib v1.0.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)

+ 10 - 0
go.sum

@@ -1,2 +1,12 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 32 - 0
v2alpha/center_test.go

@@ -0,0 +1,32 @@
+package fserr
+
+import (
+	"github.com/stretchr/testify/suite"
+	"net/http"
+	"testing"
+)
+
+type TestCenterSuite struct {
+	suite.Suite
+	expectedBusinessCode int
+}
+
+func (s *TestCenterSuite) SetupTest() {
+	s.expectedBusinessCode = 1001
+	register(s.expectedBusinessCode, NewOK(s.expectedBusinessCode, "ok"))
+}
+
+func (s *TestCenterSuite) TestGetCenterErrCode() {
+	s.Equal(s.expectedBusinessCode, getCode(s.expectedBusinessCode).BusinessCode)
+}
+
+func (s *TestCenterSuite) TestDefaultErrCode() {
+	notExistErrCode := getCode(2001)
+	s.Equal("", notExistErrCode.Message)
+	s.Equal(http.StatusOK, defaultErrCode.HttpCode)
+	s.Equal(2001, notExistErrCode.BusinessCode)
+}
+
+func TestCenter(t *testing.T) {
+	suite.Run(t, &TestCenterSuite{})
+}

+ 4 - 20
v2alpha/code.go

@@ -12,28 +12,12 @@ type codeType interface {
 var serviceCode int
 
 const (
-	errBasic = iota + 1
-	errDb
-	errRetry
-	errServiceInvoke
+	ErrBasic = iota + 100101
+	ErrDb
+	ErrRetry
+	ErrServiceInvoke
 )
 
-func ErrBasic() int {
-	return serviceCode + errBasic
-}
-
-func ErrDb() int {
-	return serviceCode + errDb
-}
-
-func ErrRetry() int {
-	return serviceCode + errRetry
-}
-
-func ErrServiceInvoke() int {
-	return serviceCode + errServiceInvoke
-}
-
 // ErrCode 产生error所包含的错误码信息
 // 支持http错误码、业务错误码
 // 可通过下方快捷函数快速创建指定http码的错误码

+ 38 - 0
v2alpha/code_test.go

@@ -0,0 +1,38 @@
+package fserr
+
+import (
+	"github.com/stretchr/testify/suite"
+	"net/http"
+	"testing"
+)
+
+type TestCodeSuite struct {
+	suite.Suite
+}
+
+func (s *TestCodeSuite) SetupTest() {
+	NewInternalError(ErrBasic, "basic error")
+	NewBadRequest(100102, "customer error")
+	SetDefault(http.StatusInternalServerError, 100101, "default")
+}
+
+func (s *TestCodeSuite) TestBuiltinErrCode() {
+	errCode := getCode(ErrBasic)
+	s.Equal(http.StatusInternalServerError, errCode.HttpCode)
+	s.Equal("basic error", errCode.Message)
+}
+
+func (s *TestCodeSuite) TestDefaultErrCode() {
+	s.Equal(http.StatusInternalServerError, defaultErrCode.HttpCode)
+	s.Equal("default", defaultErrCode.Message)
+}
+
+func (s *TestCodeSuite) TestCustomerErrCode() {
+	errCode := getCode(100102)
+	s.Equal(http.StatusBadRequest, errCode.HttpCode)
+	s.Equal("customer error", errCode.Message)
+}
+
+func TestCode(t *testing.T) {
+	suite.Run(t, &TestCodeSuite{})
+}

+ 6 - 2
v2alpha/errors.go

@@ -74,8 +74,10 @@ func (w *withMessage) Format(s fmt.State, verb rune) {
 			return
 		}
 		fallthrough
-	case 's', 'q':
+	case 's':
 		_, _ = io.WriteString(s, w.Error())
+	case 'q':
+		_, _ = fmt.Fprintf(s, "%q", w.Error())
 	}
 }
 
@@ -100,7 +102,9 @@ func (w *withCode) Format(s fmt.State, verb rune) {
 			return
 		}
 		fallthrough
-	case 's', 'q':
+	case 's':
 		_, _ = io.WriteString(s, w.Error())
+	case 'q':
+		_, _ = fmt.Fprintf(s, "%q", w.Error())
 	}
 }

+ 76 - 0
v2alpha/errors_test.go

@@ -0,0 +1,76 @@
+package fserr
+
+import (
+	"fmt"
+	"github.com/stretchr/testify/suite"
+	"net/http"
+	"testing"
+)
+
+type TestErrorsSuite struct {
+	suite.Suite
+	originFundamental *fundamental
+	originStack       *withStack
+	originMessage     *withMessage
+	originCode        *withCode
+}
+
+func (s *TestErrorsSuite) SetupTest() {
+	s.originFundamental = &fundamental{
+		msg:   "origin fundamental",
+		stack: callers(),
+	}
+	s.originStack = &withStack{
+		error: s.originFundamental,
+		stack: callers(),
+	}
+	s.originMessage = &withMessage{
+		cause: s.originStack,
+		msg:   "origin message",
+	}
+	s.originCode = &withCode{
+		cause:        s.originMessage,
+		Msg:          "with code",
+		HttpCode:     http.StatusOK,
+		BusinessCode: ErrBasic,
+	}
+}
+
+func (s *TestErrorsSuite) TestFundamental() {
+	s.Equal("origin fundamental", s.originFundamental.msg)
+	s.Equal("origin fundamental", s.originFundamental.Error())
+	s.Equal("origin fundamental",
+		fmt.Sprintf("%s", s.originFundamental))
+	s.Equal(`"origin fundamental"`,
+		fmt.Sprintf("%q", s.originFundamental))
+}
+
+func (s *TestErrorsSuite) TestStack() {
+	s.Equal(s.originFundamental, s.originStack.Cause())
+	s.Equal(s.originFundamental, s.originStack.Unwrap())
+	s.Equal("origin fundamental", s.originStack.Error())
+	s.Equal("origin fundamental", fmt.Sprintf("%s", s.originStack))
+	s.Equal(`"origin fundamental"`, fmt.Sprintf("%q", s.originStack))
+}
+
+func (s *TestErrorsSuite) TestMessage() {
+	s.Equal(s.originStack, s.originMessage.Cause())
+	s.Equal(s.originStack, s.originMessage.Unwrap())
+	s.Equal("origin message: origin fundamental", s.originMessage.Error())
+	s.Equal("origin message: origin fundamental",
+		fmt.Sprintf("%s", s.originMessage))
+	s.Equal(`"origin message: origin fundamental"`,
+		fmt.Sprintf("%q", s.originMessage))
+}
+
+func (s *TestErrorsSuite) TestCode() {
+	s.Equal(s.originMessage, s.originCode.Cause())
+	s.Equal(s.originMessage, s.originCode.Unwrap())
+	s.Equal("with code", s.originCode.Error())
+	s.Equal("with code", fmt.Sprintf("%s", s.originCode))
+	s.Equal(`"with code"`, fmt.Sprintf("%q", s.originCode))
+}
+
+func TestErrors(t *testing.T) {
+	suite.Run(t, &TestErrorsSuite{})
+}

+ 25 - 0
v2alpha/option_test.go

@@ -0,0 +1,25 @@
+package fserr
+
+import (
+	"github.com/stretchr/testify/suite"
+	"testing"
+)
+
+type TestOptionSuite struct {
+	suite.Suite
+	opt Option
+}
+
+func (s *TestOptionSuite) SetupTest() {
+	s.opt = MsgOption("cover message")
+}
+
+func (s *TestOptionSuite) TestCode() {
+	w := &withCode{}
+	s.opt(w)
+	s.Equal("cover message", w.Msg)
+}
+
+func TestOption(t *testing.T) {
+	suite.Run(t, &TestOptionSuite{})
+}

+ 4 - 2
v2alpha/public.go

@@ -56,10 +56,10 @@ func WithCode[T codeType](err error, businessCode T, options ...Option) error {
 	return ret
 }
 
-// UmWrap 获取包装过的error
+// UnWrap 获取包装过的error
 // 若error1使用 Wrap 包装后产出错误error2
 // 当使用 UmWrap 后,返回的是error1
-func UmWrap(err error) error {
+func UnWrap(err error) error {
 	type causer interface {
 		Cause() error
 	}
@@ -116,6 +116,8 @@ func IsCode(err error, code int) bool {
 }
 
 // SetServiceCode 设置服务错误码
+// 例如设置服务码为300000,用户不存在错误码为2001,
+// 那么最终业务错误码为302001
 func SetServiceCode(code int) {
 	serviceCode = code
 }

+ 121 - 42
v2alpha/public_test.go

@@ -1,49 +1,128 @@
 package fserr
 
 import (
-	"fmt"
+	"errors"
+	"github.com/stretchr/testify/suite"
+	"net/http"
 	"testing"
 )
 
-func TestNew(t *testing.T) {
-	expected := "test"
-	err := New(expected)
-	if err.Error() != expected {
-		t.Errorf("expected %s but not", expected)
-	}
-	if fmt.Sprintf("%s", err) != expected {
-		t.Errorf("expected %s but not", expected)
-	}
-	if fmt.Sprintf("%v", err) != expected {
-		t.Errorf("expected %s but not", expected)
-	}
-	if fmt.Sprintf("%q", err) != `"test"` {
-		t.Errorf("expected %s but not", expected)
-	}
-}
-
-func TestWrap(t *testing.T) {
-	expected := "wrap: test"
-	err := Wrap(New("test"), "wrap")
-	if err.Error() != expected {
-		t.Errorf("expected %s but not", expected)
-	}
-	if fmt.Sprintf("%s", err) != expected {
-		t.Errorf("expected %s but not", expected)
-	}
-	if fmt.Sprintf("%v", err) != expected {
-		t.Errorf("expected %s but not", expected)
-	}
-	if fmt.Sprintf("%q", err) != `"wrap: test"` {
-		t.Errorf("expected %s but not", expected)
-	}
-}
-
-func TestCause(t *testing.T) {
-	origin := New("origin")
-	err := Wrap(origin, "wrap")
-	err = UmWrap(err)
-	if err != origin {
-		t.Errorf("expected %s but not", "origin")
-	}
+type TestPublicSuite struct {
+	suite.Suite
+	outerErr,
+	newErr, newFmtErr,
+	wrapErr, wrapFmtErr, wrapOuterErr, wrapNilErr,
+	codeErr, codeOptionErr, codeOuterErr, codeNilErr error
+	errBasicMsg string
+}
+
+func (s *TestPublicSuite) SetupTest() {
+	s.outerErr = errors.New("outer error")
+	s.errBasicMsg = "basic error"
+	NewOK(ErrBasic, s.errBasicMsg)
+
+	// new
+	s.newErr = New("new error")
+	s.newFmtErr = New("new %s", "error")
+
+	// wrap
+	s.wrapErr = Wrap(s.newErr, "wrap error")
+	s.wrapFmtErr = Wrap(s.newErr, "wrap %s", "error")
+	s.wrapOuterErr = Wrap(s.outerErr, "wrap error")
+	s.wrapNilErr = Wrap(nil, "wrap error")
+
+	// code
+	s.codeErr = WithCode(s.newErr, ErrBasic)
+	s.codeOptionErr = WithCode(s.newErr, ErrBasic, MsgOption("cover message"))
+	s.codeOuterErr = WithCode(s.outerErr, ErrBasic)
+	s.codeNilErr = WithCode(nil, ErrBasic)
+}
+
+func (s *TestPublicSuite) TestNew() {
+	s.Equal("new error", s.newErr.Error())
+	s.Equal("new error", s.newFmtErr.Error())
+}
+
+func (s *TestPublicSuite) TestWrap() {
+	s.Equal("wrap error: new error", s.wrapErr.Error())
+	s.Equal("wrap error: new error", s.wrapFmtErr.Error())
+	s.Equal("wrap error: outer error", s.wrapOuterErr.Error())
+	s.Nil(s.wrapNilErr)
+}
+
+func (s *TestPublicSuite) TestWithCode() {
+	s.Equal(s.errBasicMsg, s.codeErr.Error())
+	s.Equal("cover message", s.codeOptionErr.Error())
+	s.Equal("basic error", s.codeOuterErr.Error())
+	s.Equal("basic error", s.codeNilErr.Error())
+}
+
+func (s *TestPublicSuite) TestUnWrap() {
+	s.Equal(s.newErr, UnWrap(s.newErr))
+
+	s.Equal(s.newErr, UnWrap(s.wrapErr))
+	s.Equal(s.outerErr, UnWrap(s.wrapOuterErr))
+	s.Nil(UnWrap(s.wrapNilErr))
+
+	s.Equal(s.newErr, UnWrap(s.codeErr))
+	s.Equal(s.outerErr, UnWrap(s.codeOuterErr))
+	s.Equal(nil, UnWrap(s.codeNilErr))
+}
+
+func (s *TestPublicSuite) TestIs() {
+	s.True(Is(s.newErr, s.newErr))
+	s.True(Is(s.wrapErr, s.newErr))
+	s.True(Is(s.codeErr, s.newErr))
+
+	s.False(Is(s.newErr, s.outerErr))
+	s.False(Is(s.wrapErr, s.outerErr))
+	s.False(Is(s.codeErr, s.outerErr))
+}
+
+func (s *TestPublicSuite) TestAs() {
+	var originErr *fundamental
+	s.True(As(s.wrapErr, &originErr))
+	s.Equal(UnWrap(s.wrapErr), originErr)
+
+	var codeErr *withCode
+	s.False(As(s.wrapErr, &codeErr))
+}
+
+func (s *TestPublicSuite) TestOuterMsg() {
+	s.Equal("new error", outerMsg(s.newErr))
+	s.Equal("wrap error", outerMsg(s.wrapErr))
+	s.Equal(s.errBasicMsg, outerMsg(s.codeErr))
+	s.Equal("outer error", outerMsg(s.outerErr))
+	s.Equal("", outerMsg(nil))
+}
+
+func (s *TestPublicSuite) TestParseCode() {
+	code := ParseCode(s.codeErr)
+	s.Equal(ErrBasic, code.BusinessCode)
+	s.Equal(http.StatusOK, code.HttpCode)
+	s.Equal(s.errBasicMsg, code.Msg)
+	s.Equal(s.newErr, code.cause)
+
+	err := ParseCode(Wrap(s.codeErr, "wrap error"))
+	s.Equal(ErrBasic, err.BusinessCode)
+	s.Equal(http.StatusOK, err.HttpCode)
+	s.Equal("wrap error", err.Msg)
+	s.Equal(s.newErr, err.cause)
+}
+
+func (s *TestPublicSuite) TestIsCode() {
+	s.True(IsCode(s.codeErr, ErrBasic))
+	s.False(IsCode(s.codeErr, ErrDb))
+	s.False(IsCode(s.wrapErr, ErrBasic))
+}
+
+func (s *TestPublicSuite) TestSetServiceCode() {
+	SetServiceCode(300000)
+	NewOK(2001, "ok")
+	err := WithCode(nil, 2001)
+	s.Equal(302001, ParseCode(err).BusinessCode)
+}
+
+func TestPublic(t *testing.T) {
+	suite.Run(t, &TestPublicSuite{})
 }