package services import ( "bytes" "database/sql" "errors" "mime/multipart" "net/http" "net/http/httptest" "testing" "quyun/v2/app/commands/testx" "quyun/v2/app/errorx" common_dto "quyun/v2/app/http/v1/dto" . "github.com/smartystreets/goconvey/convey" "github.com/stretchr/testify/suite" "go.ipao.vip/atom/contracts" "go.uber.org/dig" ) type CommonTestSuiteInjectParams struct { dig.In DB *sql.DB Initials []contracts.Initial `group:"initials"` } type CommonTestSuite struct { suite.Suite CommonTestSuiteInjectParams } func Test_Common(t *testing.T) { providers := testx.Default().With(Provide) testx.Serve(providers, t, func(p CommonTestSuiteInjectParams) { suite.Run(t, &CommonTestSuite{CommonTestSuiteInjectParams: p}) }) } func (s *CommonTestSuite) Test_AbortUpload() { Convey("AbortUpload", s.T(), func() { ctx := s.T().Context() tenantID := int64(1) ownerID := int64(1001) tempDir := s.T().TempDir() So(Common.storage, ShouldNotBeNil) Common.storage.Config.LocalPath = tempDir newUpload := func() string { form := &common_dto.UploadInitForm{ Filename: "sample.mp4", Type: "video", MimeType: "video/mp4", } resp, err := Common.InitUpload(ctx, tenantID, ownerID, form) So(err, ShouldBeNil) So(resp.UploadID, ShouldNotBeBlank) return resp.UploadID } Convey("should allow owner to abort", func() { uploadID := newUpload() err := Common.AbortUpload(ctx, tenantID, ownerID, uploadID) So(err, ShouldBeNil) }) Convey("should reject abort by other user", func() { uploadID := newUpload() otherID := int64(2002) err := Common.AbortUpload(ctx, tenantID, otherID, uploadID) So(err, ShouldNotBeNil) var appErr *errorx.AppError So(errors.As(err, &appErr), ShouldBeTrue) So(appErr.Code, ShouldEqual, errorx.ErrForbidden.Code) So(Common.AbortUpload(ctx, tenantID, ownerID, uploadID), ShouldBeNil) }) Convey("should return not found for missing upload", func() { err := Common.AbortUpload(ctx, tenantID, ownerID, "missing-upload") So(err, ShouldNotBeNil) var appErr *errorx.AppError So(errors.As(err, &appErr), ShouldBeTrue) So(appErr.Code, ShouldEqual, errorx.ErrRecordNotFound.Code) }) }) } func (s *CommonTestSuite) Test_UploadPart() { Convey("UploadPart", s.T(), func() { ctx := s.T().Context() tenantID := int64(1) ownerID := int64(1001) otherID := int64(2002) tempDir := s.T().TempDir() So(Common.storage, ShouldNotBeNil) Common.storage.Config.LocalPath = tempDir newUpload := func() string { form := &common_dto.UploadInitForm{ Filename: "sample.mp4", Type: "video", MimeType: "video/mp4", } resp, err := Common.InitUpload(ctx, tenantID, ownerID, form) So(err, ShouldBeNil) So(resp.UploadID, ShouldNotBeBlank) return resp.UploadID } newFileHeader := func() *multipart.FileHeader { body := &bytes.Buffer{} writer := multipart.NewWriter(body) part, err := writer.CreateFormFile("file", "sample.txt") So(err, ShouldBeNil) _, err = part.Write([]byte("hello world")) So(err, ShouldBeNil) So(writer.Close(), ShouldBeNil) req := httptest.NewRequest(http.MethodPost, "/upload", body) req.Header.Set("Content-Type", writer.FormDataContentType()) So(req.ParseMultipartForm(32<<20), ShouldBeNil) So(req.MultipartForm, ShouldNotBeNil) So(req.MultipartForm.File["file"], ShouldNotBeEmpty) return req.MultipartForm.File["file"][0] } Convey("should allow owner to upload part", func() { uploadID := newUpload() form := &common_dto.UploadPartForm{UploadID: uploadID, PartNumber: 1} err := Common.UploadPart(ctx, tenantID, ownerID, newFileHeader(), form) So(err, ShouldBeNil) }) Convey("should reject other user", func() { uploadID := newUpload() form := &common_dto.UploadPartForm{UploadID: uploadID, PartNumber: 1} err := Common.UploadPart(ctx, tenantID, otherID, newFileHeader(), form) So(err, ShouldNotBeNil) var appErr *errorx.AppError So(errors.As(err, &appErr), ShouldBeTrue) So(appErr.Code, ShouldEqual, errorx.ErrForbidden.Code) }) }) }