| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | package test | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	crand "crypto/rand" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"io" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"math/rand" | 
					
						
							|  |  |  | 	"reflect" | 
					
						
							|  |  |  | 	"sort" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/restic/restic/backend" | 
					
						
							|  |  |  | 	. "github.com/restic/restic/test" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // CreateFn is a function that creates a temporary repository for the tests. | 
					
						
							|  |  |  | var CreateFn func() (backend.Backend, error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // OpenFn is a function that opens a previously created temporary repository. | 
					
						
							|  |  |  | var OpenFn func() (backend.Backend, error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // CleanupFn removes temporary files and directories created during the tests. | 
					
						
							|  |  |  | var CleanupFn func() error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var but backend.Backend // backendUnderTest | 
					
						
							|  |  |  | var butInitialized bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func open(t testing.TB) backend.Backend { | 
					
						
							|  |  |  | 	if OpenFn == nil { | 
					
						
							|  |  |  | 		t.Fatal("OpenFn not set") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if CreateFn == nil { | 
					
						
							|  |  |  | 		t.Fatalf("CreateFn not set") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !butInitialized { | 
					
						
							|  |  |  | 		be, err := CreateFn() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("Create returned unexpected error: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		but = be | 
					
						
							|  |  |  | 		butInitialized = true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if but == nil { | 
					
						
							|  |  |  | 		var err error | 
					
						
							|  |  |  | 		but, err = OpenFn() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("Open returned unexpected error: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return but | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func close(t testing.TB) { | 
					
						
							|  |  |  | 	if but == nil { | 
					
						
							|  |  |  | 		t.Fatalf("trying to close non-existing backend") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err := but.Close() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("Close returned unexpected error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	but = nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestCreate creates a backend. | 
					
						
							|  |  |  | func TestCreate(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 	if CreateFn == nil { | 
					
						
							|  |  |  | 		t.Fatalf("CreateFn not set!") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	be, err := CreateFn() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Printf("foo\n") | 
					
						
							|  |  |  | 		t.Fatalf("Create returned error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	butInitialized = true | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = be.Close() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("Close returned error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestOpen opens a previously created backend. | 
					
						
							|  |  |  | func TestOpen(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 	if OpenFn == nil { | 
					
						
							|  |  |  | 		t.Fatalf("OpenFn not set!") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	be, err := OpenFn() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("Open returned error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = be.Close() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("Close returned error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestCreateWithConfig tests that creating a backend in a location which already | 
					
						
							| 
									
										
										
										
											2016-01-23 18:07:15 +01:00
										 |  |  | // has a config file fails. | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | func TestCreateWithConfig(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 18:07:15 +01:00
										 |  |  | 	if CreateFn == nil { | 
					
						
							|  |  |  | 		t.Fatalf("CreateFn not set") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b := open(t) | 
					
						
							|  |  |  | 	defer close(t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// save a config | 
					
						
							|  |  |  | 	store(t, b, backend.Config, []byte("test config")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// now create the backend again, this must fail | 
					
						
							|  |  |  | 	_, err := CreateFn() | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		t.Fatalf("expected error not found for creating a backend with an existing config file") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// remove config | 
					
						
							|  |  |  | 	err = b.Remove(backend.Config, "") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("unexpected error removing config: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestLocation tests that a location string is returned. | 
					
						
							|  |  |  | func TestLocation(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 	b := open(t) | 
					
						
							|  |  |  | 	defer close(t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	l := b.Location() | 
					
						
							|  |  |  | 	if l == "" { | 
					
						
							|  |  |  | 		t.Fatalf("invalid location string %q", l) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestConfig saves and loads a config from the backend. | 
					
						
							|  |  |  | func TestConfig(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 	b := open(t) | 
					
						
							|  |  |  | 	defer close(t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var testString = "Config" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// create config and read it back | 
					
						
							|  |  |  | 	_, err := b.GetReader(backend.Config, "", 0, 0) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		t.Fatalf("did not get expected error for non-existing config") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	blob, err := b.Create() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("Create() error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = blob.Write([]byte(testString)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("Write() error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = blob.Finalize(backend.Config, "") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("Finalize() error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// try accessing the config with different names, should all return the | 
					
						
							|  |  |  | 	// same config | 
					
						
							|  |  |  | 	for _, name := range []string{"", "foo", "bar", "0000000000000000000000000000000000000000000000000000000000000000"} { | 
					
						
							|  |  |  | 		rd, err := b.GetReader(backend.Config, name, 0, 0) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("unable to read config with name %q: %v", name, err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		buf, err := ioutil.ReadAll(rd) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("read config error: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err = rd.Close() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("close error: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if string(buf) != testString { | 
					
						
							|  |  |  | 			t.Fatalf("wrong data returned, want %q, got %q", testString, string(buf)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestGetReader tests various ways the GetReader function can be called. | 
					
						
							|  |  |  | func TestGetReader(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 	b := open(t) | 
					
						
							|  |  |  | 	defer close(t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length := rand.Intn(1<<24) + 2000 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data := make([]byte, length) | 
					
						
							|  |  |  | 	_, err := io.ReadFull(crand.Reader, data) | 
					
						
							|  |  |  | 	OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	blob, err := b.Create() | 
					
						
							|  |  |  | 	OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	id := backend.Hash(data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = blob.Write([]byte(data)) | 
					
						
							|  |  |  | 	OK(t, err) | 
					
						
							|  |  |  | 	OK(t, blob.Finalize(backend.Data, id.String())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < 500; i++ { | 
					
						
							|  |  |  | 		l := rand.Intn(length + 2000) | 
					
						
							|  |  |  | 		o := rand.Intn(length + 2000) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		d := data | 
					
						
							|  |  |  | 		if o < len(d) { | 
					
						
							|  |  |  | 			d = d[o:] | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			o = len(d) | 
					
						
							|  |  |  | 			d = d[:0] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if l > 0 && l < len(d) { | 
					
						
							|  |  |  | 			d = d[:l] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		rd, err := b.GetReader(backend.Data, id.String(), uint(o), uint(l)) | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 		buf, err := ioutil.ReadAll(rd) | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if !bytes.Equal(buf, d) { | 
					
						
							|  |  |  | 			t.Fatalf("data not equal") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	OK(t, b.Remove(backend.Data, id.String())) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestLoad tests the backend's Load function. | 
					
						
							|  |  |  | func TestLoad(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 	b := open(t) | 
					
						
							|  |  |  | 	defer close(t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err := b.Load(backend.Handle{}, nil, 0) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		t.Fatalf("Load() did not return an error for invalid handle") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = b.Load(backend.Handle{Type: backend.Data, Name: "foobar"}, nil, 0) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		t.Fatalf("Load() did not return an error for non-existing blob") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length := rand.Intn(1<<24) + 2000 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data := make([]byte, length) | 
					
						
							|  |  |  | 	_, err = io.ReadFull(crand.Reader, data) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("reading random data failed: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	id := backend.Hash(data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	blob, err := b.Create() | 
					
						
							|  |  |  | 	OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = blob.Write([]byte(data)) | 
					
						
							|  |  |  | 	OK(t, err) | 
					
						
							|  |  |  | 	OK(t, blob.Finalize(backend.Data, id.String())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < 500; i++ { | 
					
						
							|  |  |  | 		l := rand.Intn(length + 2000) | 
					
						
							|  |  |  | 		o := rand.Intn(length + 2000) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		d := data | 
					
						
							|  |  |  | 		if o < len(d) { | 
					
						
							|  |  |  | 			d = d[o:] | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			o = len(d) | 
					
						
							|  |  |  | 			d = d[:0] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if l > 0 && l < len(d) { | 
					
						
							|  |  |  | 			d = d[:l] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		buf := make([]byte, l) | 
					
						
							|  |  |  | 		h := backend.Handle{Type: backend.Data, Name: id.String()} | 
					
						
							|  |  |  | 		n, err := b.Load(h, buf, int64(o)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// if we requested data beyond the end of the file, ignore | 
					
						
							|  |  |  | 		// ErrUnexpectedEOF error | 
					
						
							|  |  |  | 		if l > len(d) && err == io.ErrUnexpectedEOF { | 
					
						
							|  |  |  | 			err = nil | 
					
						
							|  |  |  | 			buf = buf[:len(d)] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Errorf("Load(%d, %d): unexpected error: %v", len(buf), int64(o), err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if n != len(buf) { | 
					
						
							|  |  |  | 			t.Errorf("Load(%d, %d): wrong length returned, want %d, got %d", | 
					
						
							|  |  |  | 				len(buf), int64(o), len(buf), n) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		buf = buf[:n] | 
					
						
							|  |  |  | 		if !bytes.Equal(buf, d) { | 
					
						
							|  |  |  | 			t.Errorf("Load(%d, %d) returned wrong bytes", len(buf), int64(o)) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	OK(t, b.Remove(backend.Data, id.String())) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestWrite tests writing data to the backend. | 
					
						
							|  |  |  | func TestWrite(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 	b := open(t) | 
					
						
							|  |  |  | 	defer close(t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	length := rand.Intn(1<<23) + 2000 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data := make([]byte, length) | 
					
						
							|  |  |  | 	_, err := io.ReadFull(crand.Reader, data) | 
					
						
							|  |  |  | 	OK(t, err) | 
					
						
							|  |  |  | 	id := backend.Hash(data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < 10; i++ { | 
					
						
							|  |  |  | 		blob, err := b.Create() | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		o := 0 | 
					
						
							|  |  |  | 		for o < len(data) { | 
					
						
							|  |  |  | 			l := rand.Intn(len(data) - o) | 
					
						
							|  |  |  | 			if len(data)-o < 20 { | 
					
						
							|  |  |  | 				l = len(data) - o | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			n, err := blob.Write(data[o : o+l]) | 
					
						
							|  |  |  | 			OK(t, err) | 
					
						
							|  |  |  | 			if n != l { | 
					
						
							|  |  |  | 				t.Fatalf("wrong number of bytes written, want %v, got %v", l, n) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			o += l | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		name := fmt.Sprintf("%s-%d", id, i) | 
					
						
							|  |  |  | 		OK(t, blob.Finalize(backend.Data, name)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		rd, err := b.GetReader(backend.Data, name, 0, 0) | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		buf, err := ioutil.ReadAll(rd) | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if len(buf) != len(data) { | 
					
						
							|  |  |  | 			t.Fatalf("number of bytes does not match, want %v, got %v", len(data), len(buf)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if !bytes.Equal(buf, data) { | 
					
						
							|  |  |  | 			t.Fatalf("data not equal") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		err = b.Remove(backend.Data, name) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Fatalf("error removing item: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var testStrings = []struct { | 
					
						
							|  |  |  | 	id   string | 
					
						
							|  |  |  | 	data string | 
					
						
							|  |  |  | }{ | 
					
						
							|  |  |  | 	{"c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2", "foobar"}, | 
					
						
							|  |  |  | 	{"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, | 
					
						
							|  |  |  | 	{"cc5d46bdb4991c6eae3eb739c9c8a7a46fe9654fab79c47b4fe48383b5b25e1c", "foo/bar"}, | 
					
						
							|  |  |  | 	{"4e54d2c721cbdb730f01b10b62dec622962b36966ec685880effa63d71c808f2", "foo/../../baz"}, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func store(t testing.TB, b backend.Backend, tpe backend.Type, data []byte) { | 
					
						
							|  |  |  | 	id := backend.Hash(data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	blob, err := b.Create() | 
					
						
							|  |  |  | 	OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err = blob.Write([]byte(data)) | 
					
						
							|  |  |  | 	OK(t, err) | 
					
						
							|  |  |  | 	OK(t, blob.Finalize(tpe, id.String())) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func read(t testing.TB, rd io.Reader, expectedData []byte) { | 
					
						
							|  |  |  | 	buf, err := ioutil.ReadAll(rd) | 
					
						
							|  |  |  | 	OK(t, err) | 
					
						
							|  |  |  | 	if expectedData != nil { | 
					
						
							|  |  |  | 		Equals(t, expectedData, buf) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestBackend tests all functions of the backend. | 
					
						
							|  |  |  | func TestBackend(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 	b := open(t) | 
					
						
							|  |  |  | 	defer close(t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, tpe := range []backend.Type{ | 
					
						
							|  |  |  | 		backend.Data, backend.Key, backend.Lock, | 
					
						
							|  |  |  | 		backend.Snapshot, backend.Index, | 
					
						
							|  |  |  | 	} { | 
					
						
							|  |  |  | 		// detect non-existing files | 
					
						
							|  |  |  | 		for _, test := range testStrings { | 
					
						
							|  |  |  | 			id, err := backend.ParseID(test.id) | 
					
						
							|  |  |  | 			OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// test if blob is already in repository | 
					
						
							|  |  |  | 			ret, err := b.Test(tpe, id.String()) | 
					
						
							|  |  |  | 			OK(t, err) | 
					
						
							|  |  |  | 			Assert(t, !ret, "blob was found to exist before creating") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// try to open not existing blob | 
					
						
							|  |  |  | 			_, err = b.GetReader(tpe, id.String(), 0, 0) | 
					
						
							|  |  |  | 			Assert(t, err != nil, "blob data could be extracted before creation") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// try to read not existing blob | 
					
						
							|  |  |  | 			_, err = b.GetReader(tpe, id.String(), 0, 1) | 
					
						
							|  |  |  | 			Assert(t, err != nil, "blob reader could be obtained before creation") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// try to get string out, should fail | 
					
						
							|  |  |  | 			ret, err = b.Test(tpe, id.String()) | 
					
						
							|  |  |  | 			OK(t, err) | 
					
						
							|  |  |  | 			Assert(t, !ret, "id %q was found (but should not have)", test.id) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// add files | 
					
						
							|  |  |  | 		for _, test := range testStrings { | 
					
						
							|  |  |  | 			store(t, b, tpe, []byte(test.data)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// test GetReader() | 
					
						
							|  |  |  | 			rd, err := b.GetReader(tpe, test.id, 0, uint(len(test.data))) | 
					
						
							|  |  |  | 			OK(t, err) | 
					
						
							|  |  |  | 			Assert(t, rd != nil, "GetReader() returned nil") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			read(t, rd, []byte(test.data)) | 
					
						
							|  |  |  | 			OK(t, rd.Close()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// try to read it out with an offset and a length | 
					
						
							|  |  |  | 			start := 1 | 
					
						
							|  |  |  | 			end := len(test.data) - 2 | 
					
						
							|  |  |  | 			length := end - start | 
					
						
							|  |  |  | 			rd, err = b.GetReader(tpe, test.id, uint(start), uint(length)) | 
					
						
							|  |  |  | 			OK(t, err) | 
					
						
							|  |  |  | 			Assert(t, rd != nil, "GetReader() returned nil") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			read(t, rd, []byte(test.data[start:end])) | 
					
						
							|  |  |  | 			OK(t, rd.Close()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// test adding the first file again | 
					
						
							|  |  |  | 		test := testStrings[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// create blob | 
					
						
							|  |  |  | 		blob, err := b.Create() | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_, err = blob.Write([]byte(test.data)) | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 		err = blob.Finalize(tpe, test.id) | 
					
						
							|  |  |  | 		Assert(t, err != nil, "expected error, got %v", err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// remove and recreate | 
					
						
							|  |  |  | 		err = b.Remove(tpe, test.id) | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// test that the blob is gone | 
					
						
							|  |  |  | 		ok, err := b.Test(tpe, test.id) | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 		Assert(t, ok == false, "removed blob still present") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// create blob | 
					
						
							|  |  |  | 		blob, err = b.Create() | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_, err = io.Copy(blob, bytes.NewReader([]byte(test.data))) | 
					
						
							|  |  |  | 		OK(t, err) | 
					
						
							|  |  |  | 		OK(t, blob.Finalize(tpe, test.id)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// list items | 
					
						
							|  |  |  | 		IDs := backend.IDs{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for _, test := range testStrings { | 
					
						
							|  |  |  | 			id, err := backend.ParseID(test.id) | 
					
						
							|  |  |  | 			OK(t, err) | 
					
						
							|  |  |  | 			IDs = append(IDs, id) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		list := backend.IDs{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for s := range b.List(tpe, nil) { | 
					
						
							|  |  |  | 			list = append(list, ParseID(s)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if len(IDs) != len(list) { | 
					
						
							|  |  |  | 			t.Fatalf("wrong number of IDs returned: want %d, got %d", len(IDs), len(list)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		sort.Sort(IDs) | 
					
						
							|  |  |  | 		sort.Sort(list) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if !reflect.DeepEqual(IDs, list) { | 
					
						
							|  |  |  | 			t.Fatalf("lists aren't equal, want:\n  %v\n  got:\n%v\n", IDs, list) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// remove content if requested | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | 		if TestCleanupTempDirs { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 			for _, test := range testStrings { | 
					
						
							|  |  |  | 				id, err := backend.ParseID(test.id) | 
					
						
							|  |  |  | 				OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				found, err := b.Test(tpe, id.String()) | 
					
						
							|  |  |  | 				OK(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				OK(t, b.Remove(tpe, id.String())) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				found, err = b.Test(tpe, id.String()) | 
					
						
							|  |  |  | 				OK(t, err) | 
					
						
							|  |  |  | 				Assert(t, !found, fmt.Sprintf("id %q not found after removal", id)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestDelete tests the Delete function. | 
					
						
							|  |  |  | func TestDelete(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 	b := open(t) | 
					
						
							|  |  |  | 	defer close(t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	be, ok := b.(backend.Deleter) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err := be.Delete() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("error deleting backend: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | // TestCleanup runs the cleanup function after all tests are run. | 
					
						
							|  |  |  | func TestCleanup(t testing.TB) { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 	if CleanupFn == nil { | 
					
						
							|  |  |  | 		t.Log("CleanupFn function not set") | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-23 19:12:02 +01:00
										 |  |  | 	if !TestCleanupTempDirs { | 
					
						
							| 
									
										
										
										
											2016-01-23 17:08:03 +01:00
										 |  |  | 		t.Logf("not cleaning up backend") | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err := CleanupFn() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("Cleanup returned error: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |