@@ -10,6 +10,7 @@ import (
1010 "net/http"
1111 "net/http/httptest"
1212 "os"
13+ "path"
1314 "path/filepath"
1415 "reflect"
1516 "strings"
@@ -164,8 +165,7 @@ func createOverwriteDeleteSeq(t testing.TB, path string, data string) []TestRequ
164165 return req
165166}
166167
167- // TestResticHandler runs tests on the restic handler code, especially in append-only mode.
168- func TestResticHandler (t * testing.T ) {
168+ func createTestHandler (t * testing.T , conf Server ) (http.Handler , string , string , string , func ()) {
169169 buf := make ([]byte , 32 )
170170 _ , err := io .ReadFull (rand .Reader , buf )
171171 if err != nil {
@@ -175,6 +175,38 @@ func TestResticHandler(t *testing.T) {
175175 dataHash := sha256 .Sum256 ([]byte (data ))
176176 fileID := hex .EncodeToString (dataHash [:])
177177
178+ // setup the server with a local backend in a temporary directory
179+ tempdir , err := ioutil .TempDir ("" , "rest-server-test-" )
180+ if err != nil {
181+ t .Fatal (err )
182+ }
183+
184+ // make sure the tempdir is properly removed
185+ cleanup := func () {
186+ err := os .RemoveAll (tempdir )
187+ if err != nil {
188+ t .Fatal (err )
189+ }
190+ }
191+
192+ conf .Path = tempdir
193+ mux , err := NewHandler (& conf )
194+ if err != nil {
195+ t .Fatalf ("error from NewHandler: %v" , err )
196+ }
197+ return mux , data , fileID , tempdir , cleanup
198+ }
199+
200+ // TestResticAppendOnlyHandler runs tests on the restic handler code, especially in append-only mode.
201+ func TestResticAppendOnlyHandler (t * testing.T ) {
202+ mux , data , fileID , _ , cleanup := createTestHandler (t , Server {
203+ AppendOnly : true ,
204+ NoAuth : true ,
205+ Debug : true ,
206+ PanicOnError : true ,
207+ })
208+ defer cleanup ()
209+
178210 var tests = []struct {
179211 seq []TestRequest
180212 }{
@@ -226,37 +258,115 @@ func TestResticHandler(t *testing.T) {
226258 {createOverwriteDeleteSeq (t , "/parent2/data/" + fileID , data )},
227259 }
228260
229- // setup the server with a local backend in a temporary directory
230- tempdir , err := ioutil .TempDir ("" , "rest-server-test-" )
231- if err != nil {
232- t .Fatal (err )
261+ // create the repos
262+ for _ , path := range []string {"/" , "/parent1/sub1/" , "/parent1/" , "/parent2/" } {
263+ checkRequest (t , mux .ServeHTTP ,
264+ newRequest (t , "POST" , path + "?create=true" , nil ),
265+ []wantFunc {wantCode (http .StatusOK )})
233266 }
234267
235- // make sure the tempdir is properly removed
236- defer func () {
237- err := os .RemoveAll (tempdir )
238- if err != nil {
239- t .Fatal (err )
240- }
241- }()
268+ for _ , test := range tests {
269+ t .Run ("" , func (t * testing.T ) {
270+ for i , seq := range test .seq {
271+ t .Logf ("request %v: %v %v" , i , seq .req .Method , seq .req .URL .Path )
272+ checkRequest (t , mux .ServeHTTP , seq .req , seq .want )
273+ }
274+ })
275+ }
276+ }
242277
243- // set append-only mode and configure path
244- mux , err := NewHandler (& Server {
245- AppendOnly : true ,
246- Path : tempdir ,
278+ // createOverwriteDeleteSeq returns a sequence which will create a new file at
279+ // path, and then deletes it twice.
280+ func createIdempotentDeleteSeq (t testing.TB , path string , data string ) []TestRequest {
281+ return []TestRequest {
282+ {
283+ req : newRequest (t , "POST" , path , strings .NewReader (data )),
284+ want : []wantFunc {wantCode (http .StatusOK )},
285+ },
286+ {
287+ req : newRequest (t , "DELETE" , path , nil ),
288+ want : []wantFunc {wantCode (http .StatusOK )},
289+ },
290+ {
291+ req : newRequest (t , "GET" , path , nil ),
292+ want : []wantFunc {wantCode (http .StatusNotFound )},
293+ },
294+ {
295+ req : newRequest (t , "DELETE" , path , nil ),
296+ want : []wantFunc {wantCode (http .StatusOK )},
297+ },
298+ }
299+ }
300+
301+ // TestResticHandler runs tests on the restic handler code, especially in append-only mode.
302+ func TestResticHandler (t * testing.T ) {
303+ mux , data , fileID , _ , cleanup := createTestHandler (t , Server {
247304 NoAuth : true ,
248305 Debug : true ,
249306 PanicOnError : true ,
250307 })
251- if err != nil {
252- t .Fatalf ("error from NewHandler: %v" , err )
308+ defer cleanup ()
309+
310+ var tests = []struct {
311+ seq []TestRequest
312+ }{
313+ {createIdempotentDeleteSeq (t , "/config" , data )},
314+ {createIdempotentDeleteSeq (t , "/data/" + fileID , data )},
253315 }
254316
255- // create the repos
256- for _ , path := range []string {"/" , "/parent1/sub1/" , "/parent1/" , "/parent2/" } {
257- checkRequest (t , mux .ServeHTTP ,
258- newRequest (t , "POST" , path + "?create=true" , nil ),
259- []wantFunc {wantCode (http .StatusOK )})
317+ // create the repo
318+ checkRequest (t , mux .ServeHTTP ,
319+ newRequest (t , "POST" , "/?create=true" , nil ),
320+ []wantFunc {wantCode (http .StatusOK )})
321+
322+ for _ , test := range tests {
323+ t .Run ("" , func (t * testing.T ) {
324+ for i , seq := range test .seq {
325+ t .Logf ("request %v: %v %v" , i , seq .req .Method , seq .req .URL .Path )
326+ checkRequest (t , mux .ServeHTTP , seq .req , seq .want )
327+ }
328+ })
329+ }
330+ }
331+
332+ // TestResticErrorHandler runs tests on the restic handler error handling.
333+ func TestResticErrorHandler (t * testing.T ) {
334+ mux , _ , _ , tempdir , cleanup := createTestHandler (t , Server {
335+ AppendOnly : true ,
336+ NoAuth : true ,
337+ Debug : true ,
338+ })
339+ defer cleanup ()
340+
341+ var tests = []struct {
342+ seq []TestRequest
343+ }{
344+ // Test inaccessible file
345+ {
346+ []TestRequest {{
347+ req : newRequest (t , "GET" , "/config" , nil ),
348+ want : []wantFunc {wantCode (http .StatusInternalServerError )},
349+ }},
350+ },
351+ {
352+ []TestRequest {{
353+ req : newRequest (t , "GET" , "/parent4/config" , nil ),
354+ want : []wantFunc {wantCode (http .StatusNotFound )},
355+ }},
356+ },
357+ }
358+
359+ // create the repo
360+ checkRequest (t , mux .ServeHTTP ,
361+ newRequest (t , "POST" , "/?create=true" , nil ),
362+ []wantFunc {wantCode (http .StatusOK )})
363+ // create inaccessible config
364+ checkRequest (t , mux .ServeHTTP ,
365+ newRequest (t , "POST" , "/config" , strings .NewReader ("example" )),
366+ []wantFunc {wantCode (http .StatusOK )})
367+ err := os .Chmod (path .Join (tempdir , "config" ), 0o000 )
368+ if err != nil {
369+ t .Fatal (err )
260370 }
261371
262372 for _ , test := range tests {
@@ -359,31 +469,13 @@ func (d *delayErrorReader) Read(p []byte) (int, error) {
359469
360470// TestAbortedRequest runs tests with concurrent upload requests for the same file.
361471func TestAbortedRequest (t * testing.T ) {
362- // setup the server with a local backend in a temporary directory
363- tempdir , err := ioutil .TempDir ("" , "rest-server-test-" )
364- if err != nil {
365- t .Fatal (err )
366- }
367-
368- // make sure the tempdir is properly removed
369- defer func () {
370- err := os .RemoveAll (tempdir )
371- if err != nil {
372- t .Fatal (err )
373- }
374- }()
375-
376- // configure path, the race condition doesn't happen for append-only repositories
377- mux , err := NewHandler (& Server {
378- AppendOnly : false ,
379- Path : tempdir ,
472+ // the race condition doesn't happen for append-only repositories
473+ mux , _ , _ , _ , cleanup := createTestHandler (t , Server {
380474 NoAuth : true ,
381475 Debug : true ,
382476 PanicOnError : true ,
383477 })
384- if err != nil {
385- t .Fatalf ("error from NewHandler: %v" , err )
386- }
478+ defer cleanup ()
387479
388480 // create the repo
389481 checkRequest (t , mux .ServeHTTP ,
0 commit comments