generated from VLADIMIR/template
add load applications
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"evening_detective_server/internal/modules/file_storage"
|
||||
"evening_detective_server/internal/modules/processor_jwt"
|
||||
"evening_detective_server/internal/modules/string_tools"
|
||||
"evening_detective_server/internal/services/file_service"
|
||||
proto "evening_detective_server/proto"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// fakeStorage — in-memory реализация IFileStorage для app-слоя.
|
||||
type fakeStorage struct {
|
||||
files map[string]*file_storage.File
|
||||
putErr error
|
||||
getErr error
|
||||
}
|
||||
|
||||
func newFakeStorage() *fakeStorage {
|
||||
return &fakeStorage{files: map[string]*file_storage.File{}}
|
||||
}
|
||||
|
||||
func (s *fakeStorage) Put(_ context.Context, f *file_storage.File) error {
|
||||
if s.putErr != nil {
|
||||
return s.putErr
|
||||
}
|
||||
cp := *f
|
||||
cp.Data = append([]byte(nil), f.Data...)
|
||||
s.files[f.Name] = &cp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *fakeStorage) Get(_ context.Context, name string) (*file_storage.File, error) {
|
||||
if s.getErr != nil {
|
||||
return nil, s.getErr
|
||||
}
|
||||
f, ok := s.files[name]
|
||||
if !ok {
|
||||
return nil, file_storage.ErrFileNotFound
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (s *fakeStorage) Delete(_ context.Context, name string) error {
|
||||
delete(s.files, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *fakeStorage) MimeType(filename string) string {
|
||||
return file_storage.FileType(filename)
|
||||
}
|
||||
|
||||
func newTestFileServer(storage *fakeStorage, maxSize int) *server {
|
||||
if storage == nil {
|
||||
storage = newFakeStorage()
|
||||
}
|
||||
return &server{
|
||||
fileService: file_service.NewFileService(storage, string_tools.NewStringTools(), maxSize),
|
||||
}
|
||||
}
|
||||
|
||||
func ctxWithClaims(roles ...string) context.Context {
|
||||
return context.WithValue(context.Background(), "claims", &processor_jwt.JWTClaims{UserID: 1, Roles: roles})
|
||||
}
|
||||
|
||||
func pdfData(n int) []byte {
|
||||
b := make([]byte, n)
|
||||
copy(b, "%PDF-1.7 ")
|
||||
for i := 8; i < n; i++ {
|
||||
b[i] = 'x'
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestUploadFilePermissionDenied(t *testing.T) {
|
||||
s := newTestFileServer(nil, 1<<20)
|
||||
_, err := s.UploadFile(ctxWithClaims(), &proto.UploadFileReq{Filename: "clue.pdf", Data: pdfData(16)})
|
||||
if status.Code(err) != codes.PermissionDenied {
|
||||
t.Errorf("code = %v, want PermissionDenied", status.Code(err))
|
||||
}
|
||||
}
|
||||
|
||||
func TestUploadFileValidationInvalidArgument(t *testing.T) {
|
||||
s := newTestFileServer(nil, 1<<20)
|
||||
// Имя без расширения.
|
||||
_, err := s.UploadFile(ctxWithClaims("author"), &proto.UploadFileReq{Filename: "clue", Data: pdfData(16)})
|
||||
if status.Code(err) != codes.InvalidArgument {
|
||||
t.Errorf("code = %v, want InvalidArgument", status.Code(err))
|
||||
}
|
||||
}
|
||||
|
||||
func TestUploadFileTooLargeResourceExhausted(t *testing.T) {
|
||||
s := newTestFileServer(nil, 1024)
|
||||
_, err := s.UploadFile(ctxWithClaims("author"), &proto.UploadFileReq{Filename: "clue.pdf", Data: pdfData(1025)})
|
||||
if status.Code(err) != codes.ResourceExhausted {
|
||||
t.Errorf("code = %v, want ResourceExhausted", status.Code(err))
|
||||
}
|
||||
}
|
||||
|
||||
func TestUploadFilePutErrorInternal(t *testing.T) {
|
||||
storage := newFakeStorage()
|
||||
storage.putErr = errors.New("s3 недоступен")
|
||||
s := newTestFileServer(storage, 1<<20)
|
||||
|
||||
_, err := s.UploadFile(ctxWithClaims("author"), &proto.UploadFileReq{Filename: "clue.pdf", Data: pdfData(16)})
|
||||
if status.Code(err) != codes.Internal {
|
||||
t.Errorf("code = %v, want Internal", status.Code(err))
|
||||
}
|
||||
}
|
||||
|
||||
func TestUploadFileSuccess(t *testing.T) {
|
||||
s := newTestFileServer(nil, 1<<20)
|
||||
rsp, err := s.UploadFile(ctxWithClaims("author"), &proto.UploadFileReq{Filename: "clue.pdf", Data: pdfData(16)})
|
||||
if err != nil {
|
||||
t.Fatalf("UploadFile: %v", err)
|
||||
}
|
||||
if rsp.Filename == "" {
|
||||
t.Errorf("Filename пустой")
|
||||
}
|
||||
if rsp.FileType != "pdf" {
|
||||
t.Errorf("FileType = %q, want pdf", rsp.FileType)
|
||||
}
|
||||
if rsp.Error != "" {
|
||||
t.Errorf("Error = %q, want пусто", rsp.Error)
|
||||
}
|
||||
}
|
||||
|
||||
// mockServerTransportStream — заглушка для grpc.SetHeader в юнит-тестах.
|
||||
type mockServerTransportStream struct {
|
||||
grpc.ServerTransportStream
|
||||
header metadata.MD
|
||||
}
|
||||
|
||||
func (m *mockServerTransportStream) SetHeader(md metadata.MD) error {
|
||||
m.header = md
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestDownloadFileNotFound(t *testing.T) {
|
||||
s := newTestFileServer(nil, 1<<20)
|
||||
_, err := s.DownloadFile(context.Background(), &proto.DownloadFileReq{Filename: "missing.pdf"})
|
||||
if status.Code(err) != codes.NotFound {
|
||||
t.Errorf("code = %v, want NotFound", status.Code(err))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDownloadFileInternal(t *testing.T) {
|
||||
storage := newFakeStorage()
|
||||
storage.getErr = errors.New("s3 недоступен")
|
||||
s := newTestFileServer(storage, 1<<20)
|
||||
|
||||
_, err := s.DownloadFile(context.Background(), &proto.DownloadFileReq{Filename: "clue.pdf"})
|
||||
if status.Code(err) != codes.Internal {
|
||||
t.Errorf("code = %v, want Internal", status.Code(err))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDownloadFileSuccess(t *testing.T) {
|
||||
storage := newFakeStorage()
|
||||
storage.files["clue.pdf"] = &file_storage.File{
|
||||
Name: "clue.pdf",
|
||||
Data: []byte("%PDF-1.7 content"),
|
||||
Mime: "application/pdf",
|
||||
}
|
||||
s := newTestFileServer(storage, 1<<20)
|
||||
|
||||
stream := &mockServerTransportStream{}
|
||||
ctx := grpc.NewContextWithServerTransportStream(context.Background(), stream)
|
||||
|
||||
body, err := s.DownloadFile(ctx, &proto.DownloadFileReq{Filename: "clue.pdf"})
|
||||
if err != nil {
|
||||
t.Fatalf("DownloadFile: %v", err)
|
||||
}
|
||||
if string(body.Data) != "%PDF-1.7 content" {
|
||||
t.Errorf("Data = %q", body.Data)
|
||||
}
|
||||
if body.ContentType != "application/pdf" {
|
||||
t.Errorf("ContentType = %q, want application/pdf", body.ContentType)
|
||||
}
|
||||
if got := stream.header.Get("X-Content-Type-Options"); len(got) != 1 || got[0] != "nosniff" {
|
||||
t.Errorf("X-Content-Type-Options = %v, want nosniff", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user