Merge pull request #960 from restic/travis-run-tests-against-s3
Enable CI tests against AWS S3
This commit is contained in:
commit
1c9159d6a0
9 changed files with 82 additions and 21 deletions
|
@ -150,6 +150,22 @@ func (env *TravisEnvironment) RunTests() error {
|
||||||
|
|
||||||
env.env["GOPATH"] = cwd + ":" + filepath.Join(cwd, "vendor")
|
env.env["GOPATH"] = cwd + ":" + filepath.Join(cwd, "vendor")
|
||||||
|
|
||||||
|
// ensure that the following tests cannot be silently skipped on Travis
|
||||||
|
ensureTests := []string{
|
||||||
|
"restic/backend/rest.TestBackendREST",
|
||||||
|
"restic/backend/sftp.TestBackendSFTP",
|
||||||
|
"restic/backend/s3.TestBackendMinio",
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the test s3 repository is available, make sure that the test is not skipped
|
||||||
|
if os.Getenv("RESTIC_TEST_S3_REPOSITORY") != "" {
|
||||||
|
ensureTests = append(ensureTests, "restic/backend/s3.TestBackendS3")
|
||||||
|
} else {
|
||||||
|
msg("S3 repository not available\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
env.env["RESTIC_TEST_DISALLOW_SKIP"] = strings.Join(ensureTests, ",")
|
||||||
|
|
||||||
if *runCrossCompile {
|
if *runCrossCompile {
|
||||||
// compile for all target architectures with tags
|
// compile for all target architectures with tags
|
||||||
for _, tags := range []string{"release", "debug"} {
|
for _, tags := range []string{"release", "debug"} {
|
||||||
|
|
|
@ -60,7 +60,13 @@ func runRESTServer(ctx context.Context, t testing.TB, dir string) func() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBackend(t *testing.T) {
|
func TestBackendREST(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if t.Skipped() {
|
||||||
|
SkipDisallowed(t, "restic/backend/rest.TestBackendREST")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,12 @@ func newCredentials(t testing.TB) (key, secret string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBackendMinio(t *testing.T) {
|
func TestBackendMinio(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if t.Skipped() {
|
||||||
|
SkipDisallowed(t, "restic/backend/s3.TestBackendMinio")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// try to find a minio binary
|
// try to find a minio binary
|
||||||
_, err := exec.LookPath("minio")
|
_, err := exec.LookPath("minio")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -169,7 +175,6 @@ func TestBackendMinio(t *testing.T) {
|
||||||
cfg.stopServer()
|
cfg.stopServer()
|
||||||
}
|
}
|
||||||
if cfg.removeTempdir != nil {
|
if cfg.removeTempdir != nil {
|
||||||
t.Logf("removeTempdir %v", config)
|
|
||||||
cfg.removeTempdir()
|
cfg.removeTempdir()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -180,6 +185,12 @@ func TestBackendMinio(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBackendS3(t *testing.T) {
|
func TestBackendS3(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if t.Skipped() {
|
||||||
|
SkipDisallowed(t, "restic/backend/s3.TestBackendS3")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
vars := []string{
|
vars := []string{
|
||||||
"RESTIC_TEST_S3_KEY",
|
"RESTIC_TEST_S3_KEY",
|
||||||
"RESTIC_TEST_S3_SECRET",
|
"RESTIC_TEST_S3_SECRET",
|
||||||
|
|
|
@ -29,7 +29,13 @@ func findSFTPServerBinary() string {
|
||||||
|
|
||||||
var sftpServer = findSFTPServerBinary()
|
var sftpServer = findSFTPServerBinary()
|
||||||
|
|
||||||
func TestBackend(t *testing.T) {
|
func TestBackendSFTP(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
if t.Skipped() {
|
||||||
|
SkipDisallowed(t, "restic/backend/sftp.TestBackendSFTP")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if sftpServer == "" {
|
if sftpServer == "" {
|
||||||
t.Skip("sftp server binary not found")
|
t.Skip("sftp server binary not found")
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,7 +277,8 @@ func BackendTestLoad(t testing.TB, s *Suite) {
|
||||||
|
|
||||||
type errorCloser struct {
|
type errorCloser struct {
|
||||||
io.Reader
|
io.Reader
|
||||||
t testing.TB
|
size int64
|
||||||
|
t testing.TB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec errorCloser) Close() error {
|
func (ec errorCloser) Close() error {
|
||||||
|
@ -285,6 +286,10 @@ func (ec errorCloser) Close() error {
|
||||||
return errors.New("forbidden method close was called")
|
return errors.New("forbidden method close was called")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec errorCloser) Size() int64 {
|
||||||
|
return ec.size
|
||||||
|
}
|
||||||
|
|
||||||
// BackendTestSave tests saving data in the backend.
|
// BackendTestSave tests saving data in the backend.
|
||||||
func BackendTestSave(t testing.TB, s *Suite) {
|
func BackendTestSave(t testing.TB, s *Suite) {
|
||||||
b := s.open(t)
|
b := s.open(t)
|
||||||
|
@ -354,7 +359,7 @@ func BackendTestSave(t testing.TB, s *Suite) {
|
||||||
|
|
||||||
// wrap the tempfile in an errorCloser, so we can detect if the backend
|
// wrap the tempfile in an errorCloser, so we can detect if the backend
|
||||||
// closes the reader
|
// closes the reader
|
||||||
err = b.Save(h, errorCloser{t: t, Reader: tmpfile})
|
err = b.Save(h, errorCloser{t: t, size: int64(length), Reader: tmpfile})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,22 @@ package test
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
TestPassword = getStringVar("RESTIC_TEST_PASSWORD", "geheim")
|
TestPassword = getStringVar("RESTIC_TEST_PASSWORD", "geheim")
|
||||||
TestCleanupTempDirs = getBoolVar("RESTIC_TEST_CLEANUP", true)
|
TestCleanupTempDirs = getBoolVar("RESTIC_TEST_CLEANUP", true)
|
||||||
TestTempDir = getStringVar("RESTIC_TEST_TMPDIR", "")
|
TestTempDir = getStringVar("RESTIC_TEST_TMPDIR", "")
|
||||||
RunIntegrationTest = getBoolVar("RESTIC_TEST_INTEGRATION", true)
|
RunIntegrationTest = getBoolVar("RESTIC_TEST_INTEGRATION", true)
|
||||||
RunFuseTest = getBoolVar("RESTIC_TEST_FUSE", true)
|
RunFuseTest = getBoolVar("RESTIC_TEST_FUSE", true)
|
||||||
TestSFTPPath = getStringVar("RESTIC_TEST_SFTPPATH", "/usr/lib/ssh:/usr/lib/openssh:/usr/libexec")
|
TestSFTPPath = getStringVar("RESTIC_TEST_SFTPPATH", "/usr/lib/ssh:/usr/lib/openssh:/usr/libexec")
|
||||||
TestWalkerPath = getStringVar("RESTIC_TEST_PATH", ".")
|
TestWalkerPath = getStringVar("RESTIC_TEST_PATH", ".")
|
||||||
BenchArchiveDirectory = getStringVar("RESTIC_BENCH_DIR", ".")
|
BenchArchiveDirectory = getStringVar("RESTIC_BENCH_DIR", ".")
|
||||||
TestS3Server = getStringVar("RESTIC_TEST_S3_SERVER", "")
|
TestS3Server = getStringVar("RESTIC_TEST_S3_SERVER", "")
|
||||||
TestRESTServer = getStringVar("RESTIC_TEST_REST_SERVER", "")
|
TestRESTServer = getStringVar("RESTIC_TEST_REST_SERVER", "")
|
||||||
|
TestIntegrationDisallowSkip = getStringVar("RESTIC_TEST_DISALLOW_SKIP", "")
|
||||||
)
|
)
|
||||||
|
|
||||||
func getStringVar(name, defaultValue string) string {
|
func getStringVar(name, defaultValue string) string {
|
||||||
|
@ -40,3 +43,15 @@ func getBoolVar(name string, defaultValue bool) bool {
|
||||||
|
|
||||||
return defaultValue
|
return defaultValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SkipDisallowed fails the test if it needs to run. The environment
|
||||||
|
// variable RESTIC_TEST_DISALLOW_SKIP contains a comma-separated list of test
|
||||||
|
// names that must be run. If name is in this list, the test is marked as
|
||||||
|
// failed.
|
||||||
|
func SkipDisallowed(t testing.TB, name string) {
|
||||||
|
for _, s := range strings.Split(TestIntegrationDisallowSkip, ",") {
|
||||||
|
if s == name {
|
||||||
|
t.Fatalf("test %v is in list of tests that need to run ($RESTIC_TEST_DISALLOW_SKIP)", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ func (c Client) MakeBucket(bucketName string, location string) (err error) {
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
err := httpRespToErrorResponse(resp, bucketName, "")
|
err := httpRespToErrorResponse(resp, bucketName, "")
|
||||||
errResp := ToErrorResponse(err)
|
errResp := ToErrorResponse(err)
|
||||||
if errResp.Code == "InvalidRegion" && errResp.Region != "" {
|
if resp.StatusCode == http.StatusBadRequest && errResp.Region != "" {
|
||||||
// Fetch bucket region found in headers
|
// Fetch bucket region found in headers
|
||||||
// of S3 error response, attempt bucket
|
// of S3 error response, attempt bucket
|
||||||
// create again.
|
// create again.
|
||||||
|
|
|
@ -157,11 +157,13 @@ func hashCopyN(hashAlgorithms map[string]hash.Hash, hashSums map[string][]byte,
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err == nil && size == partSize {
|
||||||
for k, v := range hashAlgorithms {
|
for k, v := range hashAlgorithms {
|
||||||
hashSums[k] = v.Sum(nil)
|
hashSums[k] = v.Sum(nil)
|
||||||
|
}
|
||||||
|
return size, nil
|
||||||
}
|
}
|
||||||
return size, err
|
return 0, ErrUnexpectedEOF(size, partSize, "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// getUploadID - fetch upload id if already present for an object name
|
// getUploadID - fetch upload id if already present for an object name
|
||||||
|
|
2
vendor/src/github.com/minio/minio-go/api.go
vendored
2
vendor/src/github.com/minio/minio-go/api.go
vendored
|
@ -553,7 +553,7 @@ func (c Client) executeMethod(method string, metadata requestMetadata) (res *htt
|
||||||
// Bucket region if set in error response and the error
|
// Bucket region if set in error response and the error
|
||||||
// code dictates invalid region, we can retry the request
|
// code dictates invalid region, we can retry the request
|
||||||
// with the new region.
|
// with the new region.
|
||||||
if errResponse.Region != "" && res.StatusCode == http.StatusBadRequest {
|
if res.StatusCode == http.StatusBadRequest && errResponse.Region != "" {
|
||||||
c.bucketLocCache.Set(metadata.bucketName, errResponse.Region)
|
c.bucketLocCache.Set(metadata.bucketName, errResponse.Region)
|
||||||
continue // Retry.
|
continue // Retry.
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue