github.com/mckael/restic@v0.8.3/internal/backend/rest/rest_test.go (about) 1 package rest_test 2 3 import ( 4 "context" 5 "net" 6 "net/url" 7 "os" 8 "os/exec" 9 "testing" 10 "time" 11 12 "github.com/restic/restic/internal/backend" 13 "github.com/restic/restic/internal/backend/rest" 14 "github.com/restic/restic/internal/backend/test" 15 "github.com/restic/restic/internal/restic" 16 rtest "github.com/restic/restic/internal/test" 17 ) 18 19 func runRESTServer(ctx context.Context, t testing.TB, dir string) (*url.URL, func()) { 20 srv, err := exec.LookPath("rest-server") 21 if err != nil { 22 t.Skip(err) 23 } 24 25 cmd := exec.CommandContext(ctx, srv, "--path", dir) 26 cmd.Stdout = os.Stdout 27 cmd.Stderr = os.Stdout 28 if err := cmd.Start(); err != nil { 29 t.Fatal(err) 30 } 31 32 // wait until the TCP port is reachable 33 var success bool 34 for i := 0; i < 10; i++ { 35 time.Sleep(200 * time.Millisecond) 36 37 c, err := net.Dial("tcp", "localhost:8000") 38 if err != nil { 39 continue 40 } 41 42 success = true 43 if err := c.Close(); err != nil { 44 t.Fatal(err) 45 } 46 } 47 48 if !success { 49 t.Fatal("unable to connect to rest server") 50 return nil, nil 51 } 52 53 url, err := url.Parse("http://localhost:8000/restic-test") 54 if err != nil { 55 t.Fatal(err) 56 } 57 58 cleanup := func() { 59 if err := cmd.Process.Kill(); err != nil { 60 t.Fatal(err) 61 } 62 63 // ignore errors, we've killed the process 64 _ = cmd.Wait() 65 } 66 67 return url, cleanup 68 } 69 70 func newTestSuite(ctx context.Context, t testing.TB, url *url.URL, minimalData bool) *test.Suite { 71 tr, err := backend.Transport(backend.TransportOptions{}) 72 if err != nil { 73 t.Fatalf("cannot create transport for tests: %v", err) 74 } 75 76 return &test.Suite{ 77 MinimalData: minimalData, 78 79 // NewConfig returns a config for a new temporary backend that will be used in tests. 80 NewConfig: func() (interface{}, error) { 81 cfg := rest.NewConfig() 82 cfg.URL = url 83 return cfg, nil 84 }, 85 86 // CreateFn is a function that creates a temporary repository for the tests. 87 Create: func(config interface{}) (restic.Backend, error) { 88 cfg := config.(rest.Config) 89 return rest.Create(cfg, tr) 90 }, 91 92 // OpenFn is a function that opens a previously created temporary repository. 93 Open: func(config interface{}) (restic.Backend, error) { 94 cfg := config.(rest.Config) 95 return rest.Open(cfg, tr) 96 }, 97 98 // CleanupFn removes data created during the tests. 99 Cleanup: func(config interface{}) error { 100 return nil 101 }, 102 } 103 } 104 105 func TestBackendREST(t *testing.T) { 106 defer func() { 107 if t.Skipped() { 108 rtest.SkipDisallowed(t, "restic/backend/rest.TestBackendREST") 109 } 110 }() 111 112 ctx, cancel := context.WithCancel(context.Background()) 113 defer cancel() 114 115 dir, cleanup := rtest.TempDir(t) 116 defer cleanup() 117 118 serverURL, cleanup := runRESTServer(ctx, t, dir) 119 defer cleanup() 120 121 newTestSuite(ctx, t, serverURL, false).RunTests(t) 122 } 123 124 func TestBackendRESTExternalServer(t *testing.T) { 125 repostr := os.Getenv("RESTIC_TEST_REST_REPOSITORY") 126 if repostr == "" { 127 t.Skipf("environment variable %v not set", "RESTIC_TEST_REST_REPOSITORY") 128 } 129 130 cfg, err := rest.ParseConfig(repostr) 131 if err != nil { 132 t.Fatal(err) 133 } 134 135 c := cfg.(rest.Config) 136 137 ctx, cancel := context.WithCancel(context.Background()) 138 defer cancel() 139 140 newTestSuite(ctx, t, c.URL, true).RunTests(t) 141 } 142 143 func BenchmarkBackendREST(t *testing.B) { 144 ctx, cancel := context.WithCancel(context.Background()) 145 defer cancel() 146 147 dir, cleanup := rtest.TempDir(t) 148 defer cleanup() 149 150 serverURL, cleanup := runRESTServer(ctx, t, dir) 151 defer cleanup() 152 153 newTestSuite(ctx, t, serverURL, false).RunBenchmarks(t) 154 }