1package dump 2 3import ( 4 "archive/tar" 5 "bytes" 6 "fmt" 7 "io" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/restic/restic/internal/fs" 16) 17 18func TestWriteTar(t *testing.T) { 19 WriteTest(t, WriteTar, checkTar) 20} 21 22func checkTar(t *testing.T, testDir string, srcTar *bytes.Buffer) error { 23 tr := tar.NewReader(srcTar) 24 25 fileNumber := 0 26 tarFiles := 0 27 28 err := filepath.Walk(testDir, func(path string, info os.FileInfo, err error) error { 29 if err != nil { 30 return err 31 } 32 if info.Name() != filepath.Base(testDir) { 33 fileNumber++ 34 } 35 return nil 36 }) 37 if err != nil { 38 return err 39 } 40 41 for { 42 hdr, err := tr.Next() 43 if err == io.EOF { 44 break 45 } 46 if err != nil { 47 t.Fatal(err) 48 } 49 50 matchPath := filepath.Join(testDir, hdr.Name) 51 match, err := os.Lstat(matchPath) 52 if err != nil { 53 return err 54 } 55 56 // check metadata, tar header contains time rounded to seconds 57 fileTime := match.ModTime().Round(time.Second) 58 tarTime := hdr.ModTime 59 if !fileTime.Equal(tarTime) { 60 return fmt.Errorf("modTime does not match, got: %s, want: %s", fileTime, tarTime) 61 } 62 63 if os.FileMode(hdr.Mode).Perm() != match.Mode().Perm() || os.FileMode(hdr.Mode)&^os.ModePerm != 0 { 64 return fmt.Errorf("mode does not match, got: %v, want: %v", os.FileMode(hdr.Mode), match.Mode()) 65 } 66 67 switch hdr.Typeflag { 68 case tar.TypeDir: 69 // this is a folder 70 if hdr.Name == "." { 71 // we don't need to check the root folder 72 continue 73 } 74 75 filebase := filepath.ToSlash(match.Name()) 76 if filepath.Base(hdr.Name) != filebase { 77 return fmt.Errorf("foldernames don't match got %v want %v", filepath.Base(hdr.Name), filebase) 78 } 79 if !strings.HasSuffix(hdr.Name, "/") { 80 return fmt.Errorf("foldernames must end with separator got %v", hdr.Name) 81 } 82 case tar.TypeSymlink: 83 target, err := fs.Readlink(matchPath) 84 if err != nil { 85 return err 86 } 87 if target != hdr.Linkname { 88 return fmt.Errorf("symlink target does not match, got %s want %s", target, hdr.Linkname) 89 } 90 default: 91 if match.Size() != hdr.Size { 92 return fmt.Errorf("size does not match got %v want %v", hdr.Size, match.Size()) 93 } 94 contentsFile, err := ioutil.ReadFile(matchPath) 95 if err != nil { 96 t.Fatal(err) 97 } 98 contentsTar := &bytes.Buffer{} 99 _, err = io.Copy(contentsTar, tr) 100 if err != nil { 101 t.Fatal(err) 102 } 103 if contentsTar.String() != string(contentsFile) { 104 return fmt.Errorf("contents does not match, got %s want %s", contentsTar, contentsFile) 105 } 106 } 107 tarFiles++ 108 } 109 110 if tarFiles != fileNumber { 111 return fmt.Errorf("not the same amount of files got %v want %v", tarFiles, fileNumber) 112 } 113 114 return nil 115} 116