github.com/cloudreve/Cloudreve/v3@v3.0.0-20240224133659-3edb00a6484c/pkg/filesystem/driver/local/handler_test.go (about)

     1  package local
     2  
     3  import (
     4  	"context"
     5  	model "github.com/cloudreve/Cloudreve/v3/models"
     6  	"github.com/cloudreve/Cloudreve/v3/pkg/auth"
     7  	"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/driver"
     8  	"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx"
     9  	"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
    10  	"github.com/cloudreve/Cloudreve/v3/pkg/util"
    11  	"github.com/jinzhu/gorm"
    12  	"github.com/stretchr/testify/assert"
    13  	"io"
    14  	"os"
    15  	"strings"
    16  	"testing"
    17  )
    18  
    19  func TestHandler_Put(t *testing.T) {
    20  	asserts := assert.New(t)
    21  	handler := Driver{}
    22  
    23  	defer func() {
    24  		os.Remove(util.RelativePath("TestHandler_Put.txt"))
    25  		os.Remove(util.RelativePath("inner/TestHandler_Put.txt"))
    26  	}()
    27  
    28  	testCases := []struct {
    29  		file        fsctx.FileHeader
    30  		errContains string
    31  	}{
    32  		{&fsctx.FileStream{
    33  			SavePath: "TestHandler_Put.txt",
    34  			File:     io.NopCloser(strings.NewReader("")),
    35  		}, ""},
    36  		{&fsctx.FileStream{
    37  			SavePath: "TestHandler_Put.txt",
    38  			File:     io.NopCloser(strings.NewReader("")),
    39  		}, "file with the same name existed or unavailable"},
    40  		{&fsctx.FileStream{
    41  			SavePath: "inner/TestHandler_Put.txt",
    42  			File:     io.NopCloser(strings.NewReader("")),
    43  		}, ""},
    44  		{&fsctx.FileStream{
    45  			Mode:     fsctx.Append | fsctx.Overwrite,
    46  			SavePath: "inner/TestHandler_Put.txt",
    47  			File:     io.NopCloser(strings.NewReader("123")),
    48  		}, ""},
    49  		{&fsctx.FileStream{
    50  			AppendStart: 10,
    51  			Mode:        fsctx.Append | fsctx.Overwrite,
    52  			SavePath:    "inner/TestHandler_Put.txt",
    53  			File:        io.NopCloser(strings.NewReader("123")),
    54  		}, "size of unfinished uploaded chunks is not as expected"},
    55  		{&fsctx.FileStream{
    56  			Mode:     fsctx.Append | fsctx.Overwrite,
    57  			SavePath: "inner/TestHandler_Put.txt",
    58  			File:     io.NopCloser(strings.NewReader("123")),
    59  		}, ""},
    60  	}
    61  
    62  	for _, testCase := range testCases {
    63  		err := handler.Put(context.Background(), testCase.file)
    64  		if testCase.errContains != "" {
    65  			asserts.Error(err)
    66  			asserts.Contains(err.Error(), testCase.errContains)
    67  		} else {
    68  			asserts.NoError(err)
    69  			asserts.True(util.Exists(util.RelativePath(testCase.file.Info().SavePath)))
    70  		}
    71  	}
    72  }
    73  
    74  func TestDriver_TruncateFailed(t *testing.T) {
    75  	a := assert.New(t)
    76  	h := Driver{}
    77  	a.Error(h.Truncate(context.Background(), "TestDriver_TruncateFailed", 0))
    78  }
    79  
    80  func TestHandler_Delete(t *testing.T) {
    81  	asserts := assert.New(t)
    82  	handler := Driver{}
    83  	ctx := context.Background()
    84  	filePath := util.RelativePath("TestHandler_Delete.file")
    85  
    86  	file, err := os.Create(filePath)
    87  	asserts.NoError(err)
    88  	_ = file.Close()
    89  	list, err := handler.Delete(ctx, []string{"TestHandler_Delete.file"})
    90  	asserts.Equal([]string{}, list)
    91  	asserts.NoError(err)
    92  
    93  	file, err = os.Create(filePath)
    94  	_ = file.Close()
    95  	file, _ = os.OpenFile(filePath, os.O_RDWR, os.FileMode(0))
    96  	asserts.NoError(err)
    97  	list, err = handler.Delete(ctx, []string{"TestHandler_Delete.file", "test.notexist"})
    98  	file.Close()
    99  	asserts.Equal([]string{}, list)
   100  	asserts.NoError(err)
   101  
   102  	list, err = handler.Delete(ctx, []string{"test.notexist"})
   103  	asserts.Equal([]string{}, list)
   104  	asserts.NoError(err)
   105  
   106  	file, err = os.Create(filePath)
   107  	asserts.NoError(err)
   108  	list, err = handler.Delete(ctx, []string{"TestHandler_Delete.file"})
   109  	_ = file.Close()
   110  	asserts.Equal([]string{}, list)
   111  	asserts.NoError(err)
   112  }
   113  
   114  func TestHandler_Get(t *testing.T) {
   115  	asserts := assert.New(t)
   116  	handler := Driver{}
   117  	ctx, cancel := context.WithCancel(context.Background())
   118  	defer cancel()
   119  
   120  	// 成功
   121  	file, err := os.Create(util.RelativePath("TestHandler_Get.txt"))
   122  	asserts.NoError(err)
   123  	_ = file.Close()
   124  
   125  	rs, err := handler.Get(ctx, "TestHandler_Get.txt")
   126  	asserts.NoError(err)
   127  	asserts.NotNil(rs)
   128  
   129  	// 文件不存在
   130  
   131  	rs, err = handler.Get(ctx, "TestHandler_Get_notExist.txt")
   132  	asserts.Error(err)
   133  	asserts.Nil(rs)
   134  }
   135  
   136  func TestHandler_Thumb(t *testing.T) {
   137  	asserts := assert.New(t)
   138  	handler := Driver{}
   139  	ctx := context.Background()
   140  	file, err := os.Create(util.RelativePath("TestHandler_Thumb._thumb"))
   141  	asserts.NoError(err)
   142  	file.Close()
   143  
   144  	f := &model.File{
   145  		SourceName: "TestHandler_Thumb",
   146  		MetadataSerialized: map[string]string{
   147  			model.ThumbStatusMetadataKey: model.ThumbStatusExist,
   148  		},
   149  	}
   150  
   151  	// 正常
   152  	{
   153  		thumb, err := handler.Thumb(ctx, f)
   154  		asserts.NoError(err)
   155  		asserts.NotNil(thumb.Content)
   156  	}
   157  
   158  	// file 不存在
   159  	{
   160  		f.SourceName = "not_exist"
   161  		_, err := handler.Thumb(ctx, f)
   162  		asserts.Error(err)
   163  		asserts.ErrorIs(err, driver.ErrorThumbNotExist)
   164  	}
   165  
   166  	// thumb not exist
   167  	{
   168  		f.MetadataSerialized[model.ThumbStatusMetadataKey] = model.ThumbStatusNotExist
   169  		_, err := handler.Thumb(ctx, f)
   170  		asserts.Error(err)
   171  		asserts.ErrorIs(err, driver.ErrorThumbNotExist)
   172  	}
   173  }
   174  
   175  func TestHandler_Source(t *testing.T) {
   176  	asserts := assert.New(t)
   177  	handler := Driver{
   178  		Policy: &model.Policy{},
   179  	}
   180  	ctx := context.Background()
   181  	auth.General = auth.HMACAuth{SecretKey: []byte("test")}
   182  
   183  	// 成功
   184  	{
   185  		file := model.File{
   186  			Model: gorm.Model{
   187  				ID: 1,
   188  			},
   189  			Name: "test.jpg",
   190  		}
   191  		ctx := context.WithValue(ctx, fsctx.FileModelCtx, file)
   192  		sourceURL, err := handler.Source(ctx, "", 0, false, 0)
   193  		asserts.NoError(err)
   194  		asserts.NotEmpty(sourceURL)
   195  		asserts.Contains(sourceURL, "sign=")
   196  	}
   197  
   198  	// 下载
   199  	{
   200  		file := model.File{
   201  			Model: gorm.Model{
   202  				ID: 1,
   203  			},
   204  			Name: "test.jpg",
   205  		}
   206  		ctx := context.WithValue(ctx, fsctx.FileModelCtx, file)
   207  		sourceURL, err := handler.Source(ctx, "", 0, true, 0)
   208  		asserts.NoError(err)
   209  		asserts.NotEmpty(sourceURL)
   210  		asserts.Contains(sourceURL, "sign=")
   211  		asserts.Contains(sourceURL, "download")
   212  	}
   213  
   214  	// 无法获取上下文
   215  	{
   216  		sourceURL, err := handler.Source(ctx, "", 0, false, 0)
   217  		asserts.Error(err)
   218  		asserts.Empty(sourceURL)
   219  	}
   220  
   221  	// 设定了CDN
   222  	{
   223  		handler.Policy.BaseURL = "https://cqu.edu.cn"
   224  		file := model.File{
   225  			Model: gorm.Model{
   226  				ID: 1,
   227  			},
   228  			Name: "test.jpg",
   229  		}
   230  		ctx := context.WithValue(ctx, fsctx.FileModelCtx, file)
   231  		sourceURL, err := handler.Source(ctx, "", 0, false, 0)
   232  		asserts.NoError(err)
   233  		asserts.NotEmpty(sourceURL)
   234  		asserts.Contains(sourceURL, "sign=")
   235  		asserts.Contains(sourceURL, "https://cqu.edu.cn")
   236  	}
   237  
   238  	// 设定了CDN,解析失败
   239  	{
   240  		handler.Policy.BaseURL = string([]byte{0x7f})
   241  		file := model.File{
   242  			Model: gorm.Model{
   243  				ID: 1,
   244  			},
   245  			Name: "test.jpg",
   246  		}
   247  		ctx := context.WithValue(ctx, fsctx.FileModelCtx, file)
   248  		sourceURL, err := handler.Source(ctx, "", 0, false, 0)
   249  		asserts.Error(err)
   250  		asserts.Empty(sourceURL)
   251  	}
   252  }
   253  
   254  func TestHandler_GetDownloadURL(t *testing.T) {
   255  	asserts := assert.New(t)
   256  	handler := Driver{Policy: &model.Policy{}}
   257  	ctx := context.Background()
   258  	auth.General = auth.HMACAuth{SecretKey: []byte("test")}
   259  
   260  	// 成功
   261  	{
   262  		file := model.File{
   263  			Model: gorm.Model{
   264  				ID: 1,
   265  			},
   266  			Name: "test.jpg",
   267  		}
   268  		ctx := context.WithValue(ctx, fsctx.FileModelCtx, file)
   269  		downloadURL, err := handler.Source(ctx, "", 10, true, 0)
   270  		asserts.NoError(err)
   271  		asserts.Contains(downloadURL, "sign=")
   272  	}
   273  
   274  	// 无法获取上下文
   275  	{
   276  		downloadURL, err := handler.Source(ctx, "", 10, true, 0)
   277  		asserts.Error(err)
   278  		asserts.Empty(downloadURL)
   279  	}
   280  }
   281  
   282  func TestHandler_Token(t *testing.T) {
   283  	asserts := assert.New(t)
   284  	handler := Driver{
   285  		Policy: &model.Policy{},
   286  	}
   287  	ctx := context.Background()
   288  	upSession := &serializer.UploadSession{SavePath: "TestHandler_Token"}
   289  	_, err := handler.Token(ctx, 10, upSession, &fsctx.FileStream{})
   290  	asserts.NoError(err)
   291  
   292  	file, _ := os.Create("TestHandler_Token")
   293  	defer func() {
   294  		file.Close()
   295  		os.Remove("TestHandler_Token")
   296  	}()
   297  
   298  	_, err = handler.Token(ctx, 10, upSession, &fsctx.FileStream{})
   299  	asserts.Error(err)
   300  	asserts.Contains(err.Error(), "already exist")
   301  }
   302  
   303  func TestDriver_CancelToken(t *testing.T) {
   304  	a := assert.New(t)
   305  	handler := Driver{}
   306  	a.NoError(handler.CancelToken(context.Background(), &serializer.UploadSession{}))
   307  }
   308  
   309  func TestDriver_List(t *testing.T) {
   310  	asserts := assert.New(t)
   311  	handler := Driver{}
   312  	ctx := context.Background()
   313  
   314  	// 创建测试目录结构
   315  	for _, path := range []string{
   316  		"test/TestDriver_List/parent.txt",
   317  		"test/TestDriver_List/parent_folder2/sub2.txt",
   318  		"test/TestDriver_List/parent_folder1/sub_folder/sub1.txt",
   319  		"test/TestDriver_List/parent_folder1/sub_folder/sub2.txt",
   320  	} {
   321  		f, _ := util.CreatNestedFile(util.RelativePath(path))
   322  		f.Close()
   323  	}
   324  
   325  	// 非递归列出
   326  	{
   327  		res, err := handler.List(ctx, "test/TestDriver_List", false)
   328  		asserts.NoError(err)
   329  		asserts.Len(res, 3)
   330  	}
   331  
   332  	// 递归列出
   333  	{
   334  		res, err := handler.List(ctx, "test/TestDriver_List", true)
   335  		asserts.NoError(err)
   336  		asserts.Len(res, 7)
   337  	}
   338  }