diff --git a/gateway/http.go b/gateway/http.go index 6439bbf..501b12f 100644 --- a/gateway/http.go +++ b/gateway/http.go @@ -120,10 +120,7 @@ func loadGlobalMessages(pd ProtobufDescription) error { continue } msg := dynamicpb.NewMessageType(msgType) - err := protoregistry.GlobalTypes.RegisterMessage(msg) - if err != nil { - return false - } + _ = protoregistry.GlobalTypes.RegisterMessage(msg) } for i := 0; i < fd.Enums().Len(); i++ { enumType := fd.Enums().Get(i) @@ -132,10 +129,7 @@ func loadGlobalMessages(pd ProtobufDescription) error { continue } enum := dynamicpb.NewEnumType(enumType) - err := protoregistry.GlobalTypes.RegisterEnum(enum) - if err != nil { - return false - } + _ = protoregistry.GlobalTypes.RegisterEnum(enum) } return true @@ -294,7 +288,7 @@ func (h *HttpEndpointImpl) inParamsHandle(pathParams map[string]string, req *htt } func (h *HttpEndpointImpl) addHexEncodeSHA256HashV2(req *http.Request) error { - if req.Body == nil { + if req==nil||req.Body == nil { return nil } // 创建SHA256哈希对象 @@ -386,6 +380,7 @@ func (h *HttpEndpointImpl) RegisterHandlerClient(ctx context.Context, pd Protobu } for _, item := range items { item := item + // log.Printf("register endpoint %s: %s %v", strings.ToUpper(item.HttpMethod), item.HttpUri, item.Pattern) mux.Handle(strings.ToUpper(item.HttpMethod), item.Pattern, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { if req.Header.Get("accept") == "" { req.Header.Set("accept", "application/json") diff --git a/gateway/http_test.go b/gateway/http_test.go index d947b8a..3d924bc 100644 --- a/gateway/http_test.go +++ b/gateway/http_test.go @@ -37,6 +37,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/peer" "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/reflect/protodesc" "google.golang.org/protobuf/reflect/protoregistry" "gopkg.in/cenkalti/backoff.v1" ) @@ -134,11 +135,11 @@ func testRegisterClient(t *testing.T) { go example.Run(helloAddr) time.Sleep(2 * time.Second) go gw.Start() - time.Sleep(1 * time.Second) - f:=func(){ + time.Sleep(2 * time.Second) + f := func() { gw.Start() } - c.So(f,c.ShouldPanic) + c.So(f, c.ShouldPanic) time.Sleep(4 * time.Second) _, err = gw.proxyLB.Select("test/.test") c.So(err, c.ShouldNotBeNil) @@ -181,6 +182,16 @@ func testRequestGet(t *testing.T) { c.So(err, c.ShouldBeNil) c.So(resp.StatusCode, c.ShouldEqual, http.StatusIMUsed) + url = fmt.Sprintf("http://127.0.0.1:%d/api/v1/example/world?msg=hello", gwPort) + r2, err := http.NewRequest(http.MethodPost, url, nil) + + c.So(err, c.ShouldBeNil) + + resp2, err := http.DefaultClient.Do(r2) + + c.So(err, c.ShouldBeNil) + c.So(resp2.StatusCode, c.ShouldEqual, http.StatusNotImplemented) + }) } func testCors(t *testing.T) { @@ -774,10 +785,6 @@ func testWebSocketError(t *testing.T) { output: []interface{}{nil, fmt.Errorf("test upgrade error")}, exceptErr: websocket.ErrBadHandshake, }, - // { - // patch: (*websocketForwarder).Write, - // output: []interface{}{0, fmt.Errorf("test websocket write error")}, - // }, { patch: (*goloadbalancer.ConnPool).Get, output: []interface{}{nil, fmt.Errorf("test get conn error")}, @@ -852,6 +859,11 @@ func testServerSideEventErr(t *testing.T) { output: []interface{}{nil, fmt.Errorf("test marshal error")}, err: fmt.Errorf("test marshal error"), }, + { + patch: (*gwRuntime.DecoderWrapper).Decode, + output: []interface{}{fmt.Errorf("test decode error")}, + err: fmt.Errorf("test decode error"), + }, } for _, caseV := range cases { url := fmt.Sprintf("http://127.0.0.1:%d/api/v1/example/server/sse/world?msg=hello", gwPort) @@ -1075,9 +1087,74 @@ func testUpdateLoadbalance(t *testing.T) { } for _, v := range endps { c.So(v.Stats().GetIdleConns(), c.ShouldBeGreaterThan, 0) - // c.So(v.Close(), c.ShouldBeNil) } - // helloAddr := fmt.Sprintf("") + }) +} +func testStartErr(t *testing.T) { + c.Convey("test start error", t, func() { + _, filename, _, _ := runtime.Caller(0) + pbFile := filepath.Join(filepath.Dir(filepath.Dir(filename)), "testdata", "helloworld.pb") + pb, err := os.ReadFile(pbFile) + c.So(err, c.ShouldBeNil) + pd, err := NewDescriptionFromBinary(pb, filepath.Join("tmp", "test-pd")) + c.So(err, c.ShouldBeNil) + opts, cnf := newTestServer(0, 0) + localGW := NewGateway(cnf, opts) + err = localGW.RegisterHandlerClient(context.Background(), pd) + c.So(err, c.ShouldBeNil) + + c.So(localGW.Start, c.ShouldPanic) + + min := 1949 + max := 12138 + rander := rand.New(rand.NewSource(time.Now().Unix())) // 初始化随机数种子 + + randomNumber := rander.Intn(max-min+1) + min + opts1, cnf1 := newTestServer(randomNumber+3, randomNumber) + localGW1 := NewGateway(cnf1, opts1) + err = localGW1.RegisterHandlerClient(context.Background(), pd) + c.So(err, c.ShouldBeNil) + go localGW1.Start() + time.Sleep(3 * time.Second) + opts2, cnf2 := newTestServer(gwPort, randomNumber+4) + localGW2 := NewGateway(cnf2, opts2) + err = localGW2.RegisterHandlerClient(context.Background(), pd) + c.So(err, c.ShouldBeNil) + c.So(localGW2.Start, c.ShouldPanic) + + }) +} +func testAddHexEncodeSHA256HashV2Err(t *testing.T) { + c.Convey("test add hex encode sha256 hash v2 err", t, func() { + httpEp := &HttpEndpointImpl{} + err := httpEp.addHexEncodeSHA256HashV2(nil) + c.So(err, c.ShouldBeNil) + patch := gomonkey.ApplyFuncReturn(io.Copy, int64(0), fmt.Errorf("test io copy error")) + defer patch.Reset() + req, err := http.NewRequest(http.MethodPost, "http://www.example.com", strings.NewReader("hello")) + c.So(err, c.ShouldBeNil) + err = httpEp.addHexEncodeSHA256HashV2(req) + c.So(err.Error(), c.ShouldContainSubstring, "test io copy error") + patch.Reset() + }) +} + +func testRegisterHandlerClientErr(t *testing.T) { + c.Convey("test register handler client err", t, func() { + _, filename, _, _ := runtime.Caller(0) + pbFile := filepath.Join(filepath.Dir(filepath.Dir(filename)), "testdata", "helloworld.pb") + pb, err := os.ReadFile(pbFile) + c.So(err, c.ShouldBeNil) + pd, err := NewDescriptionFromBinary(pb, filepath.Join("tmp", "test-pd")) + c.So(err, c.ShouldBeNil) + patch := gomonkey.ApplyFuncReturn(protodesc.NewFiles,nil, fmt.Errorf("test NewFiles error")) + defer patch.Reset() + err = gw.RegisterHandlerClient(context.Background(), pd) + patch.Reset() + + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "test NewFiles error") + }) } func TestHttp(t *testing.T) { @@ -1095,10 +1172,14 @@ func TestHttp(t *testing.T) { t.Run("testWebSocketError", testWebSocketError) t.Run("testServerSideEventErr", testServerSideEventErr) t.Run("testClientStreamErr", testClientStreamErr) + t.Run("testAddHexEncodeSHA256HashV2Err", testAddHexEncodeSHA256HashV2Err) + t.Run("testRegisterHandlerClientErr", testRegisterHandlerClientErr) // t.Run("testInParamsHandle", testInParamsHandle) t.Run("testRequestError", testRequestError) t.Run("testLoadHttpEndpointItemErr", testLoadHttpEndpointItemErr) t.Run("testDeleteEndpoint", testDeleteEndpoint) t.Run("testRegisterLocalService", testRegisterLocalService) + t.Run("testStartErr", testStartErr) + // time.Sleep(30 * time.Second) } diff --git a/gateway/mask_test.go b/gateway/mask_test.go index 5c0edd6..027dd43 100644 --- a/gateway/mask_test.go +++ b/gateway/mask_test.go @@ -71,5 +71,11 @@ func TestDecodeErr(t *testing.T) { c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, caseV.err.Error()) } + r := bytes.NewReader([]byte(`{"message":"John Doe","msg":{"msg":"hello world"},"allow":"DENY","repeated_msg":[{"msg":"John Doe"}]}`)) + decoder := NewMaskDecoder(NewJsonDecoder(r)) + mapData:=make(map[string]interface{}) + err := decoder.Decode(mapData) + c.So(err, c.ShouldBeNil) + c.So(len(mapData), c.ShouldEqual, 0) }) } diff --git a/gateway/middlewares.go b/gateway/middlewares.go index c22e8e4..fde450c 100644 --- a/gateway/middlewares.go +++ b/gateway/middlewares.go @@ -233,6 +233,10 @@ func HandleErrorWithLogger(logger logger.Logger) runtime.ErrorHandlerFunc { "status": statusCode, }, ) + if _,ok:=metadata.FromIncomingContext(ctx);!ok{ + md:=IncomingHeadersToMetadata(ctx,req) + ctx=metadata.NewIncomingContext(ctx,md) + } code := statusCode data := &common.HttpResponse{} data.Code = int32(common.Code_INTERNAL_ERROR) diff --git a/go.mod b/go.mod index 2fbb3f0..8032970 100644 --- a/go.mod +++ b/go.mod @@ -10,9 +10,9 @@ require ( github.com/cockroachdb/errors v1.11.1 github.com/google/wire v0.6.0 github.com/smartystreets/goconvey v1.8.1 - github.com/spark-lence/tiga v0.0.0-20240517061929-e81eba889226 + github.com/spark-lence/tiga v0.0.0-20240523101823-47fd881052e5 github.com/spf13/cobra v1.8.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 + google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e google.golang.org/grpc v1.64.0 google.golang.org/protobuf v1.34.1 ) @@ -80,7 +80,7 @@ require ( require ( github.com/agiledragon/gomonkey/v2 v2.11.0 github.com/begonia-org/go-loadbalancer v0.0.0-20240519060752-71ca464f0f1a - github.com/begonia-org/go-sdk v0.0.0-20240521170528-b02c5a54f25e + github.com/begonia-org/go-sdk v0.0.0-20240524034736-5c195b7e4b0f github.com/go-git/go-git/v5 v5.11.0 github.com/go-playground/validator/v10 v10.19.0 github.com/gorilla/websocket v1.5.0 @@ -135,7 +135,7 @@ require ( golang.org/x/sys v0.20.0 // indirect golang.org/x/text v0.15.0 // indirect golang.org/x/tools v0.21.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index c40e5b0..f5b9ba6 100644 --- a/go.sum +++ b/go.sum @@ -21,30 +21,12 @@ github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/begonia-org/go-layered-cache v0.0.0-20240510102605-41bdb7aa07fa h1:DHjhGvN6SYMA2Vf2D0/kILQKcSiFQH6OqNMivYebFag= github.com/begonia-org/go-layered-cache v0.0.0-20240510102605-41bdb7aa07fa/go.mod h1:xEqoca1vNGqH8CV7X9EzhDV5Ihtq9J95p7ZipzUB6pc= -github.com/begonia-org/go-loadbalancer v0.0.0-20240408092223-42b5fab476ce h1:qLUMzfJuPyWVeIs9d4FaootUIQzWs4xfFwkI6R6IH40= -github.com/begonia-org/go-loadbalancer v0.0.0-20240408092223-42b5fab476ce/go.mod h1:crPS67sfgmgv47psftwfmTMbmTfdepVm8MPeqApINlI= -github.com/begonia-org/go-loadbalancer v0.0.0-20240515153502-b1d83dda8ae3 h1:0BxtLwjHi9tQiQ8l+rEqIqTY0WqngC3RptORz7edTHU= -github.com/begonia-org/go-loadbalancer v0.0.0-20240515153502-b1d83dda8ae3/go.mod h1:crPS67sfgmgv47psftwfmTMbmTfdepVm8MPeqApINlI= github.com/begonia-org/go-loadbalancer v0.0.0-20240519060752-71ca464f0f1a h1:Mpw7T+90KC5QW7yCa8Nn/5psnlvsexipAOrQAcc7YE0= github.com/begonia-org/go-loadbalancer v0.0.0-20240519060752-71ca464f0f1a/go.mod h1:crPS67sfgmgv47psftwfmTMbmTfdepVm8MPeqApINlI= -github.com/begonia-org/go-sdk v0.0.0-20240515083527-ef2ff6b73539 h1:M7pPon2kyX2MlJM8R6+TGqGAFhWzSzAd8VqCZ9/bm3g= -github.com/begonia-org/go-sdk v0.0.0-20240515083527-ef2ff6b73539/go.mod h1:I70a3fiAADGrOoOC3lv408rFcTRhTwLt3pwr6cQwB4Y= -github.com/begonia-org/go-sdk v0.0.0-20240516160356-c90fe583fd2e h1:VwPf1HI//SopJpJtWHtQd6JreryTtu8s1m0zQo+Jeqc= -github.com/begonia-org/go-sdk v0.0.0-20240516160356-c90fe583fd2e/go.mod h1:I70a3fiAADGrOoOC3lv408rFcTRhTwLt3pwr6cQwB4Y= -github.com/begonia-org/go-sdk v0.0.0-20240517035447-b6ee0a94bc66 h1:ejdny9b1oeioMFd8IWQcY9uDpDOAlTnMAJvhsalHdjs= -github.com/begonia-org/go-sdk v0.0.0-20240517035447-b6ee0a94bc66/go.mod h1:I70a3fiAADGrOoOC3lv408rFcTRhTwLt3pwr6cQwB4Y= -github.com/begonia-org/go-sdk v0.0.0-20240517084829-c3cdf5e5e1eb h1:H58fLjtWA5CZSl20GLyi+3xnQiRiP47aEub7YWFjuQc= -github.com/begonia-org/go-sdk v0.0.0-20240517084829-c3cdf5e5e1eb/go.mod h1:I70a3fiAADGrOoOC3lv408rFcTRhTwLt3pwr6cQwB4Y= -github.com/begonia-org/go-sdk v0.0.0-20240517093020-2a19277f4cd0 h1:PRMFCCLybAmO0gnaU3pZhY1koi1N1so3iMBdbLEfCOU= -github.com/begonia-org/go-sdk v0.0.0-20240517093020-2a19277f4cd0/go.mod h1:I70a3fiAADGrOoOC3lv408rFcTRhTwLt3pwr6cQwB4Y= -github.com/begonia-org/go-sdk v0.0.0-20240519143740-d09416b7b751 h1:ku84LpIO8hZ54BzE089pfTB1Op7YIA3GMLEcN49VoUI= -github.com/begonia-org/go-sdk v0.0.0-20240519143740-d09416b7b751/go.mod h1:I70a3fiAADGrOoOC3lv408rFcTRhTwLt3pwr6cQwB4Y= -github.com/begonia-org/go-sdk v0.0.0-20240520034852-0b45d3942779 h1:iL/WWH9anPFbGJWYIhqPIcVAkWKfPq0HntG5NkHI2uk= -github.com/begonia-org/go-sdk v0.0.0-20240520034852-0b45d3942779/go.mod h1:I70a3fiAADGrOoOC3lv408rFcTRhTwLt3pwr6cQwB4Y= -github.com/begonia-org/go-sdk v0.0.0-20240520090120-64e22f6f7a4d h1:yJ0+f8SDNyA2GSf1XvLN2R4BK60ruNU7+V328BBCDYw= -github.com/begonia-org/go-sdk v0.0.0-20240520090120-64e22f6f7a4d/go.mod h1:I70a3fiAADGrOoOC3lv408rFcTRhTwLt3pwr6cQwB4Y= github.com/begonia-org/go-sdk v0.0.0-20240521170528-b02c5a54f25e h1:QIlVvEUYC2t+ctxzKMFtMw0a1eXauR87pimm2D55guQ= github.com/begonia-org/go-sdk v0.0.0-20240521170528-b02c5a54f25e/go.mod h1:I70a3fiAADGrOoOC3lv408rFcTRhTwLt3pwr6cQwB4Y= +github.com/begonia-org/go-sdk v0.0.0-20240524034736-5c195b7e4b0f h1:DQAupqwJEj9lYPk7phcbr+8+lZOFPLRNA9Ao+8Sh11M= +github.com/begonia-org/go-sdk v0.0.0-20240524034736-5c195b7e4b0f/go.mod h1:I70a3fiAADGrOoOC3lv408rFcTRhTwLt3pwr6cQwB4Y= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= @@ -240,12 +222,10 @@ github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sS github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spark-lence/tiga v0.0.0-20240510102710-93bf07b60b07 h1:BLvfdUv/NKsRirhQbUum2eduFHfu0tcWyF4fHhP62zY= -github.com/spark-lence/tiga v0.0.0-20240510102710-93bf07b60b07/go.mod h1:jo3Qr3EkFkOX0GUD6c4YyLoJESTYtd2hfYP9HZk8s8I= -github.com/spark-lence/tiga v0.0.0-20240517030839-e2e8385d3629 h1:J5qEeswukKY+wAnQLgHFz8T9/vItTF4lga7JDjwz8fE= -github.com/spark-lence/tiga v0.0.0-20240517030839-e2e8385d3629/go.mod h1:MSL8X9t+qvpQ4Tq3vVPKncq9RJcCzF2XGEWkCuNhm6Q= github.com/spark-lence/tiga v0.0.0-20240517061929-e81eba889226 h1:WKMb1r+0r5lDKrynMlC9v62EajmtLXMIIk6NzrVbcNs= github.com/spark-lence/tiga v0.0.0-20240517061929-e81eba889226/go.mod h1:MSL8X9t+qvpQ4Tq3vVPKncq9RJcCzF2XGEWkCuNhm6Q= +github.com/spark-lence/tiga v0.0.0-20240523101823-47fd881052e5 h1:lbs5Qf0cOLvIu0d1hftGNYWeudonk77XA6FRxa40yN8= +github.com/spark-lence/tiga v0.0.0-20240523101823-47fd881052e5/go.mod h1:MSL8X9t+qvpQ4Tq3vVPKncq9RJcCzF2XGEWkCuNhm6Q= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= @@ -412,18 +392,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1:W5Xj/70xIA4x60O/IFyXivR5MGqblAb8R3w26pnD6No= -google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= -google.golang.org/genproto/googleapis/api v0.0.0-20240515191416-fc5f0ca64291 h1:4HZJ3Xv1cmrJ+0aFo304Zn79ur1HMxptAE7aCPNLSqc= -google.golang.org/genproto/googleapis/api v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 h1:AgADTJarZTBqgjiUzRgfaBchgYB3/WFTC80GPwsMcRI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e h1:SkdGTrROJl2jRGT/Fxv5QUf9jtdKCQh4KQJXbXVLAi0= +google.golang.org/genproto/googleapis/api v0.0.0-20240521202816-d264139d666e/go.mod h1:LweJcLbyVij6rCex8YunD8DYR5VDonap/jYl3ZRxcIU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 h1:Q2RxlXqh1cgzzUgV261vBO2jI5R/3DD1J2pM0nI4NhU= google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e h1:Elxv5MwEkCI9f5SkoL6afed6NTdxaGoAo39eANBwHL8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= diff --git a/internal/biz/aksk.go b/internal/biz/aksk.go index 15494cd..528edd6 100644 --- a/internal/biz/aksk.go +++ b/internal/biz/aksk.go @@ -74,7 +74,7 @@ func (a *AccessKeyAuth) AppValidator(ctx context.Context, req *gosdk.GatewayRequ return "", gosdk.NewError(errors.ErrRequestExpired, int32(api.APPSvrCode_APP_REQUEST_EXPIRED_ERR), codes.DeadlineExceeded, "app_timestamp") } - secret, err := a.app.GetSecret(ctx, accessKey) + secret, err := a.GetSecret(ctx, accessKey) if err != nil { return "", gosdk.NewError(err, int32(api.APPSvrCode_APP_UNKNOWN), codes.Unauthenticated, "app_secret") } diff --git a/internal/biz/aksk_test.go b/internal/biz/aksk_test.go index f544f7a..5a989c0 100644 --- a/internal/biz/aksk_test.go +++ b/internal/biz/aksk_test.go @@ -16,8 +16,10 @@ import ( "github.com/begonia-org/begonia/internal/data" cfg "github.com/begonia-org/begonia/internal/pkg/config" "github.com/begonia-org/begonia/internal/pkg/errors" + "github.com/begonia-org/begonia/internal/pkg/routers" "github.com/begonia-org/begonia/internal/pkg/utils" gosdk "github.com/begonia-org/go-sdk" + api "github.com/begonia-org/go-sdk/api/app/v1" c "github.com/smartystreets/goconvey/convey" "github.com/spark-lence/tiga" @@ -114,7 +116,18 @@ func testGetAPPID(t *testing.T) { c.So(appid, c.ShouldBeEmpty) }) } +func testIfNeedValidate(t *testing.T) { + c.Convey("test if need validate", t, func() { + ok := biz.IfNeedValidate(context.TODO(), akskAccess) + c.So(ok, c.ShouldBeFalse) + patch := gomonkey.ApplyFuncReturn((*routers.HttpURIRouteToSrvMethod).GetRouteByGrpcMethod, &routers.APIMethodDetails{AuthRequired: true}) + defer patch.Reset() + ok = biz.IfNeedValidate(context.TODO(), akskAccess) + c.So(ok, c.ShouldBeTrue) + patch.Reset() + }) +} func testValidator(t *testing.T) { signer := gosdk.NewAppAuthSigner(akskAccess, akskSecret) c.Convey("test validator success", t, func() { @@ -184,10 +197,39 @@ func testValidator(t *testing.T) { c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, errors.ErrAppSignatureInvalid.Error()) }) + + c.Convey("test validator fail with invalidate sk ak", t, func() { + req, err := http.NewRequest(http.MethodPost, "http://127.0.0.1:1949/api/v1/helloworld", strings.NewReader(`{"msg":"hello"}`)) + if err != nil { + t.Error(err) + return + } + req.Header.Add("content-type", "application/json") + + gw, err := gosdk.NewGatewayRequestFromHttp(req) + c.So(err, c.ShouldBeNil) + err = signer.SignRequest(gw) + c.So(err, c.ShouldBeNil) + patch := gomonkey.ApplyFuncReturn((*biz.AccessKeyAuth).GetSecret, "", fmt.Errorf("sk not found")) + defer patch.Reset() + aksk := newAKSK() + _, err = aksk.AppValidator(context.TODO(), gw) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "sk not found") + patch.Reset() + + patch2 := gomonkey.ApplyFuncReturn((*gosdk.AppAuthSignerImpl).Sign, "", fmt.Errorf("sign error")) + defer patch2.Reset() + _, err = aksk.AppValidator(context.TODO(), gw) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "sign error") + patch2.Reset() + }) } func TestAKSK(t *testing.T) { t.Run("get secret", testGetSecret) t.Run("get appid", testGetAPPID) t.Run("validator", testValidator) + t.Run("if need validate", testIfNeedValidate) } diff --git a/internal/biz/app_test.go b/internal/biz/app_test.go index 899aa6a..dec37f1 100644 --- a/internal/biz/app_test.go +++ b/internal/biz/app_test.go @@ -2,10 +2,12 @@ package biz_test import ( "context" + "crypto/rand" "fmt" "testing" "time" + "github.com/agiledragon/gomonkey/v2" "github.com/begonia-org/begonia" "github.com/begonia-org/begonia/config" "github.com/begonia-org/begonia/gateway" @@ -109,6 +111,36 @@ func testPutApp(t *testing.T) { err = appBiz.Put(context.TODO(), app2, "396870469984194560") c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, "Duplicate entry") + + patch := gomonkey.ApplyFuncReturn(rand.Read, 0, fmt.Errorf("read error")) + defer patch.Reset() + _, err = appBiz.CreateApp(context.TODO(), &api.AppsRequest{ + Name: appName, + Description: "test", + Tags: []string{"test-app"}, + }, "396870469984194560") + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "read error") + patch.Reset() + + patch2 := gomonkey.ApplyFuncReturn(biz.GenerateAppSecret, "", fmt.Errorf("generate secret error")) + defer patch2.Reset() + _, err = appBiz.CreateApp(context.TODO(), &api.AppsRequest{ + Name: appName, + Description: "test", + Tags: []string{"test-app"}, + }, "396870469984194560") + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "generate secret error") + patch2.Reset() + + _, err = appBiz.CreateApp(context.TODO(), &api.AppsRequest{ + Name: appName, + Description: "test", + Tags: []string{"test-app"}, + }, "396870469984194560") + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "Duplicate entry") }) } @@ -178,6 +210,23 @@ func testPatchApp(t *testing.T) { c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, "Duplicate entry") + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + config := config.ReadConfig(env) + repo := data.NewAppRepo(config, gateway.Log) + + patch := gomonkey.ApplyMethodReturn(repo, "Patch", fmt.Errorf("patch error")) + defer patch.Reset() + _, err = appBiz.Patch(context.TODO(), &api.AppsRequest{ + Appid: appid, + Name: appName2, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"name"}}, + }, "") + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "patch error") + patch.Reset() }) } @@ -203,24 +252,89 @@ func testListApp(t *testing.T) { }) c.So(len(apps), c.ShouldEqual, 0) c.So(err, c.ShouldBeNil) + + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + config := config.ReadConfig(env) + repo := data.NewAppRepo(config, gateway.Log) + + patch := gomonkey.ApplyMethodReturn(repo, "List",nil, fmt.Errorf("list error")) + defer patch.Reset() + _, err = appBiz.List(context.TODO(), &api.AppsListRequest{ + PageSize: 10, + Page: 1, + Tags: []string{"not-exist"}, + Status: []api.APPStatus{api.APPStatus_APP_DISABLED}, + }) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "list error") + patch.Reset() + }) } func testDelApp(t *testing.T) { + appBiz := newAppBiz() + c.Convey("test app del success", t, func() { - appBiz := newAppBiz() err := appBiz.Del(context.TODO(), appid) c.So(err, c.ShouldBeNil) _, err = appBiz.Get(context.TODO(), appid) c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, "not found") }) + c.Convey("test app del failed", t, func() { + err := appBiz.Del(context.TODO(), "123456") + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "not found") + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + config := config.ReadConfig(env) + repo := data.NewAppRepo(config, gateway.Log) + + patch := gomonkey.ApplyMethodReturn(repo, "Del", fmt.Errorf("del error")) + defer patch.Reset() + err = appBiz.Del(context.TODO(), appid) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "del error") + }) } +func testCache(t *testing.T) { + appBiz := newAppBiz() + + c.Convey("test app cache success", t, func() { + appName2 = fmt.Sprintf("app-biz-2-%s", time.Now().Format("20060102150405")) + access2, _ := utils.GenerateRandomString(32) + secret2, _ := utils.GenerateRandomString(64) + snk, _ := tiga.NewSnowflake(1) + app2 := &api.Apps{ + Appid: snk.GenerateIDString(), + AccessKey: access2, + Secret: secret2, + Status: api.APPStatus_APP_ENABLED, + IsDeleted: false, + Name: appName2, + Description: "test", + CreatedAt: timestamppb.New(time.Now()), + UpdatedAt: timestamppb.New(time.Now()), + } + err := appBiz.Cache(context.Background(), "app:test:prefix", app2, 3*time.Second) + c.So(err, c.ShouldBeNil) + + // app, err := appBiz.Get(context.Background(), app2.Appid) + + }) +} func TestAppBiz(t *testing.T) { t.Run("testPutApp", testPutApp) t.Run("testGetApp", testGetApp) t.Run("testPatchApp", testPatchApp) t.Run("testListApp", testListApp) + t.Run("testCache", testCache) t.Run("testDelApp", testDelApp) } diff --git a/internal/biz/authz.go b/internal/biz/authz.go index 011e2e1..e775ae3 100644 --- a/internal/biz/authz.go +++ b/internal/biz/authz.go @@ -161,7 +161,7 @@ func (u *AuthzUsecase) Logout(ctx context.Context, req *api.LogoutAPIRequest) er if len(token) == 0 { return gosdk.NewError(errors.ErrTokenMissing, int32(common.Code_TOKEN_NOT_FOUND), codes.InvalidArgument, "token_missing") } - err := u.repo.PutBlackList(ctx, tiga.GetMd5(token[0])) + err := u.PutBlackList(ctx, tiga.GetMd5(token[0])) if err != nil { return gosdk.NewError(err, int32(common.Code_AUTH_ERROR), codes.Internal, "add_black_list") } diff --git a/internal/biz/authz_test.go b/internal/biz/authz_test.go index d043c64..52c6215 100644 --- a/internal/biz/authz_test.go +++ b/internal/biz/authz_test.go @@ -61,6 +61,15 @@ func testAuthSeed(t *testing.T) { seedTimestampToken = fmt.Sprintf("%d", token) c.So(err, c.ShouldBeNil) seedAuthToken = seed + + patch := gomonkey.ApplyFuncReturn((crypto.UsersAuth).GenerateAuthSeed, "", fmt.Errorf("error auth seed")) + defer patch.Reset() + _, err = authzBiz.AuthSeed(context.TODO(), &v1.AuthLogAPIRequest{ + Token: fmt.Sprintf("%d", token), + }) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "error auth seed") + }) } @@ -207,6 +216,54 @@ func testLogin(t *testing.T) { c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, errors.ErrTokenExpired.Error()) }) + c.Convey("test login failed with invalid UserAuth", t, func() { + + info, _ := getUserAuth(adminUser, adminPasswd, pubKey, seedAuthToken, seedTimestampToken) + patch := gomonkey.ApplyFuncReturn(json.Marshal, nil, fmt.Errorf("error marshal")) + defer patch.Reset() + _, err = authzBiz.Login(context.TODO(), info) + + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "error marshal") + patch.Reset() + }) + c.Convey("test login failed with invalid EncryptAES", t, func() { + patch := gomonkey.ApplyFuncReturn(tiga.EncryptAES, "", fmt.Errorf("error encryptAES")) + defer patch.Reset() + info, _ := getUserAuth(adminUser, adminPasswd, pubKey, seedAuthToken, seedTimestampToken) + _, err := authzBiz.Login(context.TODO(), info) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrEncrypt.Error()) + patch.Reset() + + }) + + c.Convey("test login failed with invalid user status", t, func() { + mockUser := &v1.Users{ + Password: adminPasswd, + Name: adminUser, + Status: v1.USER_STATUS_LOCKED, + } + repo := data.NewUserRepo(config, gateway.Log) + patch := gomonkey.ApplyMethodReturn(repo, "Get", mockUser, nil) + defer patch.Reset() + info, err := getUserAuth(adminUser, adminPasswd, pubKey, seedAuthToken, seedTimestampToken) + c.So(err, c.ShouldBeNil) + _, err = authzBiz.Login(context.TODO(), info) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrUserDisabled.Error()) + patch.Reset() + }) + c.Convey("test login failed with jwt generate error", t, func() { + info, _ := getUserAuth(adminUser, adminPasswd, pubKey, seedAuthToken, seedTimestampToken) + patch := gomonkey.ApplyFuncReturn(tiga.GenerateJWT, nil, fmt.Errorf("error generate jwt")) + defer patch.Reset() + _, err = authzBiz.Login(context.TODO(), info) + + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "error generate jwt") + patch.Reset() + }) } @@ -231,12 +288,39 @@ func testLogout(t *testing.T) { c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, errors.ErrNoMetadata.Error()) + + patch := gomonkey.ApplyFuncReturn((*biz.AuthzUsecase).PutBlackList, fmt.Errorf("error PutBlackList")) + defer patch.Reset() + ctx = metadata.NewIncomingContext(context.Background(), metadata.Pairs("x-token", authzStr)) + err = authzBiz.Logout(ctx, &v1.LogoutAPIRequest{}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "error PutBlackList") + }) } +func testDelToken(t *testing.T) { + c.Convey("test del token", t, func() { + authzBiz := newAuthzBiz() + err := authzBiz.DelToken(context.TODO(), authzStr) + c.So(err, c.ShouldBeNil) + }) +} +func testPutBlackList(t *testing.T) { + authzBiz := newAuthzBiz() + c.Convey("test put black list", t, func() { + token := tiga.GetMd5("test") + err := authzBiz.PutBlackList(context.TODO(), token) + c.So(err, c.ShouldBeNil) + ok, err := authzBiz.CheckInBlackList(context.TODO(), token) + c.So(err, c.ShouldBeNil) + c.So(ok, c.ShouldBeTrue) + }) +} func TestAuthz(t *testing.T) { t.Run("test auth seed", testAuthSeed) t.Run("test login", testLogin) t.Run("test logout", testLogout) - + t.Run("test del token", testDelToken) + t.Run("test put black list", testPutBlackList) } diff --git a/internal/biz/data.go b/internal/biz/data.go index 6376065..9740b36 100644 --- a/internal/biz/data.go +++ b/internal/biz/data.go @@ -14,7 +14,6 @@ import ( "github.com/begonia-org/go-sdk/logger" "github.com/bsm/redislock" "go.etcd.io/etcd/api/v3/mvccpb" - "google.golang.org/grpc/status" ) type DataLock interface { @@ -54,20 +53,23 @@ func (d *DataOperatorUsecase) Do(ctx context.Context) { if err != nil { d.log.Error(ctx, err) } + if err := d.doWatchEndpoint(ctx); err != nil { + d.log.Error(ctx, err) + + } }() d.log.Info(ctx, "start watch") - d.handle(ctx) + d.Handle(ctx) time.Sleep(3 * time.Second) } -func (d *DataOperatorUsecase) handle(ctx context.Context) { +func (d *DataOperatorUsecase) Handle(ctx context.Context) { errChan := make(chan error, 3) wg := &sync.WaitGroup{} actions := []operationAction{ d.loadUsersBlacklist, d.loadApps, - d.doWatchEndpoint, // d.loadLocalBloom, } for _, action := range actions { @@ -82,9 +84,6 @@ func (d *DataOperatorUsecase) handle(ctx context.Context) { go func() { for err := range errChan { if err != nil { - if st, ok := status.FromError(err); ok { - st.Details() - } d.log.Error(ctx, err) } @@ -104,8 +103,8 @@ func (d *DataOperatorUsecase) loadUsersBlacklist(ctx context.Context) error { // d.log.Infof(ctx, "lock key:%d", exp) lock, err := d.repo.Locker(ctx, lockKey, time.Second*time.Duration(exp)) if err != nil { - // d.log.Error("get lock error", err) - return fmt.Errorf("get lock error: %w", err) + d.log.Errorf(ctx, "get lock error:%s", err.Error()) + return fmt.Errorf("get lock error:%w", err) } @@ -114,7 +113,6 @@ func (d *DataOperatorUsecase) loadUsersBlacklist(ctx context.Context) error { return fmt.Errorf("lock error: %w", err) } defer func() { - err = lock.UnLock(ctx) if err != nil { // d.log.Error("unlock error", err) @@ -125,7 +123,6 @@ func (d *DataOperatorUsecase) loadUsersBlacklist(ctx context.Context) error { }() prefix := d.config.GetUserBlackListPrefix() lastUpdate, err := d.repo.LastUpdated(ctx, prefix) - // d.log.Infof("last update:%v", lastUpdate.Unix()) // 如果缓存时间小于3秒,说明刚刚更新过,不需要再次更新 // 直接加载远程缓存到本地 // lastUpdate ttl 0 { + log.Printf("list tags:%v", in.Tags) ks, err := u.repo.GetKeysByTags(ctx, in.Tags) if err != nil { return nil, gosdk.NewError(err, int32(common.Code_INTERNAL_ERROR), codes.Internal, "get_keys_by_tags") diff --git a/internal/biz/endpoint/endpoint_test.go b/internal/biz/endpoint/endpoint_test.go index 0494116..40e8344 100644 --- a/internal/biz/endpoint/endpoint_test.go +++ b/internal/biz/endpoint/endpoint_test.go @@ -341,6 +341,23 @@ func testWatcherUpdate(t *testing.T) { err = watcher.Handle(context.TODO(), mvccpb.PUT, cnf.GetServiceKey(epId), string(val)) c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, "register error") + patch2.Reset() + gw := gateway.Get() + + patch3 := gomonkey.ApplyMethodReturn(gw, "DeleteHandlerClient", fmt.Errorf("test DeleteHandlerClient error")) + defer patch3.Reset() + err = watcher.Handle(context.TODO(), mvccpb.PUT, cnf.GetServiceKey(epId), string(val)) + patch3.Reset() + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "test DeleteHandlerClient error") + + patch4 := gomonkey.ApplyFuncReturn(gateway.NewLoadBalanceEndpoint,nil, fmt.Errorf("test gateway.NewLoadBalanceEndpoint error")) + defer patch4.Reset() + err = watcher.Handle(context.TODO(), mvccpb.PUT, cnf.GetServiceKey(epId), string(val)) + patch4.Reset() + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrUnknownLoadBalancer.Error()) + }) } @@ -379,6 +396,11 @@ func testWatcherDel(t *testing.T) { err = watcher.Handle(context.TODO(), mvccpb.DELETE, cnf.GetServiceKey(epId), string(val)) c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, "unregister error") + patch.Reset() + + err = watcher.Handle(context.TODO(), mvccpb.Event_EventType(3), cnf.GetServiceKey(epId), string(val)) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "unknown operation") }) } diff --git a/internal/biz/file/file.go b/internal/biz/file/file.go index d00281a..d0e9fcd 100644 --- a/internal/biz/file/file.go +++ b/internal/biz/file/file.go @@ -3,9 +3,9 @@ package file import ( "context" "crypto/sha256" + goErr "errors" "fmt" "io" - "log" "net/http" "os" "path/filepath" @@ -48,26 +48,11 @@ func NewFileUsecase(config *config.Config) *FileUsecase { func (f *FileUsecase) getPartsDir(key string) string { return filepath.Join(f.config.GetUploadDir(), key, "parts") } -func (f *FileUsecase) spiltKey(key string) (string, string, error) { - if strings.HasPrefix(key, "/") { - return "", "", gosdk.NewError(errors.ErrInvalidFileKey, int32(api.FileSvrStatus_FILE_INVALIDATE_KEY_ERR), codes.InvalidArgument, "invalid_key") - } - if strings.Contains(key, "/") { - name := filepath.Base(key) - // filename := getFilenameWithoutExt(name) - return filepath.Dir(key), name, nil - } - return "", key, nil -} func (f *FileUsecase) InitiateUploadFile(ctx context.Context, in *api.InitiateMultipartUploadRequest) (*api.InitiateMultipartUploadResponse, error) { if in.Key == "" || strings.HasPrefix(in.Key, "/") { return nil, gosdk.NewError(errors.ErrInvalidFileKey, int32(api.FileSvrStatus_FILE_INVALIDATE_KEY_ERR), codes.InvalidArgument, "invalid_key") } uploadId := f.snowflake.GenerateIDString() - _, _, err := f.spiltKey(in.Key) - if err != nil { - return nil, err - } saveDir := f.getPartsDir(uploadId) if err := os.MkdirAll(saveDir, 0755); err != nil { err = gosdk.NewError(err, int32(common.Code_INTERNAL_ERROR), codes.Internal, "create_upload_dir") @@ -124,7 +109,7 @@ func (f *FileUsecase) commitFile(dir string, filename string, authorId string, a err = p.(error) } if err != nil { - err = w.Reset(&git.ResetOptions{Mode: git.HardReset}) + _ = w.Reset(&git.ResetOptions{Mode: git.HardReset}) } }() @@ -144,14 +129,14 @@ func (f *FileUsecase) commitFile(dir string, filename string, authorId string, a // 打印新提交的ID obj, err := repo.CommitObject(commit) - if err != nil && err != git.ErrEmptyCommit { + if err != nil && !goErr.Is(err, git.ErrEmptyCommit) { return "", err } // 空提交处理 - if err == git.ErrEmptyCommit { + if goErr.Is(err, git.ErrEmptyCommit) { headRef, err := repo.Head() - if err != nil { - return "", err + if err != nil || headRef.Hash().IsZero() { + return "", fmt.Errorf("get head ref error:%w or head ref is nil", err) } return headRef.Hash().String(), nil } @@ -178,12 +163,6 @@ func (f *FileUsecase) checkIn(key string) (string, error) { if key == "" || strings.HasPrefix(key, "/") { return "", gosdk.NewError(errors.ErrInvalidFileKey, int32(api.FileSvrStatus_FILE_INVALIDATE_KEY_ERR), codes.InvalidArgument, "invalid_key") } - // if authorId == "" { - // return "", gosdk.NewError(errors.ErrIdentityMissing, int32(user.UserSvrCode_USER_IDENTITY_MISSING_ERR), codes.InvalidArgument, "not_found_identity") - // } - // if !strings.HasPrefix(key, authorId) { - // key = authorId + "/" + key - // } return key, nil } @@ -363,7 +342,7 @@ func (f *FileUsecase) getPersistenceKeyParts(key string) string { } func (f *FileUsecase) getUri(filePath string) (string, error) { uploadRootDir := f.config.GetUploadDir() - log.Printf("uploadRootDir:%s,filePath:%s", uploadRootDir, filePath) + // log.Printf("uploadRootDir:%s,filePath:%s", uploadRootDir, filePath) uri, err := filepath.Rel(uploadRootDir, filePath) if err != nil { return "", gosdk.NewError(err, int32(common.Code_INTERNAL_ERROR), codes.Internal, "get_file_uri") @@ -395,7 +374,7 @@ func (f *FileUsecase) CompleteMultipartUploadFile(ctx context.Context, in *api.C in.Key = filepath.Join(authorId, key) partsDir := f.getPartsDir(in.UploadId) if !pathExists(partsDir) { - err := gosdk.NewError(errors.ErrUploadIdNotFound, int32(api.FileSvrStatus_FILE_NOT_FOUND_UPLOADID_ERR), codes.NotFound, "upload_id_not_found") + err := gosdk.NewError(fmt.Errorf("%s:%s", in.UploadId, errors.ErrUploadIdNotFound.Error()), int32(api.FileSvrStatus_FILE_NOT_FOUND_UPLOADID_ERR), codes.NotFound, "upload_id_not_found") return nil, err } @@ -411,7 +390,7 @@ func (f *FileUsecase) CompleteMultipartUploadFile(ctx context.Context, in *api.C // merge files to uploadDir/key err = f.mergeFiles(files, filePath) if err != nil { - return nil, gosdk.NewError(fmt.Errorf("merge file error"), int32(common.Code_INTERNAL_ERROR), codes.Internal, "merge_files") + return nil, gosdk.NewError(fmt.Errorf("merge file error:%w", err), int32(common.Code_INTERNAL_ERROR), codes.Internal, "merge_files") } // the parts file has been merged, remove the parts dir to uploadDir/parts/key keyParts := f.getPersistenceKeyParts(in.Key) @@ -435,7 +414,6 @@ func (f *FileUsecase) CompleteMultipartUploadFile(ctx context.Context, in *api.C return nil, gosdk.NewError(err, int32(common.Code_INTERNAL_ERROR), codes.Internal, "commit_file") } } - os.RemoveAll(filepath.Join(f.config.GetUploadDir(), in.UploadId)) return &api.CompleteMultipartUploadResponse{ @@ -450,18 +428,16 @@ func (f *FileUsecase) DownloadForRange(ctx context.Context, in *api.DownloadRequ return nil, 0, err } in.Key = key - if start > end { - err := gosdk.NewError(errors.ErrInvalidRange, int32(api.FileSvrStatus_FILE_INVALIDATE_RANGE_ERR), codes.InvalidArgument, "invalid_range") + if start > end && end > 0{ + err := gosdk.NewError(fmt.Errorf("%w:start=%d,end=%d", errors.ErrInvalidRange, start, end), int32(api.FileSvrStatus_FILE_INVALIDATE_RANGE_ERR), codes.InvalidArgument, "invalid_range") return nil, 0, err } file, err := f.getReader(in.Key, in.Version) - if err == git.ErrRepositoryNotExists || os.IsNotExist(err) { - return nil, 0, gosdk.NewError(err, int32(common.Code_NOT_FOUND), codes.NotFound, "file_not_found") - } if err != nil { - return nil, 0, gosdk.NewError(err, int32(common.Code_INTERNAL_ERROR), codes.Internal, "open_file") + code, grcpCode := f.checkStatusCode(err) + return nil, 0, gosdk.NewError(err, code, grcpCode, "open_file") } defer file.Close() @@ -469,9 +445,8 @@ func (f *FileUsecase) DownloadForRange(ctx context.Context, in *api.DownloadRequ if end > 0 { buf = make([]byte, end-start+1) } else { - buf = make([]byte, file.Size()-start+1) + buf = make([]byte, file.Size()-start) } - // log.Printf("start:%d,end:%d,bufsize:%d", start, end, len(buf)) _, err = file.ReadAt(buf, start) if err != nil && err != io.EOF { err = gosdk.NewError(err, int32(common.Code_INTERNAL_ERROR), codes.Internal, "read_file") @@ -489,7 +464,8 @@ func (f *FileUsecase) Metadata(ctx context.Context, in *api.FileMetadataRequest, in.Key = key file, err := f.getReader(in.Key, in.Version) if err != nil { - return nil, gosdk.NewError(err, int32(common.Code_INTERNAL_ERROR), codes.Internal, "open_file") + code, grpcCode := f.checkStatusCode(err) + return nil, gosdk.NewError(err, code, grpcCode, "open_file") } hasher := sha256.New() @@ -543,7 +519,6 @@ func (f *FileUsecase) getReader(key string, version string) (FileReader, error) var err error if version != "" { fileReader, err = NewFileVersionReader(filePath, version) - // log.Printf("version fileReader:%v", err) if err != nil { return nil, err } @@ -562,13 +537,10 @@ func (f *FileUsecase) Version(ctx context.Context, key, authorId string) (string if err != nil { return "", err } - // fileDir := filepath.Join(f.config.GetUploadDir(), in.Key) file, err := f.getReader(key, "latest") - if err == git.ErrRepositoryNotExists { - return "", gosdk.NewError(err, int32(common.Code_NOT_FOUND), codes.NotFound, "file_not_found") - } if err != nil { - return "", gosdk.NewError(err, int32(common.Code_INTERNAL_ERROR), codes.Internal, "open_file") + code, grpcCode := f.checkStatusCode(err) + return "", gosdk.NewError(err, code, grpcCode, "open_file") } defer file.Close() return file.(FileVersionReader).Version(), nil diff --git a/internal/biz/file/file_test.go b/internal/biz/file/file_test.go index 3d95399..e2cc41e 100644 --- a/internal/biz/file/file_test.go +++ b/internal/biz/file/file_test.go @@ -20,7 +20,9 @@ import ( "github.com/begonia-org/begonia/config" "github.com/begonia-org/begonia/internal/biz/file" api "github.com/begonia-org/go-sdk/api/file/v1" + "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/object" cfg "github.com/begonia-org/begonia/internal/pkg/config" "github.com/begonia-org/begonia/internal/pkg/errors" @@ -328,6 +330,20 @@ func testPutFile(t *testing.T) { c.So(err, c.ShouldNotBeNil) c.So(rsp, c.ShouldBeNil) c.So(err.Error(), c.ShouldContainSubstring, "write error") + + patch2 := gomonkey.ApplyFuncReturn(filepath.Rel, "", fmt.Errorf("rel error")) + defer patch2.Reset() + rsp, err = fileBiz.Upload(context.TODO(), &api.UploadFileRequest{ + Key: "test/upload.test6", + Content: nil, + ContentType: tmp.contentType, + UseVersion: true, + Sha256: tmp.sha256, + }, fileAuthor3) + c.So(err, c.ShouldNotBeNil) + c.So(rsp, c.ShouldBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "rel error") + patch2.Reset() }) } @@ -432,6 +448,50 @@ func testDownload(t *testing.T) { } }) } + c.Convey("test download fail", t, func() { + _, err := fileBiz.Download(context.TODO(), &api.DownloadRequest{ + Key: "/" + fileAuthor + "/test/upload.test1", + }, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrInvalidFileKey.Error()) + + env := "dev" + if begonia.Env != "" { + env = begonia.Env + + } + config := config.ReadConfig(env) + cnf := cfg.NewConfig(config) + filePath := filepath.Join(cnf.GetUploadDir(), fileAuthor, "test", "upload.test2") + t.Logf("filepath:%s", filePath) + reader, err := file.NewFileVersionReader(filePath, "latest") + c.So(err, c.ShouldBeNil) + patch := gomonkey.ApplyMethodReturn(reader, "Reader", nil, fmt.Errorf("reader error")) + defer patch.Reset() + _, err = fileBiz.Download(context.TODO(), &api.DownloadRequest{ + Key: fileAuthor + "/test/upload.test2", + Version: "latest", + }, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "reader error") + patch.Reset() + file, err := file.NewFileVersionReader(filepath.Join(cnf.GetUploadDir(), fileAuthor, "test", "upload.test2"), "latest") + c.So(err, c.ShouldBeNil) + ioReader, err := file.Reader() + c.So(err, c.ShouldBeNil) + patch2 := gomonkey.ApplyMethodReturn(ioReader, "Read", 0, fmt.Errorf("error read file")) + defer patch2.Reset() + _, err = fileBiz.Download(context.TODO(), &api.DownloadRequest{ + Key: fileAuthor + "/test/upload.test2", + Version: "latest", + }, fileAuthor) + + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "error read file") + patch2.Reset() + + // patch2:=gomonkey.ApplyFuncReturn((*object.File).) + }) } func testInitiateUploadFile(t *testing.T) { @@ -462,6 +522,14 @@ func testInitiateUploadFile(t *testing.T) { c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, errors.ErrInvalidFileKey.Error()) + patch := gomonkey.ApplyFuncReturn(os.MkdirAll, fmt.Errorf("mkdir error")) + defer patch.Reset() + _, err = fileBiz.InitiateUploadFile(context.TODO(), &api.InitiateMultipartUploadRequest{ + Key: "test/upload.parts.test1", + }) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "mkdir error") + }) } @@ -585,7 +653,47 @@ func testUploadMultipartFileFile(t *testing.T) { c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, errors.ErrSHA256NotMatch.Error()) + patch := gomonkey.ApplyFuncReturn(os.Create, nil, fmt.Errorf("file create error")) + defer patch.Reset() + _, err = fileBiz.UploadMultipartFileFile(context.TODO(), &api.UploadMultipartFileRequest{ + Key: "test/upload.parts.test1", + UploadId: rsp.UploadId, + PartNumber: 1, + Content: tmpFile2.content, + Sha256: tmpFile2.sha256, + }) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "file create error") + patch.Reset() + + patch2 := gomonkey.ApplyFuncReturn((*os.File).Write, 0, fmt.Errorf("write error")) + defer patch2.Reset() + + _, err = fileBiz.UploadMultipartFileFile(context.TODO(), &api.UploadMultipartFileRequest{ + Key: "test/upload.parts.test1", + UploadId: rsp.UploadId, + PartNumber: 1, + Content: tmpFile2.content, + Sha256: tmpFile2.sha256, + }) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "write error") + patch2.Reset() + patch3 := gomonkey.ApplyFuncReturn(filepath.Rel, "", fmt.Errorf("rel error")) + defer patch3.Reset() + + _, err = fileBiz.UploadMultipartFileFile(context.TODO(), &api.UploadMultipartFileRequest{ + Key: "test/upload.parts.test1", + UploadId: rsp.UploadId, + PartNumber: 1, + Content: tmpFile2.content, + Sha256: tmpFile2.sha256, + }) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "rel error") + patch3.Reset() }) + } func testAbortMultipartUpload(t *testing.T) { fileBiz := newFileBiz() @@ -652,14 +760,105 @@ func testCompleteMultipartUploadFile(t *testing.T) { }) c.Convey("test complete parts file fail", t, func() { + _, err := fileBiz.CompleteMultipartUploadFile(context.TODO(), &api.CompleteMultipartUploadRequest{ - Key: "test/upload.parts.test1", + Key: "test/upload.parts.test2", UploadId: "123455678098", }, fileAuthor) c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, errors.ErrUploadIdNotFound.Error()) + _, err = fileBiz.CompleteMultipartUploadFile(context.TODO(), &api.CompleteMultipartUploadRequest{ + Key: "test/upload.parts.test2", + UploadId: "123455678098", + }, "") + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrIdentityMissing.Error()) + + _, err = fileBiz.CompleteMultipartUploadFile(context.TODO(), &api.CompleteMultipartUploadRequest{ + Key: "/test/upload.parts.test2", + UploadId: "123455678098", + }, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrInvalidFileKey.Error()) + + patch := gomonkey.ApplyFuncReturn(os.Lstat, nil, fmt.Errorf("lstat error")) + defer patch.Reset() + rsp, _ := fileBiz.InitiateUploadFile(context.TODO(), &api.InitiateMultipartUploadRequest{ + Key: "test/upload.parts.test2", + }) + uploadId2 := rsp.UploadId + _, err = fileBiz.CompleteMultipartUploadFile(context.TODO(), &api.CompleteMultipartUploadRequest{ + Key: "test/upload.parts.test2", + UploadId: uploadId2, + UseVersion: true, + }, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "lstat error") + patch.Reset() + + cases := []struct { + patch interface{} + output []interface{} + err error + }{ + { + patch: os.MkdirAll, + output: []interface{}{fmt.Errorf("mkdir error")}, + err: fmt.Errorf("mkdir error"), + }, { + patch: os.Create, + output: []interface{}{nil, fmt.Errorf("create error")}, + err: fmt.Errorf("create error"), + }, { + patch: os.Open, + output: []interface{}{nil, fmt.Errorf("open error")}, + err: fmt.Errorf("open error"), + }, + { + patch: io.Copy, + output: []interface{}{int64(0), fmt.Errorf("copy error")}, + err: fmt.Errorf("copy error"), + }, + { + patch: os.RemoveAll, + output: []interface{}{fmt.Errorf("remove all error")}, + err: fmt.Errorf("remove all error"), + }, { + patch: filepath.Rel, + output: []interface{}{"", fmt.Errorf("rel error")}, + err: fmt.Errorf("rel error"), + }, { + patch: git.PlainInit, + output: []interface{}{nil, fmt.Errorf("init error")}, + err: fmt.Errorf("init error"), + }, + } + + for _, cases := range cases { + rsp, _ = fileBiz.InitiateUploadFile(context.TODO(), &api.InitiateMultipartUploadRequest{ + Key: "test/upload.parts.test2", + }) + uploadId3 := rsp.UploadId + bigTmpFile, _ := generateRandomFile(1024 * 1024 * 2) + defer os.Remove(bigTmpFile.path) + _ = uploadParts(bigTmpFile.path, uploadId3, "test/upload.parts.test2", t) + os.Remove(bigTmpFile.path) + patch2 := gomonkey.ApplyFuncReturn(cases.patch, cases.output...) + defer patch2.Reset() + _, err = fileBiz.CompleteMultipartUploadFile(context.TODO(), &api.CompleteMultipartUploadRequest{ + Key: "test/upload.parts.test2", + UploadId: uploadId3, + UseVersion: true, + }, fileAuthor) + patch2.Reset() + + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, cases.err.Error()) + + } }) + } func testFileMeta(t *testing.T) { fileBiz := newFileBiz() @@ -672,21 +871,61 @@ func testFileMeta(t *testing.T) { c.So(meta, c.ShouldNotBeNil) c.So(meta.Size, c.ShouldEqual, 1024*1024*12) c.So(meta.Sha256, c.ShouldEqual, bigFileSha256) + + meta, err = fileBiz.Metadata(context.Background(), &api.FileMetadataRequest{ + Key: fileAuthor + "/test/upload.parts.test1", + Version: "latest", + }, fileAuthor) + c.So(err, c.ShouldBeNil) + c.So(meta, c.ShouldNotBeNil) + c.So(meta.Size, c.ShouldEqual, 1024*1024*12) + c.So(meta.Sha256, c.ShouldEqual, bigFileSha256) }) c.Convey("test file metadata fail", t, func() { - // _, err := fileBiz.Metadata(context.Background(), &api.FileMetadataRequest{ - // Key: fileAuthor + "/test/upload.parts.test1", - // Version: "", - // }, "") - // c.So(err, c.ShouldNotBeNil) - // c.So(err.Error(), c.ShouldContainSubstring, errors.ErrIdentityMissing.Error()) - _, err := fileBiz.Metadata(context.Background(), &api.FileMetadataRequest{ Key: "", Version: "", }, fileAuthor) c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, errors.ErrInvalidFileKey.Error()) + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + conf := config.ReadConfig(env) + cnf := cfg.NewConfig(conf) + filePath := filepath.Join(cnf.GetUploadDir(), filepath.Dir(fileAuthor+"/test/upload.parts.test1")) + filePath = filepath.Join(filePath, filepath.Base(fileAuthor+"/test/upload.parts.test1")) + + patch := gomonkey.ApplyFuncReturn(file.NewFileVersionReader, nil, fmt.Errorf("file NewFileVersionReader error")) + defer patch.Reset() + _, err = fileBiz.Metadata(context.Background(), &api.FileMetadataRequest{ + Key: fileAuthor + "/test/upload.parts.test1", + Version: "latest", + }, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "file NewFileVersionReader error") + patch.Reset() + + reader, err := file.NewFileVersionReader(filePath, "latest") + c.So(err, c.ShouldBeNil) + patch2 := gomonkey.ApplyMethodReturn(reader, "Reader", nil, fmt.Errorf("file Reader error")) + defer patch2.Reset() + _, err = fileBiz.Metadata(context.Background(), &api.FileMetadataRequest{ + Key: fileAuthor + "/test/upload.parts.test1", + Version: "latest", + }, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "file Reader error") + patch2.Reset() + + patch3 := gomonkey.ApplyFuncReturn(io.Copy, int64(0), fmt.Errorf("io.copy error")) + defer patch3.Reset() + _, err = fileBiz.Metadata(context.Background(), &api.FileMetadataRequest{Key: fileAuthor + "/test/upload.parts.test1", + Version: "latest"}, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "io.copy error") + }) } func testVersionReader(t *testing.T) { @@ -710,6 +949,80 @@ func testVersionReader(t *testing.T) { c.So(fileReader, c.ShouldNotBeNil) }) + c.Convey("test version reader fail", t, func() { + fileBiz := newFileBiz() + _, err := fileBiz.Version(context.Background(), "/test/version.test", fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrInvalidFileKey.Error()) + patch := gomonkey.ApplyFuncReturn(file.NewFileVersionReader, nil, fmt.Errorf("file NewFileVersionReader error")) + defer patch.Reset() + _, err = fileBiz.Version(context.Background(), fileAuthor+"/test/upload.parts.test1", fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "file NewFileVersionReader error") + patch.Reset() + patch2 := gomonkey.ApplyFuncReturn(git.PlainOpen, nil, fmt.Errorf("git PlainOpen error")) + defer patch2.Reset() + _, err = file.NewFileVersionReader(fileAuthor+"/test/upload.parts.test1", "latest") + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "git PlainOpen error") + patch2.Reset() + + patch3 := gomonkey.ApplyFuncReturn((*git.Repository).Head, nil, fmt.Errorf("head error")) + defer patch3.Reset() + root := cnf.GetUploadDir() + path := filepath.Join(root, fileAuthor, "test", "upload.parts.test2") + _, err = file.NewFileVersionReader(path, "latest") + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "head error") + patch3.Reset() + + filePath := filepath.Join(cnf.GetUploadDir(), filepath.Dir(fileAuthor+"/test/upload.parts.test1")) + filePath = filepath.Join(filePath, filepath.Base(fileAuthor+"/test/upload.parts.test1")) + reader, err := file.NewFileVersionReader(filePath, "latest") + c.So(err, c.ShouldBeNil) + cases := []struct { + patch interface{} + output []interface{} + err error + }{ + { + patch: (*git.Repository).CommitObject, + output: []interface{}{nil, fmt.Errorf("commit object error")}, + err: fmt.Errorf("commit object error"), + }, + { + patch: (*object.Commit).Tree, + output: []interface{}{nil, fmt.Errorf("tree error")}, + err: fmt.Errorf("tree error"), + }, + { + patch: (*object.Tree).File, + output: []interface{}{nil, fmt.Errorf("file error")}, + err: fmt.Errorf("file error"), + }, + { + patch: io.CopyN, + output: []interface{}{ + int64(0), fmt.Errorf("copy error"), + }, + err: fmt.Errorf("copy error"), + }, + { + patch: io.ReadFull, + output: []interface{}{0, fmt.Errorf("read full error")}, + err: fmt.Errorf("read full error"), + }, + } + for _, cases := range cases { + patch4 := gomonkey.ApplyFuncReturn(cases.patch, cases.output...) + defer patch4.Reset() + _, err := reader.ReadAt(make([]byte, 1024), 512) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, cases.err.Error()) + patch4.Reset() + } + // _, err = fileBiz.Version(context.Background(), fileAuthor+"/test/upload.parts.test1", fileAuthor) + }) } func testDownloadRange(t *testing.T) { fileBiz := newFileBiz() @@ -735,6 +1048,24 @@ func testDownloadRange(t *testing.T) { } b := shaer.Sum(nil) c.So(hex.EncodeToString(b), c.ShouldEqual, bigFileSha256) + + shaer2 := sha256.New() + data, _, err := fileBiz.DownloadForRange(context.Background(), &api.DownloadRequest{ + Key: fileAuthor + "/test/upload.parts.test1", + Version: "latest", + }, 0, 0, fileAuthor) + c.So(err, c.ShouldBeNil) + shaer2.Write(data) + c.So(hex.EncodeToString(shaer2.Sum(nil)), c.ShouldEqual, bigFileSha256) + + shaer3 := sha256.New() + data, _, err = fileBiz.DownloadForRange(context.Background(), &api.DownloadRequest{ + Key: fileAuthor + "/test/upload.parts.test1", + Version: "", + }, 0, 0, fileAuthor) + c.So(err, c.ShouldBeNil) + shaer3.Write(data) + c.So(hex.EncodeToString(shaer3.Sum(nil)), c.ShouldEqual, bigFileSha256) }) c.Convey("test download range parts file fail", t, func() { _, _, err := fileBiz.DownloadForRange(context.Background(), &api.DownloadRequest{ @@ -749,6 +1080,50 @@ func testDownloadRange(t *testing.T) { }, 0, 1024, fileAuthor) c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, errors.ErrInvalidFileKey.Error()) + + _, _, err = fileBiz.DownloadForRange(context.Background(), &api.DownloadRequest{ + Key: "test/upload.parts.test1", + Version: "latest", + }, 1024, 1, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrInvalidRange.Error()) + + _, _, err = fileBiz.DownloadForRange(context.Background(), &api.DownloadRequest{ + Key: fileAuthor + "/test/upload.parts.test1", + Version: "latest", + }, 1024, 0, fileAuthor) + c.So(err, c.ShouldBeNil) + patch := gomonkey.ApplyFuncReturn(file.NewFileVersionReader, nil, git.ErrRepositoryNotExists) + defer patch.Reset() + _, _, err = fileBiz.DownloadForRange(context.Background(), &api.DownloadRequest{ + Key: "test/upload.parts.test1", + Version: "latest", + }, 0, 1024, fileAuthor) + patch.Reset() + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, git.ErrRepositoryNotExists.Error()) + patch.Reset() + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + conf := config.ReadConfig(env) + cnf := cfg.NewConfig(conf) + filePath := filepath.Join(cnf.GetUploadDir(), filepath.Dir(fileAuthor+"/test/upload.parts.test1")) + filePath = filepath.Join(filePath, filepath.Base(fileAuthor+"/test/upload.parts.test1")) + reader, err := file.NewFileVersionReader(filePath, "latest") + c.So(err, c.ShouldBeNil) + patch2 := gomonkey.ApplyMethodReturn(reader, "ReadAt", 0, fmt.Errorf("file readAt error")) + defer patch2.Reset() + + _, _, err = fileBiz.DownloadForRange(context.Background(), &api.DownloadRequest{ + Key: fileAuthor + "/test/upload.parts.test1", + Version: "latest", + }, 0, 1024, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "file readAt error") + patch2.Reset() + }) } func testDelete(t *testing.T) { @@ -759,6 +1134,32 @@ func testDelete(t *testing.T) { } config := config.ReadConfig(env) cnf := cfg.NewConfig(config) + + c.Convey("test delete file fail", t, func() { + patch := gomonkey.ApplyFuncReturn(file.NewFileReader, nil, fmt.Errorf("file not found")) + defer patch.Reset() + _, err := fileBiz.Delete(context.Background(), &api.DeleteRequest{Key: fileAuthor + "/test/upload.parts.deleted"}, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "file not found") + patch.Reset() + + _, err = fileBiz.Delete(context.Background(), &api.DeleteRequest{Key: fileAuthor + "/test/upload.parts.deleted2"}, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "not found") + + _, err = fileBiz.Delete(context.Background(), &api.DeleteRequest{Key: "/" + fileAuthor + "/test/upload.parts.deleted2"}, fileAuthor) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrInvalidFileKey.Error()) + + patch2 := gomonkey.ApplyFuncReturn(os.RemoveAll, fmt.Errorf("remove all error")) + defer patch2.Reset() + _, err = fileBiz.Delete(context.Background(), &api.DeleteRequest{Key: fileAuthor + "/test/upload.parts.test1"}, fileAuthor) + patch2.Reset() + + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "remove all error") + + }) c.Convey("test delete file success", t, func() { rsp, err := fileBiz.Delete(context.Background(), &api.DeleteRequest{Key: fileAuthor + "/test/upload.parts.test1"}, fileAuthor) c.So(err, c.ShouldBeNil) @@ -769,23 +1170,94 @@ func testDelete(t *testing.T) { c.So(err, c.ShouldNotBeNil) }) - c.Convey("test delete file fail", t, func() { - patch := gomonkey.ApplyFuncReturn(file.NewFileReader, nil, fmt.Errorf("file not found")) + +} +func testUploadVersionCommitErr(t *testing.T) { + fileBiz := newFileBiz() + c.Convey("test upload version commit error", t, func() { + var err error + tmp2, err := generateRandomFile(1024 * 1024 * 1) + if err != nil { + t.Error(err) + } + defer os.Remove(tmp2.path) + cases := []struct { + patch interface{} + output []interface{} + err error + }{ + { + patch: git.PlainInit, + output: []interface{}{nil, fmt.Errorf("commit error")}, + err: fmt.Errorf("commit error"), + }, + { + patch: (*git.Repository).Worktree, + output: []interface{}{nil, fmt.Errorf("worktree error")}, + err: fmt.Errorf("worktree error"), + }, + { + patch: (*git.Worktree).Add, + output: []interface{}{nil, fmt.Errorf("add error")}, + err: fmt.Errorf("add error"), + }, + { + patch: (*git.Worktree).Commit, + output: []interface{}{nil, fmt.Errorf("commit error")}, + err: fmt.Errorf("commit error"), + }, + { + patch: (*git.Repository).CommitObject, + output: []interface{}{nil, fmt.Errorf("commit object error")}, + err: fmt.Errorf("commit object error"), + }, + } + fileAuthor2 := fmt.Sprintf("tester-fail-%s", time.Now().Format("20060102150405")) + for index, caseV := range cases { + t.Logf("test case %d", index) + patch := gomonkey.ApplyFuncReturn(caseV.patch, caseV.output...) + defer patch.Reset() + _, err := fileBiz.Upload(context.TODO(), &api.UploadFileRequest{ + Key: "test/upload_version.test1", + Content: tmp2.content, + ContentType: tmp2.contentType, + UseVersion: true, + Sha256: tmp2.sha256, + }, fileAuthor2) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, caseV.err.Error()) + patch.Reset() + } + + patch := gomonkey.ApplyFuncReturn(git.PlainInit, nil, git.ErrRepositoryAlreadyExists) + patch = patch.ApplyFuncReturn(git.PlainOpen, nil, fmt.Errorf("open error")) defer patch.Reset() - _, err := fileBiz.Delete(context.Background(), &api.DeleteRequest{Key: fileAuthor + "/test/upload.parts.deleted"}, fileAuthor) + f := &api.UploadFileRequest{ + Key: "test/upload_version.test1", + Content: tmp2.content, + ContentType: tmp2.contentType, + UseVersion: true, + Sha256: tmp2.sha256, + } + _, err = fileBiz.Upload(context.TODO(), f, fileAuthor2) c.So(err, c.ShouldNotBeNil) - c.So(err.Error(), c.ShouldContainSubstring, "file not found") + c.So(err.Error(), c.ShouldContainSubstring, "open error") patch.Reset() - _, err = fileBiz.Delete(context.Background(), &api.DeleteRequest{Key: fileAuthor+"/test/upload.parts.deleted2"}, fileAuthor) + patch2 := gomonkey.ApplyFuncReturn((*git.Repository).CommitObject, nil, git.ErrEmptyCommit) + patch2 = patch2.ApplyFuncReturn((*git.Repository).Head, nil, fmt.Errorf("head error")) + defer patch2.Reset() + _, err = fileBiz.Upload(context.TODO(), f, fileAuthor2) c.So(err, c.ShouldNotBeNil) - c.So(err.Error(), c.ShouldContainSubstring, "not found") + c.So(err.Error(), c.ShouldContainSubstring, "head error") + t.Logf("test upload version commit error end,%s", err.Error()) + patch2.Reset() }) - } func TestFile(t *testing.T) { t.Run("test upload", testPutFile) + t.Run("test upload version commit error", testUploadVersionCommitErr) t.Run("test download", testDownload) t.Run("test initiate upload file", testInitiateUploadFile) t.Run("test upload parts file", testUploadMultipartFileFile) diff --git a/internal/biz/file/reader.go b/internal/biz/file/reader.go index c2e43e6..4da03fb 100644 --- a/internal/biz/file/reader.go +++ b/internal/biz/file/reader.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "io/fs" + "log" "os" "path/filepath" @@ -148,7 +149,7 @@ func NewFileVersionReader(path string, version string) (FileVersionReader, error fileName := filepath.Base(path) repo, err := git.PlainOpen(dir) if err != nil { - // log.Printf("failed to open git repository: %v", err) + log.Printf("failed to open git repository,%s: %v",dir, err) return nil, err } diff --git a/internal/biz/file/reader_test.go b/internal/biz/file/reader_test.go new file mode 100644 index 0000000..96cbea9 --- /dev/null +++ b/internal/biz/file/reader_test.go @@ -0,0 +1 @@ +package file_test diff --git a/internal/biz/user_test.go b/internal/biz/user_test.go index 0456be8..771fd1e 100644 --- a/internal/biz/user_test.go +++ b/internal/biz/user_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/agiledragon/gomonkey/v2" "github.com/begonia-org/begonia" "github.com/begonia-org/begonia/config" "github.com/begonia-org/begonia/gateway" @@ -66,7 +67,7 @@ func testPutUser(t *testing.T) { Name: username2, Dept: "dev", Email: fmt.Sprintf("user2-biz%s@example.com", time.Now().Format("20060102150405")), - Phone: time.Now().Format("20060102150405"), + Phone: snk.GenerateIDString(), Role: api.Role_ADMIN, Avatar: "https://www.example.com/avatar.jpg", Owner: "test-user-01", @@ -81,7 +82,7 @@ func testPutUser(t *testing.T) { }) c.Convey("test user put failed", t, func() { uid3 := snk.GenerateIDString() - err := userBiz.Add(context.TODO(), &api.Users{ + user := &api.Users{ Uid: uid3, Name: username, Dept: "dev", @@ -93,10 +94,22 @@ func testPutUser(t *testing.T) { CreatedAt: timestamppb.Now(), UpdatedAt: timestamppb.Now(), Status: api.USER_STATUS_ACTIVE, - }) + } + err := userBiz.Add(context.TODO(), user) c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, "Duplicate entry") + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + repo := data.NewUserRepo(config.ReadConfig(env), gateway.Log) + patch := gomonkey.ApplyMethodReturn(repo, "Add", fmt.Errorf("error in your SQL syntax")) + defer patch.Reset() + err = userBiz.Add(context.TODO(), user) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "error in your SQL syntax") + }) } func testGetUser(t *testing.T) { @@ -143,6 +156,23 @@ func testPatchUser(t *testing.T) { }) c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, "error in your SQL syntax") + snk, _ := tiga.NewSnowflake(1) + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + config := config.ReadConfig(env) + repo := data.NewUserRepo(config, gateway.Log) + patch := gomonkey.ApplyMethodReturn(repo, "Patch", fmt.Errorf("not found err")) + defer patch.Reset() + err = userBiz.Update(context.TODO(), &api.Users{ + Uid: snk.GenerateIDString(), + Name: "test", + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"name"}}, + }) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "not found") + patch.Reset() }) } @@ -182,7 +212,25 @@ func testListUser(t *testing.T) { users, err := userBiz.List(context.TODO(), []string{"unknown"}, []api.USER_STATUS{api.USER_STATUS_DELETED}, 1, 20) c.So(len(users), c.ShouldEqual, 0) c.So(err, c.ShouldBeNil) - // c.So(err.Error(), c.ShouldContainSubstring, "not found") + + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + repo := data.NewUserRepo(config.ReadConfig(env), gateway.Log) + patch := gomonkey.ApplyMethodReturn(repo, "List",nil, fmt.Errorf("error in your SQL syntax")) + defer patch.Reset() + _, err = userBiz.List(context.TODO(), []string{"unknown"}, []api.USER_STATUS{api.USER_STATUS_DELETED}, 1, 20) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "error in your SQL syntax") + patch.Reset() + + patch2 := gomonkey.ApplyMethodReturn(repo, "List", nil, fmt.Errorf("not found err")) + defer patch2.Reset() + _, err = userBiz.List(context.TODO(), []string{"unknown"}, []api.USER_STATUS{api.USER_STATUS_DELETED}, 1, 20) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "not found err") + patch2.Reset() }) } @@ -198,6 +246,17 @@ func testDeleteUser(t *testing.T) { err := userBiz.Delete(context.TODO(), snk.GenerateIDString()) c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, "not found") + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + repo := data.NewUserRepo(config.ReadConfig(env), gateway.Log) + patch := gomonkey.ApplyMethodReturn(repo, "Del", fmt.Errorf("error in your SQL syntax")) + defer patch.Reset() + err = userBiz.Delete(context.TODO(), snk.GenerateIDString()) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "error in your SQL syntax") + patch.Reset() }) } diff --git a/internal/data/data.go b/internal/data/data.go index 9a73bac..2a614cd 100644 --- a/internal/data/data.go +++ b/internal/data/data.go @@ -57,6 +57,7 @@ var ProviderSet = wire.NewSet(NewMySQL, NewCurdImpl, NewLayeredCache, + NewDataLock, NewAuthzRepoImpl, NewUserRepoImpl, NewEndpointRepoImpl, diff --git a/internal/data/data_test.go b/internal/data/data_test.go index 617f0f8..9c7a7e1 100644 --- a/internal/data/data_test.go +++ b/internal/data/data_test.go @@ -1,20 +1,12 @@ package data +import ( + "log" + "testing" +) + // func TestCreateInBatches(t *testing.T) { -// c.Convey("TestCreateInBatches", t, func() { -// env := "dev" -// if begonia.Env != "" { -// env = begonia.Env -// } -// conf := cfg.ReadConfig(env) -// repo := NewDataRepo(conf, gateway.Log) -// repo.db.AutoMigrate(&example.ExampleTable{}) -// snk, _ := tiga.NewSnowflake(1) -// models := []*example.ExampleTable{ -// { -// Uid: snk.GenerateIDString(), -// CreatedAt: tiga.Time(time.Now()), -// }, -// } -// }) -// } +func TestMain(m *testing.M) { + code := m.Run() + log.Printf("All tests passed with code %d", code) +} diff --git a/internal/data/endpoint_test.go b/internal/data/endpoint_test.go index b7e75a8..364638b 100644 --- a/internal/data/endpoint_test.go +++ b/internal/data/endpoint_test.go @@ -158,7 +158,7 @@ func testList(t *testing.T) { repo := NewEndpointRepo(conf, gateway.Log) snk, _ := tiga.NewSnowflake(1) enps := make([]string, 0) - c.Convey("test list", t, func() { + c.Convey("test endpoint list", t, func() { for i := 0; i < 10; i++ { epd := snk.GenerateIDString() enps = append(enps, epd) diff --git a/internal/data/operator_test.go b/internal/data/operator_test.go index 2cb779b..4bd20f8 100644 --- a/internal/data/operator_test.go +++ b/internal/data/operator_test.go @@ -234,32 +234,39 @@ func testWatcher(t *testing.T) { env = begonia.Env } operator := NewOperator(cfg.ReadConfig(env), gateway.Log) - updated := "" - deleted := "" - go func() { - err := operator.Watcher(context.Background(), "/test/user/info", func(ctx context.Context, op mvccpb.Event_EventType, key, value string) error { + updated := make(chan string,1) + deleted := make(chan string,1) + ctx,cancel:=context.WithCancel(context.Background()) + defer cancel() + defer close(updated) + defer close(deleted) + go func(ctx context.Context) { + err := operator.Watcher(ctx, "/test/watcher/user/info", func(ctx context.Context, op mvccpb.Event_EventType, key, value string) error { if op == mvccpb.PUT { - updated = key + updated<-key } else if op == mvccpb.DELETE { - deleted = key + deleted<-key } return nil }) if err != nil { t.Errorf("watcher error:%v", err) } - }() + }(ctx) snk, _ := tiga.NewSnowflake(1) uid := snk.GenerateIDString() - err := operator.(*dataOperatorRepo).data.etcd.Put(context.Background(), fmt.Sprintf("/test/user/info/%s", uid), fmt.Sprintf("user-%s", time.Now().Format("20060102150405"))) + err := operator.(*dataOperatorRepo).data.etcd.Put(context.Background(), fmt.Sprintf("/test/watcher/user/info/%s", uid), fmt.Sprintf("user-%s", time.Now().Format("20060102150405"))) c.So(err, c.ShouldBeNil) - time.Sleep(2 * time.Second) + up:=<-updated + c.So(up, c.ShouldEqual, fmt.Sprintf("/test/watcher/user/info/%s", uid)) - err = operator.(*dataOperatorRepo).data.etcd.Delete(context.Background(), fmt.Sprintf("/test/user/info/%s", uid)) + err = operator.(*dataOperatorRepo).data.etcd.Delete(context.Background(), fmt.Sprintf("/test/watcher/user/info/%s", uid)) c.So(err, c.ShouldBeNil) - time.Sleep(3 * time.Second) - c.So(updated, c.ShouldEqual, fmt.Sprintf("/test/user/info/%s", uid)) - c.So(deleted, c.ShouldEqual, fmt.Sprintf("/test/user/info/%s", uid)) + d:=<-deleted + c.So(d, c.ShouldEqual, fmt.Sprintf("/test/watcher/user/info/%s", uid)) + + cancel() + }) } diff --git a/internal/data/user_test.go b/internal/data/user_test.go index 60799af..e02c027 100644 --- a/internal/data/user_test.go +++ b/internal/data/user_test.go @@ -23,8 +23,8 @@ import ( var uid = "" var uid2 = "" var uid3 = "" -var user1 = fmt.Sprintf("user1-%s", time.Now().Format("20060102150405")) -var user2 = fmt.Sprintf("user2-%s", time.Now().Format("20060102150405")) +var user1 = fmt.Sprintf("user1-data-%s", time.Now().Format("20060102150405")) +var user2 = fmt.Sprintf("user2-data-%s", time.Now().Format("20060102150405")) // var user3 = fmt.Sprintf("user3-%s", time.Now().Format("20060102150405")) func testAddUser(t *testing.T) { @@ -35,7 +35,7 @@ func testAddUser(t *testing.T) { env = begonia.Env } repo := NewUserRepo(cfg.ReadConfig(env), gateway.Log) - snk, _ := tiga.NewSnowflake(1) + snk, _ := tiga.NewSnowflake(2) uid = snk.GenerateIDString() err := repo.Add(context.TODO(), &api.Users{ Uid: uid, @@ -68,6 +68,7 @@ func testAddUser(t *testing.T) { val, err := repo.(*userRepoImpl).local.Get(context.Background(), fmt.Sprintf("test:user:cache:%s", uid)) c.So(err, c.ShouldBeNil) c.So(val, c.ShouldNotBeNil) + time.Sleep(1 * time.Second) uid2 = snk.GenerateIDString() err = repo.Add(context.TODO(), &api.Users{ @@ -197,7 +198,6 @@ func testGetUser(t *testing.T) { func testUpdateUser(t *testing.T) { c.Convey("test user update success", t, func() { - t.Log("update test") env := "dev" if begonia.Env != "" { env = begonia.Env @@ -212,7 +212,8 @@ func testUpdateUser(t *testing.T) { createdAt := user.CreatedAt user.Name = fmt.Sprintf("user-update-%s", time.Now().Format("20060102150405")) time.Sleep(1 * time.Second) - user.Phone = time.Now().Format("20060102150405") + snk,_:=tiga.NewSnowflake(1) + user.Phone = snk.GenerateIDString() user.UpdateMask = &fieldmaskpb.FieldMask{Paths: []string{"name", "phone"}} err = repo.Patch(context.TODO(), user) diff --git a/internal/data/wire.go b/internal/data/wire.go index 4349c36..a26075a 100644 --- a/internal/data/wire.go +++ b/internal/data/wire.go @@ -4,6 +4,8 @@ package data import ( + "time" + "github.com/begonia-org/begonia/internal/biz" "github.com/begonia-org/begonia/internal/biz/endpoint" "github.com/begonia-org/begonia/internal/pkg/config" @@ -37,3 +39,6 @@ func NewOperator(cfg *tiga.Configuration, log logger.Logger) biz.DataOperatorRep func NewDataRepo(cfg *tiga.Configuration, log logger.Logger) *Data { panic(wire.Build(ProviderSet)) } +func NewLocker(cfg *tiga.Configuration, log logger.Logger,key string, ttl time.Duration,retry int) biz.DataLock { + panic(wire.Build(ProviderSet)) +} diff --git a/internal/data/wire_gen.go b/internal/data/wire_gen.go index 26add22..29f60d1 100644 --- a/internal/data/wire_gen.go +++ b/internal/data/wire_gen.go @@ -12,6 +12,7 @@ import ( "github.com/begonia-org/begonia/internal/pkg/config" "github.com/begonia-org/go-sdk/logger" "github.com/spark-lence/tiga" + "time" ) // Injectors from wire.go: @@ -85,3 +86,10 @@ func NewDataRepo(cfg *tiga.Configuration, log logger.Logger) *Data { data := NewData(mySQLDao, redisDao, etcdDao) return data } + +func NewLocker(cfg *tiga.Configuration, log logger.Logger, key string, ttl time.Duration, retry int) biz.DataLock { + redisDao := NewRDB(cfg) + client := GetRDBClient(redisDao) + bizDataLock := NewDataLock(client, key, ttl, retry) + return bizDataLock +} diff --git a/internal/data/wire_test.go b/internal/data/wire_test.go new file mode 100644 index 0000000..b401ed2 --- /dev/null +++ b/internal/data/wire_test.go @@ -0,0 +1,34 @@ +package data + +import ( + "testing" + + "github.com/begonia-org/begonia" + cfg "github.com/begonia-org/begonia/config" + "github.com/begonia-org/begonia/gateway" + c "github.com/smartystreets/goconvey/convey" +) + +func TestNewDataRepo(t *testing.T) { + c.Convey("test new data repo", t, func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + conf := cfg.ReadConfig(env) + v := NewDataRepo(conf, gateway.Log) + c.So(v, c.ShouldNotBeNil) + }) +} + +func TestNewLocker(t *testing.T) { + c.Convey("test new locker", t, func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + conf := cfg.ReadConfig(env) + v := NewLocker(conf, gateway.Log, "test-test-test", 3, 0) + c.So(v, c.ShouldNotBeNil) + }) +} diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 68b9446..48e92c0 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -186,6 +186,10 @@ func (c *Config) GetRPCPlugins() ([]*goloadbalancer.Server, error) { return plugins, nil } func (c *Config) GetEndpointsPrefix() string { + key:=fmt.Sprintf("%s.etcd.endpoint.prefix",c.GetEnv()) + if val:=c.GetString(key);val!=""{ + return val + } return c.GetString("common.etcd.endpoint.prefix") } @@ -218,6 +222,10 @@ func (c *Config) GetServiceNameKey(name string) string { return filepath.Join(prefix, name) } func (c *Config) GetAppKeyPrefix() string { + key:=fmt.Sprintf("%s.etcd.app.prefix",c.GetEnv()) + if val:=c.GetString(key);val!=""{ + return val + } prefix := c.GetString("common.etcd.app.prefix") return prefix } diff --git a/internal/service/app.go b/internal/service/app.go index 7609525..fc81cb0 100644 --- a/internal/service/app.go +++ b/internal/service/app.go @@ -17,7 +17,7 @@ type AppService struct { config *config.Config } -func (app *AppService) Put(ctx context.Context, in *api.AppsRequest) (*api.AddAppResponse, error) { +func (app *AppService) Post(ctx context.Context, in *api.AppsRequest) (*api.AddAppResponse, error) { owner := GetIdentity(ctx) appInstance, err := app.biz.CreateApp(ctx, in, owner) @@ -27,10 +27,11 @@ func (app *AppService) Put(ctx context.Context, in *api.AppsRequest) (*api.AddAp } return &api.AddAppResponse{Appid: appInstance.Appid, AccessKey: appInstance.AccessKey, Secret: appInstance.Secret}, nil } + func (app *AppService) Get(ctx context.Context, in *api.GetAPPRequest) (*api.Apps, error) { apps, err := app.biz.Get(ctx, in.Appid) if err != nil { - app.log.Errorf(ctx,"GetApps failed: %v", err) + app.log.Errorf(ctx, "GetApps failed: %v", err) return nil, err } return apps, nil @@ -40,10 +41,11 @@ func (app *AppService) Desc() *grpc.ServiceDesc { return &api.AppsService_ServiceDesc } -func NewAppService(biz *biz.AppUsecase, log logger.Logger, config *config.Config) *AppService { +func NewAppService(biz *biz.AppUsecase, log logger.Logger, config *config.Config) api.AppsServiceServer { return &AppService{biz: biz, log: log, config: config} } -func (app *AppService) Patch(ctx context.Context, in *api.AppsRequest) (*api.Apps, error) { + +func (app *AppService) Update(ctx context.Context, in *api.AppsRequest) (*api.Apps, error) { owner := GetIdentity(ctx) appInstance, err := app.biz.Patch(ctx, in, owner) if err != nil { @@ -52,6 +54,7 @@ func (app *AppService) Patch(ctx context.Context, in *api.AppsRequest) (*api.App } return appInstance, nil } + func (app *AppService) Delete(ctx context.Context, in *api.DeleteAppRequest) (*api.DeleteAppResponse, error) { err := app.biz.Del(ctx, in.Appid) if err != nil { @@ -59,3 +62,12 @@ func (app *AppService) Delete(ctx context.Context, in *api.DeleteAppRequest) (*a } return &api.DeleteAppResponse{}, nil } + +func (app *AppService) List(ctx context.Context, in *api.AppsListRequest) (*api.AppsListResponse, error) { + apps, err := app.biz.List(ctx, in) + if err != nil { + return nil, err + } + return &api.AppsListResponse{Apps: apps}, nil + // return nil, nil +} diff --git a/internal/service/app_test.go b/internal/service/app_test.go index 1e6e21b..60a5934 100644 --- a/internal/service/app_test.go +++ b/internal/service/app_test.go @@ -6,6 +6,12 @@ import ( "testing" "time" + "github.com/agiledragon/gomonkey/v2" + "github.com/begonia-org/begonia" + "github.com/begonia-org/begonia/config" + "github.com/begonia-org/begonia/gateway" + "github.com/begonia-org/begonia/internal/biz" + "github.com/begonia-org/begonia/internal/service" api "github.com/begonia-org/go-sdk/api/app/v1" "github.com/begonia-org/go-sdk/client" common "github.com/begonia-org/go-sdk/common/api/v1" @@ -13,6 +19,7 @@ import ( ) var appid = "" +var name2 = "" func addApp(t *testing.T) { c.Convey( @@ -20,12 +27,27 @@ func addApp(t *testing.T) { t, func() { apiClient := client.NewAppAPI(apiAddr, accessKey, secret) - rsp, err := apiClient.PostAppConfig(context.Background(), &api.AppsRequest{Name: fmt.Sprintf("app-%s", time.Now().Format("20060102150405")), Description: "test"}) + name := fmt.Sprintf("app-%s", time.Now().Format("20060102150405")) + rsp, err := apiClient.PostAppConfig(context.Background(), &api.AppsRequest{Name: name, Description: "test", Tags: []string{"test"}}) c.So(err, c.ShouldBeNil) c.So(rsp.StatusCode, c.ShouldEqual, common.Code_OK) c.So(rsp.Appid, c.ShouldNotBeEmpty) appid = rsp.Appid + rsp2, err := apiClient.GetAPP(context.Background(), appid) + c.So(err, c.ShouldBeNil) + c.So(rsp2.StatusCode, c.ShouldEqual, common.Code_OK) + c.So(rsp2.Name, c.ShouldNotBeEmpty) + _, err = apiClient.PostAppConfig(context.Background(), &api.AppsRequest{Name: name, Description: "test"}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldEqual, "duplicate app name") + // c.So(rsp3.StatusCode, c.ShouldEqual, common.Code_ERR) + + name2 = fmt.Sprintf("app-service-2-%s", time.Now().Format("20060102150405")) + rsp, err = apiClient.PostAppConfig(context.Background(), &api.AppsRequest{Name: name2, Description: "test"}) + c.So(err, c.ShouldBeNil) + c.So(rsp.StatusCode, c.ShouldEqual, common.Code_OK) + }, ) } @@ -43,6 +65,29 @@ func getApp(t *testing.T) { }, ) } +func testPatchApp(t *testing.T) { + c.Convey( + "test patch app", + t, + func() { + apiClient := client.NewAppAPI(apiAddr, accessKey, secret) + name := fmt.Sprintf("app-%s", time.Now().Format("20060102150405")) + rsp2, err := apiClient.UpdateAPP(context.Background(), appid, name, "test patch", nil) + c.So(err, c.ShouldBeNil) + c.So(rsp2.StatusCode, c.ShouldEqual, common.Code_OK) + rsp2, err = apiClient.GetAPP(context.Background(), appid) + c.So(err, c.ShouldBeNil) + c.So(rsp2.StatusCode, c.ShouldEqual, common.Code_OK) + c.So(rsp2.Name, c.ShouldEqual, name) + + _, err = apiClient.UpdateAPP(context.Background(), appid, name2, "test patch", nil) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldEqual, "duplicate app name") + + }, + ) + +} func delApp(t *testing.T) { c.Convey( "test del app", @@ -56,11 +101,55 @@ func delApp(t *testing.T) { _, err = apiClient.GetAPP(context.Background(), appid) c.So(err, c.ShouldNotBeNil) + + _, err = apiClient.DeleteAPP(context.TODO(), appid) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldEqual, "app not found") + // c.So(rsp3.StatusCode, c.ShouldEqual, common.Code_OK) }) } + +func listAPP(t *testing.T) { + c.Convey( + "test list app", + t, + func() { + apiClient := client.NewAppAPI(apiAddr, accessKey, secret) + rsp, err := apiClient.ListAPP(context.Background(), []string{"test", "test2"}, []api.APPStatus{api.APPStatus_APP_ENABLED}, 1, 10) + c.So(err, c.ShouldBeNil) + c.So(rsp.StatusCode, c.ShouldEqual, common.Code_OK) + c.So(rsp.Apps, c.ShouldNotBeEmpty) + c.So(rsp.Apps[0].Appid, c.ShouldNotBeEmpty) + }, + ) +} +func testListErr(t *testing.T) { + c.Convey( + "test list app", + t, + func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + cnf := config.ReadConfig(env) + srv := service.NewAPPSvrForTest(cnf, gateway.Log) + patch := gomonkey.ApplyFuncReturn((*biz.AppUsecase).List, nil, fmt.Errorf("test list app error")) + defer patch.Reset() + _, err := srv.List(context.Background(), nil) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldEqual, "test list app error") + patch.Reset() + }, + ) +} func TestApp(t *testing.T) { t.Run("add app", addApp) t.Run("get app", getApp) + t.Run("list app", listAPP) + t.Run("list app err", testListErr) + t.Run("patch app", testPatchApp) // appid = "442568851213783040" t.Run("del app", delApp) + } diff --git a/internal/service/authz.go b/internal/service/authz.go index 2cc4f51..a692b51 100644 --- a/internal/service/authz.go +++ b/internal/service/authz.go @@ -19,7 +19,7 @@ type AuthzService struct { authCrypto *crypto.UsersAuth } -func NewAuthzService(biz *biz.AuthzUsecase, log logger.Logger, auth *crypto.UsersAuth, config *config.Config) *AuthzService { +func NewAuthzService(biz *biz.AuthzUsecase, log logger.Logger, auth *crypto.UsersAuth, config *config.Config) api.AuthServiceServer { return &AuthzService{biz: biz, log: log, authCrypto: auth, config: config} } diff --git a/internal/service/authz_test.go b/internal/service/authz_test.go index e4cf5c7..cbcc778 100644 --- a/internal/service/authz_test.go +++ b/internal/service/authz_test.go @@ -13,7 +13,12 @@ import ( "runtime" "testing" + "github.com/begonia-org/begonia" + "github.com/begonia-org/begonia/config" + "github.com/begonia-org/begonia/gateway" + "github.com/begonia-org/begonia/internal/service" sys "github.com/begonia-org/go-sdk/api/sys/v1" + v1 "github.com/begonia-org/go-sdk/api/user/v1" "github.com/begonia-org/go-sdk/client" common "github.com/begonia-org/go-sdk/common/api/v1" c "github.com/smartystreets/goconvey/convey" @@ -112,10 +117,34 @@ func testLogout(t *testing.T) { c.So(err, c.ShouldBeNil) c.So(apiRsp.Code, c.ShouldNotEqual, int32(common.Code_OK)) + + _, err = apiClient.Logout(context.Background(), xtoken) + c.So(err, c.ShouldNotBeNil) + t.Logf("logout error: %v", err) + // c.So(rsp.StatusCode, c.shoun, common.Code_OK) }, ) } +func testAuthSeed(t *testing.T) { + c.Convey( + "test auth seed", + t, + func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + config := config.ReadConfig(env) + srv := service.NewAuthzSvrForTest(config, gateway.Log) + _, err := srv.AuthSeed(context.Background(), &v1.AuthLogAPIRequest{}) + c.So(err, c.ShouldNotBeNil) + + }, + ) +} + func TestAuth(t *testing.T) { t.Run("login", loginTest) t.Run("logout", testLogout) + t.Run("auth seed", testAuthSeed) } diff --git a/internal/service/endpoints.go b/internal/service/endpoints.go index fd1473b..3cfb34a 100644 --- a/internal/service/endpoints.go +++ b/internal/service/endpoints.go @@ -19,7 +19,7 @@ type EndpointsService struct { api.UnimplementedEndpointServiceServer } -func NewEndpointsService(biz *endpoint.EndpointUsecase, log logger.Logger, config *config.Config) *EndpointsService { +func NewEndpointsService(biz *endpoint.EndpointUsecase, log logger.Logger, config *config.Config) api.EndpointServiceServer { return &EndpointsService{biz: biz, log: log, config: config} } @@ -33,7 +33,7 @@ func (e *EndpointsService) Update(ctx context.Context, in *api.EndpointSrvUpdate tm, _ := time.Parse(time.RFC3339, timestamp) return &api.UpdateEndpointResponse{UpdatedAt: timestamppb.New(tm)}, nil } -func (e *EndpointsService) Put(ctx context.Context, in *api.EndpointSrvConfig) (*api.AddEndpointResponse, error) { +func (e *EndpointsService) Post(ctx context.Context, in *api.EndpointSrvConfig) (*api.AddEndpointResponse, error) { id, err := e.biz.AddConfig(ctx, in) if err != nil { return nil, err @@ -62,7 +62,7 @@ func (e *EndpointsService) Delete(ctx context.Context, in *api.DeleteEndpointReq return &api.DeleteEndpointResponse{}, nil } -func (e *EndpointsService) Details(ctx context.Context, in *api.DetailsEndpointRequest) (*api.DetailsEndpointResponse, error) { +func (e *EndpointsService) Get(ctx context.Context, in *api.DetailsEndpointRequest) (*api.DetailsEndpointResponse, error) { endpoint, err := e.biz.Get(ctx, in.UniqueKey) if err != nil { return nil, err diff --git a/internal/service/file.go b/internal/service/file.go index ee2fbd5..843d029 100644 --- a/internal/service/file.go +++ b/internal/service/file.go @@ -30,21 +30,16 @@ type FileService struct { config *config.Config } -func NewFileService(biz *file.FileUsecase, config *config.Config) *FileService { +func NewFileService(biz *file.FileUsecase, config *config.Config) api.FileServiceServer { return &FileService{biz: biz, config: config} } func (f *FileService) Upload(ctx context.Context, in *api.UploadFileRequest) (*api.UploadFileResponse, error) { - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - return nil, gosdk.NewError(fmt.Errorf("not found metadata"), int32(common.Code_PARAMS_ERROR), codes.InvalidArgument, "not_found_metadata") - } - identity := md.Get("x-identity") - if len(identity) == 0 { + identity := "" + if identity = GetIdentity(ctx); identity == "" { return nil, gosdk.NewError(errors.ErrIdentityMissing, int32(user.UserSvrCode_USER_IDENTITY_MISSING_ERR), codes.InvalidArgument, "not_found_identity") } - // in.Key = identity[0] + "/" + in.Key - return f.biz.Upload(ctx, in, identity[0]) + return f.biz.Upload(ctx, in, identity) } func (f *FileService) InitiateMultipartUpload(ctx context.Context, in *api.InitiateMultipartUploadRequest) (*api.InitiateMultipartUploadResponse, error) { @@ -54,34 +49,27 @@ func (f *FileService) UploadMultipartFile(ctx context.Context, in *api.UploadMul return f.biz.UploadMultipartFileFile(ctx, in) } func (f *FileService) CompleteMultipartUpload(ctx context.Context, in *api.CompleteMultipartUploadRequest) (*api.CompleteMultipartUploadResponse, error) { - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - return nil, gosdk.NewError(errors.ErrIdentityMissing, int32(user.UserSvrCode_USER_IDENTITY_MISSING_ERR), codes.InvalidArgument, "not_found_metadata") - } - identity := md.Get("x-identity") - if len(identity) == 0 { + identity := "" + if identity = GetIdentity(ctx); identity == "" { return nil, gosdk.NewError(errors.ErrIdentityMissing, int32(user.UserSvrCode_USER_IDENTITY_MISSING_ERR), codes.InvalidArgument, "not_found_identity") } - return f.biz.CompleteMultipartUploadFile(ctx, in, identity[0]) + return f.biz.CompleteMultipartUploadFile(ctx, in, identity) } func (f *FileService) AbortMultipartUpload(ctx context.Context, in *api.AbortMultipartUploadRequest) (*api.AbortMultipartUploadResponse, error) { return f.biz.AbortMultipartUpload(ctx, in) } func (f *FileService) Download(ctx context.Context, in *api.DownloadRequest) (*httpbody.HttpBody, error) { - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - return nil, gosdk.NewError(fmt.Errorf("not found metadata"), int32(common.Code_PARAMS_ERROR), codes.InvalidArgument, "not_found_metadata") - } - identity := md.Get("x-identity") - if len(identity) == 0 { + identity := "" + if identity = GetIdentity(ctx); identity == "" { return nil, gosdk.NewError(errors.ErrIdentityMissing, int32(user.UserSvrCode_USER_IDENTITY_MISSING_ERR), codes.InvalidArgument, "not_found_identity") } + newKey, err := url.PathUnescape(in.Key) if err != nil { return nil, gosdk.NewError(err, int32(common.Code_UNKNOWN), codes.InvalidArgument, "url_unescape") } in.Key = newKey - buf, err := f.biz.Download(ctx, in, identity[0]) + buf, err := f.biz.Download(ctx, in, identity) if err != nil { return nil, err } @@ -92,10 +80,7 @@ func (f *FileService) Download(ctx context.Context, in *api.DownloadRequest) (*h gosdk.GetMetadataKey("Content-Length"), fmt.Sprintf("%d", len(buf)), gosdk.GetMetadataKey("X-File-Sha256"), hex.EncodeToString(shaer.Sum(nil)), ) - err = grpc.SendHeader(ctx, rspMd) - if err != nil { - return nil, gosdk.NewError(err, int32(common.Code_UNKNOWN), codes.Internal, "send_header") - } + _ = grpc.SendHeader(ctx, rspMd) rsp := &httpbody.HttpBody{ ContentType: http.DetectContentType(buf), @@ -116,7 +101,7 @@ func parseRangeHeader(rangeHeader string) (start, end int64, err error) { start = 0 end, err = strconv.ParseInt(strings.TrimPrefix(rangeSpec, "-"), 10, 64) if err != nil { - return 0, 0, fmt.Errorf("invalid start value: %s", parts[0]) + return 0, 0, fmt.Errorf("invalid end value: %s", parts[0]) } return start, end, nil } @@ -124,7 +109,7 @@ func parseRangeHeader(rangeHeader string) (start, end int64, err error) { end = 0 start, err = strconv.ParseInt(strings.TrimSuffix(rangeSpec, "-"), 10, 64) if err != nil { - return 0, 0, fmt.Errorf("invalid end value: %s", parts[1]) + return 0, 0, fmt.Errorf("invalid start value: %s", parts[1]) } return start, end, nil @@ -149,12 +134,17 @@ func parseRangeHeader(rangeHeader string) (start, end int64, err error) { return start, end, nil } func (f *FileService) DownloadForRange(ctx context.Context, in *api.DownloadRequest) (*httpbody.HttpBody, error) { + identity := GetIdentity(ctx) + if identity == "" { + return nil, gosdk.NewError(errors.ErrIdentityMissing, int32(user.UserSvrCode_USER_IDENTITY_MISSING_ERR), codes.InvalidArgument, "not_found_identity") + + } md, ok := metadata.FromIncomingContext(ctx) var rangeStr string var start, end int64 var err error if ok { - if _, ok := md["range"]; !ok { + if v, ok := md["range"]; !ok || len(v) == 0 { return nil, gosdk.NewError(fmt.Errorf("range header not found"), int32(common.Code_PARAMS_ERROR), codes.InvalidArgument, "range_header_not_found") } rangeStr = md.Get("range")[0] @@ -163,11 +153,7 @@ func (f *FileService) DownloadForRange(ctx context.Context, in *api.DownloadRequ return nil, gosdk.NewError(err, int32(common.Code_UNKNOWN), codes.InvalidArgument, "parse_range_header") } } - identity := GetIdentity(ctx) - if identity == "" { - return nil, gosdk.NewError(errors.ErrIdentityMissing, int32(user.UserSvrCode_USER_IDENTITY_MISSING_ERR), codes.InvalidArgument, "not_found_identity") - } data, fileSize, err := f.biz.DownloadForRange(ctx, in, start, end, identity) if err != nil { return nil, err @@ -182,10 +168,8 @@ func (f *FileService) DownloadForRange(ctx context.Context, in *api.DownloadRequ gosdk.GetMetadataKey("Accept-Ranges"), "bytes", "X-Http-Code", fmt.Sprintf("%d", http.StatusPartialContent), ) - err = grpc.SendHeader(ctx, rspMd) - if err != nil { - return nil, gosdk.NewError(err, int32(common.Code_UNKNOWN), codes.Internal, "send_header") - } + _ = grpc.SendHeader(ctx, rspMd) + return &httpbody.HttpBody{ ContentType: "application/octet-stream", Data: data, @@ -222,13 +206,12 @@ func (f *FileService) Metadata(ctx context.Context, in *api.FileMetadataRequest) gosdk.GetMetadataKey("X-File-Version"), rsp.Version, gosdk.GetMetadataKey("Access-Control-Expose-Headers"), "Content-Length, Content-Range, Accept-Ranges, Last-Modified, ETag, Content-Type, X-File-name, X-File-Sha256", ) - // rspMd.Append(sdk.GetMetadataKey(), "Content-Length", "Content-Range", "Accept-Ranges", "Last-Modified", "ETag", "Content-Type", "x-file-name", "x-file-sha256") - err = grpc.SendHeader(ctx, rspMd) - if err != nil { + _ = grpc.SendHeader(ctx, rspMd) + // if err != nil { - return nil, gosdk.NewError(fmt.Errorf("非法的响应头,%w", err), int32(common.Code_UNKNOWN), codes.Internal, "send_header") + // return nil, gosdk.NewError(fmt.Errorf("非法的响应头,%w", err), int32(common.Code_UNKNOWN), codes.Internal, "send_header") - } + // } if md, ok := metadata.FromIncomingContext(ctx); ok { if httpMethod, ok := md["x-http-method"]; ok { if strings.EqualFold(httpMethod[0], "HEAD") { diff --git a/internal/service/file_test.go b/internal/service/file_test.go index 3371b70..d608e38 100644 --- a/internal/service/file_test.go +++ b/internal/service/file_test.go @@ -8,17 +8,25 @@ import ( "fmt" "io" "net/http" + "net/url" "os" "path/filepath" "runtime" "testing" + "github.com/agiledragon/gomonkey/v2" "github.com/begonia-org/begonia" "github.com/begonia-org/begonia/config" + "github.com/begonia-org/begonia/gateway" + "github.com/begonia-org/begonia/internal/biz/file" cfg "github.com/begonia-org/begonia/internal/pkg/config" + "github.com/begonia-org/begonia/internal/pkg/errors" + "github.com/begonia-org/begonia/internal/service" + api "github.com/begonia-org/go-sdk/api/file/v1" "github.com/begonia-org/go-sdk/client" common "github.com/begonia-org/go-sdk/common/api/v1" c "github.com/smartystreets/goconvey/convey" + "google.golang.org/grpc/metadata" ) func sumFileSha256(src string) (string, error) { @@ -121,7 +129,7 @@ func uploadParts(t *testing.T) { c.Convey("test upload file", t, func() { apiClient := client.NewFilesAPI(apiAddr, accessKey, secret) var err error - tmpFile, err = generateRandomFile(1024 * 1024 * 20) + tmpFile, err = generateRandomFile(1024 * 1024 * 2) c.So(err, c.ShouldBeNil) defer os.Remove(tmpFile.path) rsp, err := apiClient.UploadFileWithMuiltParts(context.Background(), tmpFile.path, "test/tmp.bin", true) @@ -221,10 +229,195 @@ func deleteFile(t *testing.T) { }) } +func testRangeDownload(t *testing.T) { + c.Convey("test range download file", t, func() { + apiClient := client.NewFilesAPI(apiAddr, accessKey, secret) + tmp, err := os.CreateTemp("", "testfile-*.txt") + c.So(err, c.ShouldBeNil) + defer tmp.Close() + defer os.Remove(tmp.Name()) + rsp, err := apiClient.RangeDownload(context.Background(), sdkAPPID+"/test/tmp.bin", "", -1, 128) + c.So(err, c.ShouldBeNil) + c.So(len(rsp), c.ShouldEqual, 129) + + rsp, err = apiClient.RangeDownload(context.Background(), sdkAPPID+"/test/tmp.bin", "", 128, -1) + c.So(err, c.ShouldBeNil) + c.So(len(rsp), c.ShouldEqual, 1024*1024*2-128) + + }) +} +func testUploadErr(t *testing.T) { + c.Convey("test upload file err", t, func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + cnf := config.ReadConfig(env) + srv := service.NewFileSvrForTest(cnf, gateway.Log) + _, err := srv.Upload(context.Background(), &api.UploadFileRequest{}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrIdentityMissing.Error()) + + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("app_id", sdkAPPID)) + _, err = srv.Upload(ctx, &api.UploadFileRequest{}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrIdentityMissing.Error()) + + }) +} +func testDownloadErr(t *testing.T) { + c.Convey("test download file err", t, func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + cnf := config.ReadConfig(env) + srv := service.NewFileSvrForTest(cnf, gateway.Log) + _, err := srv.Download(context.Background(), &api.DownloadRequest{}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrIdentityMissing.Error()) + + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("app_id", sdkAPPID)) + _, err = srv.Download(ctx, &api.DownloadRequest{}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrIdentityMissing.Error()) + + patch := gomonkey.ApplyFuncReturn(url.PathUnescape, "", fmt.Errorf("test PathUnescape error")) + defer patch.Reset() + ctx = metadata.NewIncomingContext(context.Background(), metadata.Pairs("x-identity", sdkAPPID)) + _, err = srv.Download(ctx, &api.DownloadRequest{Key: "test"}) + patch.Reset() + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "test PathUnescape error") + + // patch2 := gomonkey.ApplyFuncReturn(grpc.SendHeader, fmt.Errorf("test SendHeader error")) + // defer patch2.Reset() + // ctx = metadata.NewIncomingContext(context.Background(), metadata.Pairs("x-identity", sdkAPPID)) + // _, err = srv.Download(ctx, &api.DownloadRequest{Key: sdkAPPID + "/test/helloworld.pb"}) + // patch2.Reset() + // c.So(err, c.ShouldNotBeNil) + // c.So(err.Error(), c.ShouldContainSubstring, "test SendHeader error") + + }) +} +func testRangeDownloadErr(t *testing.T) { + c.Convey("test range download file err", t, func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + cnf := config.ReadConfig(env) + srv := service.NewFileSvrForTest(cnf, gateway.Log) + // ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("app_id", sdkAPPID)) + // _, err := srv.DownloadForRange(ctx, &api.DownloadRequest{}) + // c.So(err, c.ShouldNotBeNil) + // c.So(err.Error(), c.ShouldContainSubstring, errors.ErrIdentityMissing.Error()) + + cases := []struct { + rangeStr string + err error + }{ + { + rangeStr: "", + err: fmt.Errorf("range header not found"), + }, + { + rangeStr: "0-0", + err: fmt.Errorf("invalid range header"), + }, + { + rangeStr: "bytes=-ffee", + err: fmt.Errorf("invalid end value"), + }, + { + rangeStr: "bytes=ffee-", + err: fmt.Errorf("invalid start value"), + }, + { + rangeStr: "bytes=1024", + err: fmt.Errorf("invalid range specification"), + }, + { + rangeStr: "bytes=tgg-1024", + err: fmt.Errorf("invalid start value"), + }, + { + rangeStr: "bytes=1024-tgg", + err: fmt.Errorf("invalid end value"), + }, + } + for _, cs := range cases { + md := metadata.New(nil) + md.Set("x-identity", sdkAPPID) + if cs.rangeStr != "" { + md.Set("range", cs.rangeStr) + } + ctx := metadata.NewIncomingContext(context.Background(), md) + _, err := srv.DownloadForRange(ctx, &api.DownloadRequest{Key: sdkAPPID + "/test/helloworld.pb"}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, cs.err.Error()) + } + + patch := gomonkey.ApplyFuncReturn((*file.FileUsecase).DownloadForRange, nil, int64(0), fmt.Errorf("test download for range error")) + defer patch.Reset() + md := metadata.New(nil) + md.Set("x-identity", sdkAPPID) + md.Set("range", "bytes=0-0") + ctx := metadata.NewIncomingContext(context.Background(), md) + _, err := srv.DownloadForRange(ctx, &api.DownloadRequest{Key: sdkAPPID + "/test/helloworld.pb"}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "test download for range error") + patch.Reset() + + }) +} +func testDelErr(t *testing.T) { + c.Convey("test delete file err", t, func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + cnf := config.ReadConfig(env) + srv := service.NewFileSvrForTest(cnf, gateway.Log) + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("app_id", sdkAPPID)) + _, err := srv.Delete(ctx, &api.DeleteRequest{}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrIdentityMissing.Error()) + + }) +} +func testMetaErr(t *testing.T) { + c.Convey("test meta file err", t, func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + cnf := config.ReadConfig(env) + srv := service.NewFileSvrForTest(cnf, gateway.Log) + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs("app_id", sdkAPPID)) + _, err := srv.Metadata(ctx, &api.FileMetadataRequest{}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, errors.ErrIdentityMissing.Error()) + + patch:=gomonkey.ApplyFuncReturn((*file.FileUsecase).Metadata,nil,fmt.Errorf("test metadata error")) + defer patch.Reset() + ctx = metadata.NewIncomingContext(context.Background(), metadata.Pairs("x-identity", sdkAPPID)) + _, err = srv.Metadata(ctx, &api.FileMetadataRequest{Key: sdkAPPID + "/test/helloworld.pb"}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "test metadata error") + + }) +} func TestFile(t *testing.T) { t.Run("upload", upload) t.Run("download", download) + t.Run("testUploadErr", testUploadErr) + t.Run("testDownloadErr", testDownloadErr) t.Run("uploadParts", uploadParts) + t.Run("testRangeDownload", testRangeDownload) + t.Run("testRangeDownloadErr", testRangeDownloadErr) t.Run("downloadParts", downloadParts) t.Run("deleteFile", deleteFile) + t.Run("testDelErr", testDelErr) + t.Run("testMetaErr", testMetaErr) } diff --git a/internal/service/gateway_test.go b/internal/service/gateway_test.go index b5ee326..b47997f 100644 --- a/internal/service/gateway_test.go +++ b/internal/service/gateway_test.go @@ -2,6 +2,7 @@ package service_test import ( "context" + "fmt" "net/http" "os" "path/filepath" @@ -9,6 +10,12 @@ import ( "testing" "time" + "github.com/agiledragon/gomonkey/v2" + "github.com/begonia-org/begonia" + "github.com/begonia-org/begonia/config" + "github.com/begonia-org/begonia/gateway" + "github.com/begonia-org/begonia/internal/biz/endpoint" + "github.com/begonia-org/begonia/internal/service" goloadbalancer "github.com/begonia-org/go-loadbalancer" api "github.com/begonia-org/go-sdk/api/endpoint/v1" "github.com/begonia-org/go-sdk/client" @@ -52,7 +59,7 @@ func postEndpoint(t *testing.T) { c.So(resp.StatusCode, c.ShouldEqual, common.Code_OK) c.So(resp.Id, c.ShouldNotBeEmpty) shareEndpoint = resp.Id - time.Sleep(3 * time.Second) + time.Sleep(5 * time.Second) req, err := http.NewRequest("GET", "http://127.0.0.1:12140/api/v1/example/helloworld", nil) c.So(err, c.ShouldBeNil) @@ -103,7 +110,15 @@ func getEndpoint(t *testing.T) { // c.So(rsp.Details.Endpoints.Name, c.ShouldEqual, "test") }) } - +func listEndpoint(t *testing.T) { + apiClient := client.NewEndpointAPI(apiAddr, accessKey, secret) + c.Convey("test list endpoint api", t, func() { + rsp, err := apiClient.List(context.Background(), []string{"test", "test2"}, nil) + c.So(err, c.ShouldBeNil) + c.So(rsp.StatusCode, c.ShouldEqual, common.Code_OK) + c.So(len(rsp.Endpoints), c.ShouldBeGreaterThan, 0) + }) +} func delEndpoint(t *testing.T) { apiClient := client.NewEndpointAPI(apiAddr, accessKey, secret) @@ -121,10 +136,43 @@ func delEndpoint(t *testing.T) { }) } +func testEndpointSvrErr(t *testing.T) { + c.Convey("test endpoint server error", t, func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + cnf := config.ReadConfig(env) + srv := service.NewEndpointSvrForTest(cnf, gateway.Log) + // _,err:=srv.PostEndpointConfig(context.Background(),nil) + patch := gomonkey.ApplyFuncReturn((*endpoint.EndpointUsecase).AddConfig, nil, fmt.Errorf("test add endpoint error")) + defer patch.Reset() + _, err := srv.Post(context.Background(), nil) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldEqual, "test add endpoint error") + patch.Reset() + + _, err = srv.Update(context.Background(), &api.EndpointSrvUpdateRequest{}) + c.So(err, c.ShouldNotBeNil) + + _, err = srv.Get(context.Background(), &api.DetailsEndpointRequest{}) + c.So(err, c.ShouldNotBeNil) + patch = patch.ApplyFuncReturn((*endpoint.EndpointUsecase).Delete, fmt.Errorf("test DEL endpoint error")) + _, err = srv.Delete(context.Background(), &api.DeleteEndpointRequest{}) + c.So(err, c.ShouldNotBeNil) + patch.Reset() + patch = patch.ApplyFuncReturn((*endpoint.EndpointUsecase).List, nil, fmt.Errorf("test list endpoint error")) + _, err = srv.List(context.Background(), &api.ListEndpointRequest{}) + c.So(err, c.ShouldNotBeNil) + patch.Reset() + }) +} func TestEndpoint(t *testing.T) { t.Run("post", postEndpoint) t.Run("patch", patchEndpoint) t.Run("get", getEndpoint) + t.Run("list", listEndpoint) + t.Run("testErr", testEndpointSvrErr) t.Run("del", delEndpoint) } diff --git a/internal/service/service.go b/internal/service/service.go index 5ba5416..42223d7 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -3,8 +3,11 @@ package service import ( "context" - api "github.com/begonia-org/go-sdk/api/file/v1" - userAPI "github.com/begonia-org/go-sdk/api/user/v1" + app "github.com/begonia-org/go-sdk/api/app/v1" + ep "github.com/begonia-org/go-sdk/api/endpoint/v1" + file "github.com/begonia-org/go-sdk/api/file/v1" + sys "github.com/begonia-org/go-sdk/api/sys/v1" + user "github.com/begonia-org/go-sdk/api/user/v1" "github.com/google/wire" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "google.golang.org/grpc" @@ -15,40 +18,27 @@ type Service interface { Desc() *grpc.ServiceDesc } -var ProviderSet = wire.NewSet(NewAuthzService,NewUserService, - NewFileService, - NewServices, - NewEndpointsService, - NewAppService, +var ProviderSet = wire.NewSet(NewAuthzService, NewUserService, + NewFileService, + NewServices, + NewEndpointsService, + NewAppService, NewSysService) -var ServiceOptionsSet = wire.NewSet(WithFileService, WithAuthzService) type ServiceOptions func(*grpc.Server, *runtime.ServeMux, string) error -func NewServices(file *FileService, - authz *AuthzService, - ep *EndpointsService, - app *AppService, - sys *SysService, - user *UserService, +func NewServices(file file.FileServiceServer, + authz user.AuthServiceServer, + ep ep.EndpointServiceServer, + app app.AppsServiceServer, + sys sys.SystemServiceServer, + users user.UserServiceServer, ) []Service { services := make([]Service, 0) - services = append(services, file, authz, ep, app, sys,user) + services = append(services, file.(Service), authz.(Service), ep.(Service), app.(Service), sys.(Service), users.(Service)) return services } -func WithFileService(file *FileService, opts []grpc.DialOption) ServiceOptions { - return func(server *grpc.Server, mux *runtime.ServeMux, endpoint string) error { - api.RegisterFileServiceServer(server, file) - return api.RegisterFileServiceHandlerFromEndpoint(context.Background(), mux, endpoint, opts) - } -} -func WithAuthzService(authz *AuthzService, opts []grpc.DialOption) ServiceOptions { - return func(server *grpc.Server, mux *runtime.ServeMux, endpoint string) error { - userAPI.RegisterAuthServiceServer(server, authz) - return userAPI.RegisterAuthServiceHandlerFromEndpoint(context.Background(), mux, endpoint, opts) - } -} func GetIdentity(ctx context.Context) string { md, ok := metadata.FromIncomingContext(ctx) diff --git a/internal/service/sys.go b/internal/service/sys.go index bf78d44..db4b4da 100644 --- a/internal/service/sys.go +++ b/internal/service/sys.go @@ -16,7 +16,7 @@ func (s *SysService) Desc() *grpc.ServiceDesc { return &api.SystemService_ServiceDesc } -func NewSysService() *SysService { +func NewSysService() api.SystemServiceServer { return &SysService{} } diff --git a/internal/service/user.go b/internal/service/user.go index 877202c..9b8ccc7 100644 --- a/internal/service/user.go +++ b/internal/service/user.go @@ -17,7 +17,7 @@ type UserService struct { config *config.Config } -func NewUserService(biz *biz.UserUsecase, log logger.Logger, config *config.Config) *UserService { +func NewUserService(biz *biz.UserUsecase, log logger.Logger, config *config.Config) api.UserServiceServer { return &UserService{biz: biz, log: log, config: config} } diff --git a/internal/service/user_test.go b/internal/service/user_test.go index 42a474a..5a1e59c 100644 --- a/internal/service/user_test.go +++ b/internal/service/user_test.go @@ -6,6 +6,12 @@ import ( "testing" "time" + "github.com/agiledragon/gomonkey/v2" + "github.com/begonia-org/begonia" + "github.com/begonia-org/begonia/config" + "github.com/begonia-org/begonia/gateway" + "github.com/begonia-org/begonia/internal/biz" + "github.com/begonia-org/begonia/internal/service" api "github.com/begonia-org/go-sdk/api/user/v1" "github.com/begonia-org/go-sdk/client" common "github.com/begonia-org/go-sdk/common/api/v1" @@ -20,7 +26,7 @@ func addUser(t *testing.T) { t, func() { apiClient := client.NewUsersAPI(apiAddr, accessKey, secret) - name := fmt.Sprintf("user-%s", time.Now().Format("20060102150405")) + name := fmt.Sprintf("user-service-test-%s", time.Now().Format("20060102150405")) rsp, err := apiClient.PostUser(context.Background(), &api.PostUserRequest{ Name: name, Password: "123456", @@ -71,17 +77,71 @@ func patchUser(t *testing.T) { t, func() { apiClient := client.NewUsersAPI(apiAddr, accessKey, secret) - rsp, err := apiClient.PatchUser(context.Background(), uid, map[string]interface{}{ + rsp, err := apiClient.UpdateUser(context.Background(), uid, map[string]interface{}{ "password": "123456ecfasddccddd", "email": fmt.Sprintf("%s@example.com", time.Now().Format("20060102150405"))}) c.So(err, c.ShouldBeNil) c.So(rsp.StatusCode, c.ShouldEqual, common.Code_OK) }) } +func testRegisterErr(t *testing.T) { + c.Convey( + "test register user error", + t, + func() { + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + cnf := config.ReadConfig(env) + srv := service.NewUserSvrForTest(cnf, gateway.Log) + patch := gomonkey.ApplyFuncReturn((*biz.UserUsecase).Add, fmt.Errorf("test add user error")) + defer patch.Reset() + _, err := srv.Register(context.Background(), &api.PostUserRequest{}) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "test add user error") + + }) +} +func testUpdateErr(t *testing.T){ + c.Convey("test update user error",t,func(){ + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + cnf := config.ReadConfig(env) + srv := service.NewUserSvrForTest(cnf, gateway.Log) + patch := gomonkey.ApplyFuncReturn((*biz.UserUsecase).Update, fmt.Errorf("test update user error")) + defer patch.Reset() + _,err:=srv.Update(context.Background(),&api.PatchUserRequest{Uid: "",Owner: "test-user-01"}) + c.So(err,c.ShouldNotBeNil) + c.So(err.Error(),c.ShouldContainSubstring,"test update user error") + patch.Reset() + }) +} +func testDelUserErr(t *testing.T){ + c.Convey("test delete user error",t,func(){ + env := "dev" + if begonia.Env != "" { + env = begonia.Env + } + cnf := config.ReadConfig(env) + srv := service.NewUserSvrForTest(cnf, gateway.Log) + patch := gomonkey.ApplyFuncReturn((*biz.UserUsecase).Delete, fmt.Errorf("test delete user error")) + defer patch.Reset() + _,err:=srv.Delete(context.Background(),&api.DeleteUserRequest{Uid: ""}) + c.So(err,c.ShouldNotBeNil) + c.So(err.Error(),c.ShouldContainSubstring,"test delete user error") + patch.Reset() + }) +} func TestUser(t *testing.T) { t.Run("add user", addUser) t.Run("get user", getUser) // uid = "442210231930327040" t.Run("patch user", patchUser) t.Run("delete user", deleteUser) + t.Run("test register user error", testRegisterErr) + t.Run("test update user error",testUpdateErr) + t.Run("test delete user error",testDelUserErr) } diff --git a/internal/service/wire.go b/internal/service/wire.go new file mode 100644 index 0000000..35371ca --- /dev/null +++ b/internal/service/wire.go @@ -0,0 +1,42 @@ +//go:build wireinject +// +build wireinject + +package service + +import ( + "github.com/begonia-org/begonia/internal/biz" + "github.com/begonia-org/begonia/internal/data" + "github.com/begonia-org/begonia/internal/pkg" + + "github.com/begonia-org/go-sdk/logger" + app "github.com/begonia-org/go-sdk/api/app/v1" + ep "github.com/begonia-org/go-sdk/api/endpoint/v1" + file "github.com/begonia-org/go-sdk/api/file/v1" + sys "github.com/begonia-org/go-sdk/api/sys/v1" + user "github.com/begonia-org/go-sdk/api/user/v1" + + "github.com/google/wire" + + "github.com/spark-lence/tiga" +) + + + +func NewAuthzSvrForTest(config *tiga.Configuration, log logger.Logger)user.AuthServiceServer { + panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, data.ProviderSet, NewAuthzService)) +} +func NewAPPSvrForTest(config *tiga.Configuration, log logger.Logger)app.AppsServiceServer { + panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, data.ProviderSet, NewAppService)) +} +func NewEndpointSvrForTest(config *tiga.Configuration, log logger.Logger)ep.EndpointServiceServer { + panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, data.ProviderSet, NewEndpointsService)) +} +func NewFileSvrForTest(config *tiga.Configuration, log logger.Logger)file.FileServiceServer { + panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, NewFileService)) +} +func NewSysSvrForTest(config *tiga.Configuration, log logger.Logger)sys.SystemServiceServer { + panic(wire.Build(NewSysService)) +} +func NewUserSvrForTest(config *tiga.Configuration, log logger.Logger)user.UserServiceServer { + panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, data.ProviderSet, NewUserService)) +} \ No newline at end of file diff --git a/internal/service/wire_gen.go b/internal/service/wire_gen.go new file mode 100644 index 0000000..4683957 --- /dev/null +++ b/internal/service/wire_gen.go @@ -0,0 +1,92 @@ +// Code generated by Wire. DO NOT EDIT. + +//go:generate go run github.com/google/wire/cmd/wire +//go:build !wireinject +// +build !wireinject + +package service + +import ( + "github.com/begonia-org/begonia/internal/biz" + "github.com/begonia-org/begonia/internal/biz/endpoint" + "github.com/begonia-org/begonia/internal/biz/file" + "github.com/begonia-org/begonia/internal/data" + "github.com/begonia-org/begonia/internal/pkg/config" + "github.com/begonia-org/begonia/internal/pkg/crypto" + v1_2 "github.com/begonia-org/go-sdk/api/app/v1" + v1_3 "github.com/begonia-org/go-sdk/api/endpoint/v1" + v1_4 "github.com/begonia-org/go-sdk/api/file/v1" + v1_5 "github.com/begonia-org/go-sdk/api/sys/v1" + "github.com/begonia-org/go-sdk/api/user/v1" + "github.com/begonia-org/go-sdk/logger" + "github.com/spark-lence/tiga" +) + +// Injectors from wire.go: + +func NewAuthzSvrForTest(config2 *tiga.Configuration, log logger.Logger) v1.AuthServiceServer { + redisDao := data.NewRDB(config2) + configConfig := config.NewConfig(config2) + layeredCache := data.NewLayeredCache(redisDao, configConfig, log) + authzRepo := data.NewAuthzRepoImpl(log, layeredCache) + mySQLDao := data.NewMySQL(config2) + etcdDao := data.NewEtcd(config2) + dataData := data.NewData(mySQLDao, redisDao, etcdDao) + curd := data.NewCurdImpl(mySQLDao, configConfig) + userRepo := data.NewUserRepoImpl(dataData, layeredCache, curd, configConfig) + usersAuth := crypto.NewUsersAuth() + authzUsecase := biz.NewAuthzUsecase(authzRepo, userRepo, log, usersAuth, configConfig) + authServiceServer := NewAuthzService(authzUsecase, log, usersAuth, configConfig) + return authServiceServer +} + +func NewAPPSvrForTest(config2 *tiga.Configuration, log logger.Logger) v1_2.AppsServiceServer { + mySQLDao := data.NewMySQL(config2) + configConfig := config.NewConfig(config2) + curd := data.NewCurdImpl(mySQLDao, configConfig) + redisDao := data.NewRDB(config2) + layeredCache := data.NewLayeredCache(redisDao, configConfig, log) + appRepo := data.NewAppRepoImpl(curd, layeredCache, configConfig) + appUsecase := biz.NewAppUsecase(appRepo, configConfig) + appsServiceServer := NewAppService(appUsecase, log, configConfig) + return appsServiceServer +} + +func NewEndpointSvrForTest(config2 *tiga.Configuration, log logger.Logger) v1_3.EndpointServiceServer { + mySQLDao := data.NewMySQL(config2) + redisDao := data.NewRDB(config2) + etcdDao := data.NewEtcd(config2) + dataData := data.NewData(mySQLDao, redisDao, etcdDao) + configConfig := config.NewConfig(config2) + endpointRepo := data.NewEndpointRepoImpl(dataData, configConfig) + fileUsecase := file.NewFileUsecase(configConfig) + endpointUsecase := endpoint.NewEndpointUsecase(endpointRepo, fileUsecase, configConfig) + endpointServiceServer := NewEndpointsService(endpointUsecase, log, configConfig) + return endpointServiceServer +} + +func NewFileSvrForTest(config2 *tiga.Configuration, log logger.Logger) v1_4.FileServiceServer { + configConfig := config.NewConfig(config2) + fileUsecase := file.NewFileUsecase(configConfig) + fileServiceServer := NewFileService(fileUsecase, configConfig) + return fileServiceServer +} + +func NewSysSvrForTest(config2 *tiga.Configuration, log logger.Logger) v1_5.SystemServiceServer { + systemServiceServer := NewSysService() + return systemServiceServer +} + +func NewUserSvrForTest(config2 *tiga.Configuration, log logger.Logger) v1.UserServiceServer { + mySQLDao := data.NewMySQL(config2) + redisDao := data.NewRDB(config2) + etcdDao := data.NewEtcd(config2) + dataData := data.NewData(mySQLDao, redisDao, etcdDao) + configConfig := config.NewConfig(config2) + layeredCache := data.NewLayeredCache(redisDao, configConfig, log) + curd := data.NewCurdImpl(mySQLDao, configConfig) + userRepo := data.NewUserRepoImpl(dataData, layeredCache, curd, configConfig) + userUsecase := biz.NewUserUsecase(userRepo, configConfig) + userServiceServer := NewUserService(userUsecase, log, configConfig) + return userServiceServer +} diff --git a/internal/wire.go b/internal/wire.go index cab37b7..ad381b8 100644 --- a/internal/wire.go +++ b/internal/wire.go @@ -11,6 +11,12 @@ import ( "github.com/begonia-org/begonia/internal/pkg/migrate" "github.com/begonia-org/begonia/internal/server" "github.com/begonia-org/begonia/internal/service" + "github.com/begonia-org/go-sdk/logger" + app "github.com/begonia-org/go-sdk/api/app/v1" + ep "github.com/begonia-org/go-sdk/api/endpoint/v1" + file "github.com/begonia-org/go-sdk/api/file/v1" + sys "github.com/begonia-org/go-sdk/api/sys/v1" + user "github.com/begonia-org/go-sdk/api/user/v1" "github.com/google/wire" @@ -23,8 +29,24 @@ func InitOperatorApp(config *tiga.Configuration) *migrate.InitOperator { } -func New(config *tiga.Configuration, log gateway.Logger, endpoint string) GatewayWorker { +func New(config *tiga.Configuration, log logger.Logger, endpoint string) GatewayWorker { panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, data.ProviderSet, service.ProviderSet, daemon.ProviderSet, server.ProviderSet, NewGatewayWorkerImpl)) } + +func NewAuthzSvr(config *tiga.Configuration, log logger.Logger)user.AuthServiceServer { + panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, data.ProviderSet, service.ProviderSet, daemon.ProviderSet, server.ProviderSet, service.NewAuthzService)) +} +func NewAPPSvr(config *tiga.Configuration, log logger.Logger)app.AppsServiceServer { + panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, data.ProviderSet, service.ProviderSet, daemon.ProviderSet, server.ProviderSet, service.NewAppService)) +} +func NewEndpointSvr(config *tiga.Configuration, log logger.Logger)ep.EndpointServiceServer { + panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, data.ProviderSet, service.ProviderSet, daemon.ProviderSet, server.ProviderSet, service.NewEndpointsService)) +} +func NewFileSvr(config *tiga.Configuration, log logger.Logger)file.FileServiceServer { + panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, data.ProviderSet, service.ProviderSet, daemon.ProviderSet, server.ProviderSet, service.NewFileService)) +} +func NewSysSvr(config *tiga.Configuration, log logger.Logger)sys.SystemServiceServer { + panic(wire.Build(biz.ProviderSet, pkg.ProviderSet, data.ProviderSet, service.ProviderSet, daemon.ProviderSet, server.ProviderSet, service.NewSysService)) +} \ No newline at end of file diff --git a/internal/wire_gen.go b/internal/wire_gen.go index 814bcf7..d882244 100644 --- a/internal/wire_gen.go +++ b/internal/wire_gen.go @@ -48,23 +48,23 @@ func New(config2 *tiga.Configuration, log logger.Logger, endpoint2 string) Gatew authzRepo := data.NewAuthzRepoImpl(log, layeredCache) dataOperatorRepo := data.NewDataOperatorRepo(dataData, appRepo, userRepo, authzRepo, layeredCache, log) endpointRepo := data.NewEndpointRepoImpl(dataData, configConfig) - gatewayWatcher := endpoint.NewWatcher(configConfig, endpointRepo) - dataOperatorUsecase := biz.NewDataOperatorUsecase(dataOperatorRepo, configConfig, log, gatewayWatcher, endpointRepo) + endpointWatcher := endpoint.NewWatcher(configConfig, endpointRepo) + dataOperatorUsecase := biz.NewDataOperatorUsecase(dataOperatorRepo, configConfig, log, endpointWatcher, endpointRepo) daemonDaemon := daemon.NewDaemonImpl(configConfig, dataOperatorUsecase) gatewayConfig := server.NewGatewayConfig(endpoint2) fileUsecase := file.NewFileUsecase(configConfig) - fileService := service.NewFileService(fileUsecase, configConfig) + fileServiceServer := service.NewFileService(fileUsecase, configConfig) usersAuth := crypto.NewUsersAuth() authzUsecase := biz.NewAuthzUsecase(authzRepo, userRepo, log, usersAuth, configConfig) - authzService := service.NewAuthzService(authzUsecase, log, usersAuth, configConfig) + authServiceServer := service.NewAuthzService(authzUsecase, log, usersAuth, configConfig) endpointUsecase := endpoint.NewEndpointUsecase(endpointRepo, fileUsecase, configConfig) - endpointsService := service.NewEndpointsService(endpointUsecase, log, configConfig) + endpointServiceServer := service.NewEndpointsService(endpointUsecase, log, configConfig) appUsecase := biz.NewAppUsecase(appRepo, configConfig) - appService := service.NewAppService(appUsecase, log, configConfig) - sysService := service.NewSysService() + appsServiceServer := service.NewAppService(appUsecase, log, configConfig) + systemServiceServer := service.NewSysService() userUsecase := biz.NewUserUsecase(userRepo, configConfig) - userService := service.NewUserService(userUsecase, log, configConfig) - v := service.NewServices(fileService, authzService, endpointsService, appService, sysService, userService) + userServiceServer := service.NewUserService(userUsecase, log, configConfig) + v := service.NewServices(fileServiceServer, authServiceServer, endpointServiceServer, appsServiceServer, systemServiceServer, userServiceServer) accessKeyAuth := biz.NewAccessKeyAuth(appRepo, configConfig, log) pluginsApply := middleware.New(configConfig, redisDao, authzUsecase, log, accessKeyAuth, layeredCache) gatewayServer := server.NewGateway(gatewayConfig, configConfig, v, pluginsApply)