rclone/cmd/serve/restic/restic_appendonly_test.go
albertony f8d56bebaf
config: delay load config file (#5258)
Restructuring of config code in v1.55 resulted in config
file being loaded early at process startup. If configuration
file is encrypted this means user will need to supply the password,
even when running commands that does not use config.
This also lead to an issue where mount with --deamon failed to
decrypt the config file when it had to prompt user for passord.

Fixes #5236
Fixes #5228
2021-04-26 23:37:49 +02:00

147 lines
3.7 KiB
Go

package restic
import (
"crypto/rand"
"encoding/hex"
"io"
"io/ioutil"
"net/http"
"os"
"strings"
"testing"
"github.com/rclone/rclone/cmd"
"github.com/rclone/rclone/cmd/serve/httplib/httpflags"
"github.com/rclone/rclone/fs/config/configfile"
"github.com/stretchr/testify/require"
)
// createOverwriteDeleteSeq returns a sequence which will create a new file at
// path, and then try to overwrite and delete it.
func createOverwriteDeleteSeq(t testing.TB, path string) []TestRequest {
// add a file, try to overwrite and delete it
req := []TestRequest{
{
req: newRequest(t, "GET", path, nil),
want: []wantFunc{wantCode(http.StatusNotFound)},
},
{
req: newRequest(t, "POST", path, strings.NewReader("foobar test config")),
want: []wantFunc{wantCode(http.StatusOK)},
},
{
req: newRequest(t, "GET", path, nil),
want: []wantFunc{
wantCode(http.StatusOK),
wantBody("foobar test config"),
},
},
{
req: newRequest(t, "POST", path, strings.NewReader("other config")),
want: []wantFunc{wantCode(http.StatusForbidden)},
},
{
req: newRequest(t, "GET", path, nil),
want: []wantFunc{
wantCode(http.StatusOK),
wantBody("foobar test config"),
},
},
{
req: newRequest(t, "DELETE", path, nil),
want: []wantFunc{wantCode(http.StatusForbidden)},
},
{
req: newRequest(t, "GET", path, nil),
want: []wantFunc{
wantCode(http.StatusOK),
wantBody("foobar test config"),
},
},
}
return req
}
// TestResticHandler runs tests on the restic handler code, especially in append-only mode.
func TestResticHandler(t *testing.T) {
configfile.Install()
buf := make([]byte, 32)
_, err := io.ReadFull(rand.Reader, buf)
require.NoError(t, err)
randomID := hex.EncodeToString(buf)
var tests = []struct {
seq []TestRequest
}{
{createOverwriteDeleteSeq(t, "/config")},
{createOverwriteDeleteSeq(t, "/data/"+randomID)},
{
// ensure we can add and remove lock files
[]TestRequest{
{
req: newRequest(t, "GET", "/locks/"+randomID, nil),
want: []wantFunc{wantCode(http.StatusNotFound)},
},
{
req: newRequest(t, "POST", "/locks/"+randomID, strings.NewReader("lock file")),
want: []wantFunc{wantCode(http.StatusOK)},
},
{
req: newRequest(t, "GET", "/locks/"+randomID, nil),
want: []wantFunc{
wantCode(http.StatusOK),
wantBody("lock file"),
},
},
{
req: newRequest(t, "POST", "/locks/"+randomID, strings.NewReader("other lock file")),
want: []wantFunc{wantCode(http.StatusForbidden)},
},
{
req: newRequest(t, "DELETE", "/locks/"+randomID, nil),
want: []wantFunc{wantCode(http.StatusOK)},
},
{
req: newRequest(t, "GET", "/locks/"+randomID, nil),
want: []wantFunc{wantCode(http.StatusNotFound)},
},
},
},
}
// setup rclone with a local backend in a temporary directory
tempdir, err := ioutil.TempDir("", "rclone-restic-test-")
require.NoError(t, err)
// make sure the tempdir is properly removed
defer func() {
err := os.RemoveAll(tempdir)
require.NoError(t, err)
}()
// globally set append-only mode
prev := appendOnly
appendOnly = true
defer func() {
appendOnly = prev // reset when done
}()
// make a new file system in the temp dir
f := cmd.NewFsSrc([]string{tempdir})
srv := NewServer(f, &httpflags.Opt)
// create the repo
checkRequest(t, srv.ServeHTTP,
newRequest(t, "POST", "/?create=true", nil),
[]wantFunc{wantCode(http.StatusOK)})
for _, test := range tests {
t.Run("", func(t *testing.T) {
for i, seq := range test.seq {
t.Logf("request %v: %v %v", i, seq.req.Method, seq.req.URL.Path)
checkRequest(t, srv.ServeHTTP, seq.req, seq.want)
}
})
}
}