mirror of
https://github.com/restic/restic.git
synced 2025-10-09 00:50:13 +00:00
backend/rest: Implement REST API v2
This commit is contained in:
150
internal/backend/rest/rest_int_test.go
Normal file
150
internal/backend/rest/rest_int_test.go
Normal file
@@ -0,0 +1,150 @@
|
||||
package rest_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/restic/restic/internal/backend/rest"
|
||||
"github.com/restic/restic/internal/restic"
|
||||
)
|
||||
|
||||
func TestListAPI(t *testing.T) {
|
||||
var tests = []struct {
|
||||
Name string
|
||||
|
||||
ContentType string // response header
|
||||
Data string // response data
|
||||
Requests int
|
||||
|
||||
Result []restic.FileInfo
|
||||
}{
|
||||
{
|
||||
Name: "content-type-unknown",
|
||||
ContentType: "application/octet-stream",
|
||||
Data: `[
|
||||
"1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985",
|
||||
"3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352",
|
||||
"8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b"
|
||||
]`,
|
||||
Result: []restic.FileInfo{
|
||||
{Name: "1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985", Size: 4386},
|
||||
{Name: "3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352", Size: 15214},
|
||||
{Name: "8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b", Size: 33393},
|
||||
},
|
||||
Requests: 4,
|
||||
},
|
||||
{
|
||||
Name: "content-type-v1",
|
||||
ContentType: "application/vnd.x.restic.rest.v1",
|
||||
Data: `[
|
||||
"1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985",
|
||||
"3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352",
|
||||
"8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b"
|
||||
]`,
|
||||
Result: []restic.FileInfo{
|
||||
{Name: "1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985", Size: 4386},
|
||||
{Name: "3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352", Size: 15214},
|
||||
{Name: "8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b", Size: 33393},
|
||||
},
|
||||
Requests: 4,
|
||||
},
|
||||
{
|
||||
Name: "content-type-v2",
|
||||
ContentType: "application/vnd.x.restic.rest.v2",
|
||||
Data: `[
|
||||
{"name": "1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985", "size": 1001},
|
||||
{"name": "3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352", "size": 1002},
|
||||
{"name": "8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b", "size": 1003}
|
||||
]`,
|
||||
Result: []restic.FileInfo{
|
||||
{Name: "1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985", Size: 1001},
|
||||
{Name: "3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352", Size: 1002},
|
||||
{Name: "8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b", Size: 1003},
|
||||
},
|
||||
Requests: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
numRequests := 0
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||
numRequests++
|
||||
t.Logf("req %v %v, accept: %v", req.Method, req.URL.Path, req.Header["Accept"])
|
||||
|
||||
var err error
|
||||
switch {
|
||||
case req.Method == "GET":
|
||||
// list files in data/
|
||||
res.Header().Set("Content-Type", test.ContentType)
|
||||
_, err = res.Write([]byte(test.Data))
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return
|
||||
case req.Method == "HEAD":
|
||||
// stat file in data/, use the first two bytes in the name
|
||||
// of the file as the size :)
|
||||
filename := req.URL.Path[6:]
|
||||
len, err := strconv.ParseInt(filename[:4], 16, 64)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
res.Header().Set("Content-Length", fmt.Sprintf("%d", len))
|
||||
res.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
t.Errorf("unhandled request %v %v", req.Method, req.URL.Path)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
srvURL, err := url.Parse(srv.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cfg := rest.Config{
|
||||
Connections: 5,
|
||||
URL: srvURL,
|
||||
}
|
||||
|
||||
be, err := rest.Open(cfg, http.DefaultTransport)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var list []restic.FileInfo
|
||||
err = be.List(context.TODO(), restic.DataFile, func(fi restic.FileInfo) error {
|
||||
list = append(list, fi)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(list, test.Result) {
|
||||
t.Fatalf("wrong response returned, want:\n %v\ngot: %v", test.Result, list)
|
||||
}
|
||||
|
||||
if numRequests != test.Requests {
|
||||
t.Fatalf("wrong number of HTTP requests executed, want %d, got %d", test.Requests, numRequests)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err = be.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user