f8d56bebaf
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
146 lines
3.7 KiB
Go
146 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)
|
|
}
|
|
})
|
|
}
|
|
}
|