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  }