| 
									
										
										
										
											2015-08-16 22:27:07 +02:00
										 |  |  | // +build !openbsd | 
					
						
							| 
									
										
										
										
											2018-03-04 13:30:06 +00:00
										 |  |  | // +build !solaris | 
					
						
							| 
									
										
										
										
											2015-08-17 19:40:34 +02:00
										 |  |  | // +build !windows | 
					
						
							| 
									
										
										
										
											2015-08-16 22:27:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | package fuse | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"math/rand" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	"golang.org/x/net/context" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-23 14:21:03 +02:00
										 |  |  | 	"github.com/restic/restic/internal/repository" | 
					
						
							| 
									
										
										
										
											2017-07-24 17:42:25 +02:00
										 |  |  | 	"github.com/restic/restic/internal/restic" | 
					
						
							| 
									
										
										
										
											2016-08-21 17:46:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 	"bazil.org/fuse" | 
					
						
							| 
									
										
										
										
											2017-06-18 16:29:00 +02:00
										 |  |  | 	"bazil.org/fuse/fs" | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest "github.com/restic/restic/internal/test" | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | func testRead(t testing.TB, f *file, offset, length int, data []byte) { | 
					
						
							|  |  |  | 	ctx, cancel := context.WithCancel(context.Background()) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	req := &fuse.ReadRequest{ | 
					
						
							|  |  |  | 		Offset: int64(offset), | 
					
						
							|  |  |  | 		Size:   length, | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	resp := &fuse.ReadResponse{ | 
					
						
							|  |  |  | 		Data: data, | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, f.Read(ctx, req, resp)) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | func firstSnapshotID(t testing.TB, repo restic.Repository) (first restic.ID) { | 
					
						
							| 
									
										
										
										
											2018-01-21 17:25:36 +01:00
										 |  |  | 	err := repo.List(context.TODO(), restic.SnapshotFile, func(id restic.ID, size int64) error { | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 		if first.IsNull() { | 
					
						
							|  |  |  | 			first = id | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-01-21 17:25:36 +01:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-21 17:25:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	return first | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | func loadFirstSnapshot(t testing.TB, repo restic.Repository) *restic.Snapshot { | 
					
						
							|  |  |  | 	id := firstSnapshotID(t, repo) | 
					
						
							| 
									
										
										
										
											2017-06-05 23:56:59 +02:00
										 |  |  | 	sn, err := restic.LoadSnapshot(context.TODO(), repo, id) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	return sn | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | func loadTree(t testing.TB, repo restic.Repository, id restic.ID) *restic.Tree { | 
					
						
							| 
									
										
										
										
											2017-06-05 23:56:59 +02:00
										 |  |  | 	tree, err := repo.LoadTree(context.TODO(), id) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	return tree | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | func TestFuseFile(t *testing.T) { | 
					
						
							|  |  |  | 	repo, cleanup := repository.TestRepository(t) | 
					
						
							|  |  |  | 	defer cleanup() | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	ctx, cancel := context.WithCancel(context.Background()) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	timestamp, err := time.Parse(time.RFC3339, "2017-01-24T10:42:56+01:00") | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	restic.TestCreateSnapshot(t, repo, timestamp, 2, 0.1) | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	sn := loadFirstSnapshot(t, repo) | 
					
						
							|  |  |  | 	tree := loadTree(t, repo, *sn.Tree) | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	var content restic.IDs | 
					
						
							|  |  |  | 	for _, node := range tree.Nodes { | 
					
						
							|  |  |  | 		content = append(content, node.Content...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	t.Logf("tree loaded, content: %v", content) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		filesize uint64 | 
					
						
							|  |  |  | 		memfile  []byte | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	for _, id := range content { | 
					
						
							| 
									
										
										
										
											2018-01-12 01:20:12 -05:00
										 |  |  | 		size, found := repo.LookupBlobSize(id, restic.DataBlob) | 
					
						
							|  |  |  | 		rtest.Assert(t, found, "Expected to find blob id %v", id) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 		filesize += uint64(size) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		buf := restic.NewBlobBuffer(int(size)) | 
					
						
							| 
									
										
										
										
											2017-06-05 23:56:59 +02:00
										 |  |  | 		n, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, buf) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 		rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if uint(n) != size { | 
					
						
							|  |  |  | 			t.Fatalf("not enough bytes read for id %v: want %v, got %v", id.Str(), size, n) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 		if uint(len(buf)) != size { | 
					
						
							|  |  |  | 			t.Fatalf("buffer has wrong length for id %v: want %v, got %v", id.Str(), size, len(buf)) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		memfile = append(memfile, buf...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 	t.Logf("filesize is %v, memfile has size %v", filesize, len(memfile)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 	node := &restic.Node{ | 
					
						
							|  |  |  | 		Name:    "foo", | 
					
						
							|  |  |  | 		Inode:   23, | 
					
						
							|  |  |  | 		Mode:    0742, | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 		Size:    filesize, | 
					
						
							|  |  |  | 		Content: content, | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-18 16:29:00 +02:00
										 |  |  | 	root := &Root{ | 
					
						
							|  |  |  | 		blobSizeCache: NewBlobSizeCache(context.TODO(), repo.Index()), | 
					
						
							|  |  |  | 		repo:          repo, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t.Logf("blob cache has %d entries", len(root.blobSizeCache.m)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	inode := fs.GenerateDynamicInode(1, "foo") | 
					
						
							|  |  |  | 	f, err := newFile(context.TODO(), root, inode, node) | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, err) | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	attr := fuse.Attr{} | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, f.Attr(ctx, &attr)) | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.Equals(t, inode, attr.Inode) | 
					
						
							|  |  |  | 	rtest.Equals(t, node.Mode, attr.Mode) | 
					
						
							|  |  |  | 	rtest.Equals(t, node.Size, attr.Size) | 
					
						
							|  |  |  | 	rtest.Equals(t, (node.Size/uint64(attr.BlockSize))+1, attr.Blocks) | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < 200; i++ { | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 		offset := rand.Intn(int(filesize)) | 
					
						
							|  |  |  | 		length := rand.Intn(int(filesize)-offset) + 100 | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		b := memfile[offset : offset+length] | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-03 14:03:43 +02:00
										 |  |  | 		buf := make([]byte, length) | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-03 14:03:43 +02:00
										 |  |  | 		testRead(t, f, offset, length, buf) | 
					
						
							|  |  |  | 		if !bytes.Equal(b, buf) { | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 			t.Errorf("test %d failed, wrong data returned (offset %v, length %v)", i, offset, length) | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-24 11:41:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-02 15:06:39 +02:00
										 |  |  | 	rtest.OK(t, f.Release(ctx, nil)) | 
					
						
							| 
									
										
										
										
											2015-07-26 16:43:42 +02:00
										 |  |  | } |