github.com/mckael/restic@v0.8.3/internal/backend/rest/rest_int_test.go (about)

     1  package rest_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"net/url"
     9  	"reflect"
    10  	"strconv"
    11  	"testing"
    12  
    13  	"github.com/restic/restic/internal/backend/rest"
    14  	"github.com/restic/restic/internal/restic"
    15  )
    16  
    17  func TestListAPI(t *testing.T) {
    18  	var tests = []struct {
    19  		Name string
    20  
    21  		ContentType string // response header
    22  		Data        string // response data
    23  		Requests    int
    24  
    25  		Result []restic.FileInfo
    26  	}{
    27  		{
    28  			Name:        "content-type-unknown",
    29  			ContentType: "application/octet-stream",
    30  			Data: `[
    31  				"1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985",
    32  				"3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352",
    33  				"8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b"
    34  			]`,
    35  			Result: []restic.FileInfo{
    36  				{Name: "1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985", Size: 4386},
    37  				{Name: "3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352", Size: 15214},
    38  				{Name: "8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b", Size: 33393},
    39  			},
    40  			Requests: 4,
    41  		},
    42  		{
    43  			Name:        "content-type-v1",
    44  			ContentType: "application/vnd.x.restic.rest.v1",
    45  			Data: `[
    46  				"1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985",
    47  				"3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352",
    48  				"8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b"
    49  			]`,
    50  			Result: []restic.FileInfo{
    51  				{Name: "1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985", Size: 4386},
    52  				{Name: "3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352", Size: 15214},
    53  				{Name: "8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b", Size: 33393},
    54  			},
    55  			Requests: 4,
    56  		},
    57  		{
    58  			Name:        "content-type-v2",
    59  			ContentType: "application/vnd.x.restic.rest.v2",
    60  			Data: `[
    61  				{"name": "1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985", "size": 1001},
    62  				{"name": "3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352", "size": 1002},
    63  				{"name": "8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b", "size": 1003}
    64  			]`,
    65  			Result: []restic.FileInfo{
    66  				{Name: "1122e6749358b057fa1ac6b580a0fbe7a9a5fbc92e82743ee21aaf829624a985", Size: 1001},
    67  				{Name: "3b6ec1af8d4f7099d0445b12fdb75b166ba19f789e5c48350c423dc3b3e68352", Size: 1002},
    68  				{Name: "8271d221a60e0058e6c624f248d0080fc04f4fac07a28584a9b89d0eb69e189b", Size: 1003},
    69  			},
    70  			Requests: 1,
    71  		},
    72  	}
    73  
    74  	for _, test := range tests {
    75  		t.Run(test.Name, func(t *testing.T) {
    76  			numRequests := 0
    77  			srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
    78  				numRequests++
    79  				t.Logf("req %v %v, accept: %v", req.Method, req.URL.Path, req.Header["Accept"])
    80  
    81  				var err error
    82  				switch {
    83  				case req.Method == "GET":
    84  					// list files in data/
    85  					res.Header().Set("Content-Type", test.ContentType)
    86  					_, err = res.Write([]byte(test.Data))
    87  
    88  					if err != nil {
    89  						t.Fatal(err)
    90  					}
    91  					return
    92  				case req.Method == "HEAD":
    93  					// stat file in data/, use the first two bytes in the name
    94  					// of the file as the size :)
    95  					filename := req.URL.Path[6:]
    96  					len, err := strconv.ParseInt(filename[:4], 16, 64)
    97  					if err != nil {
    98  						t.Fatal(err)
    99  					}
   100  
   101  					res.Header().Set("Content-Length", fmt.Sprintf("%d", len))
   102  					res.WriteHeader(http.StatusOK)
   103  					return
   104  				}
   105  
   106  				t.Errorf("unhandled request %v %v", req.Method, req.URL.Path)
   107  			}))
   108  			defer srv.Close()
   109  
   110  			srvURL, err := url.Parse(srv.URL)
   111  			if err != nil {
   112  				t.Fatal(err)
   113  			}
   114  
   115  			cfg := rest.Config{
   116  				Connections: 5,
   117  				URL:         srvURL,
   118  			}
   119  
   120  			be, err := rest.Open(cfg, http.DefaultTransport)
   121  			if err != nil {
   122  				t.Fatal(err)
   123  			}
   124  
   125  			var list []restic.FileInfo
   126  			err = be.List(context.TODO(), restic.DataFile, func(fi restic.FileInfo) error {
   127  				list = append(list, fi)
   128  				return nil
   129  			})
   130  			if err != nil {
   131  				t.Fatal(err)
   132  			}
   133  
   134  			if !reflect.DeepEqual(list, test.Result) {
   135  				t.Fatalf("wrong response returned, want:\n  %v\ngot:  %v", test.Result, list)
   136  			}
   137  
   138  			if numRequests != test.Requests {
   139  				t.Fatalf("wrong number of HTTP requests executed, want %d, got %d", test.Requests, numRequests)
   140  			}
   141  
   142  			defer func() {
   143  				err = be.Close()
   144  				if err != nil {
   145  					t.Fatal(err)
   146  				}
   147  			}()
   148  		})
   149  	}
   150  }