github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/archive/tar/tar_test.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package tar 6 7 import ( 8 "bytes" 9 "io/ioutil" 10 "os" 11 "reflect" 12 "testing" 13 "time" 14 ) 15 16 func TestFileInfoHeader(t *testing.T) { 17 fi, err := os.Stat("testdata/small.txt") 18 if err != nil { 19 t.Fatal(err) 20 } 21 h, err := FileInfoHeader(fi, "") 22 if err != nil { 23 t.Fatalf("FileInfoHeader: %v", err) 24 } 25 if g, e := h.Name, "small.txt"; g != e { 26 t.Errorf("Name = %q; want %q", g, e) 27 } 28 if g, e := h.Mode, int64(fi.Mode().Perm())|c_ISREG; g != e { 29 t.Errorf("Mode = %#o; want %#o", g, e) 30 } 31 if g, e := h.Size, int64(5); g != e { 32 t.Errorf("Size = %v; want %v", g, e) 33 } 34 if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) { 35 t.Errorf("ModTime = %v; want %v", g, e) 36 } 37 } 38 39 func TestFileInfoHeaderDir(t *testing.T) { 40 fi, err := os.Stat("testdata") 41 if err != nil { 42 t.Fatal(err) 43 } 44 h, err := FileInfoHeader(fi, "") 45 if err != nil { 46 t.Fatalf("FileInfoHeader: %v", err) 47 } 48 if g, e := h.Name, "testdata/"; g != e { 49 t.Errorf("Name = %q; want %q", g, e) 50 } 51 // Ignoring c_ISGID for golang.org/issue/4867 52 if g, e := h.Mode&^c_ISGID, int64(fi.Mode().Perm())|c_ISDIR; g != e { 53 t.Errorf("Mode = %#o; want %#o", g, e) 54 } 55 if g, e := h.Size, int64(0); g != e { 56 t.Errorf("Size = %v; want %v", g, e) 57 } 58 if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) { 59 t.Errorf("ModTime = %v; want %v", g, e) 60 } 61 } 62 63 func TestFileInfoHeaderSymlink(t *testing.T) { 64 h, err := FileInfoHeader(symlink{}, "some-target") 65 if err != nil { 66 t.Fatal(err) 67 } 68 if g, e := h.Name, "some-symlink"; g != e { 69 t.Errorf("Name = %q; want %q", g, e) 70 } 71 if g, e := h.Linkname, "some-target"; g != e { 72 t.Errorf("Linkname = %q; want %q", g, e) 73 } 74 } 75 76 type symlink struct{} 77 78 func (symlink) Name() string { return "some-symlink" } 79 func (symlink) Size() int64 { return 0 } 80 func (symlink) Mode() os.FileMode { return os.ModeSymlink } 81 func (symlink) ModTime() time.Time { return time.Time{} } 82 func (symlink) IsDir() bool { return false } 83 func (symlink) Sys() interface{} { return nil } 84 85 func TestRoundTrip(t *testing.T) { 86 data := []byte("some file contents") 87 88 var b bytes.Buffer 89 tw := NewWriter(&b) 90 hdr := &Header{ 91 Name: "file.txt", 92 Uid: 1 << 21, // too big for 8 octal digits 93 Size: int64(len(data)), 94 ModTime: time.Now(), 95 } 96 // tar only supports second precision. 97 hdr.ModTime = hdr.ModTime.Add(-time.Duration(hdr.ModTime.Nanosecond()) * time.Nanosecond) 98 if err := tw.WriteHeader(hdr); err != nil { 99 t.Fatalf("tw.WriteHeader: %v", err) 100 } 101 if _, err := tw.Write(data); err != nil { 102 t.Fatalf("tw.Write: %v", err) 103 } 104 if err := tw.Close(); err != nil { 105 t.Fatalf("tw.Close: %v", err) 106 } 107 108 // Read it back. 109 tr := NewReader(&b) 110 rHdr, err := tr.Next() 111 if err != nil { 112 t.Fatalf("tr.Next: %v", err) 113 } 114 if !reflect.DeepEqual(rHdr, hdr) { 115 t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr) 116 } 117 rData, err := ioutil.ReadAll(tr) 118 if err != nil { 119 t.Fatalf("Read: %v", err) 120 } 121 if !bytes.Equal(rData, data) { 122 t.Errorf("Data mismatch.\n got %q\nwant %q", rData, data) 123 } 124 } 125 126 type headerRoundTripTest struct { 127 h *Header 128 fm os.FileMode 129 } 130 131 func TestHeaderRoundTrip(t *testing.T) { 132 golden := []headerRoundTripTest{ 133 // regular file. 134 { 135 h: &Header{ 136 Name: "test.txt", 137 Mode: 0644 | c_ISREG, 138 Size: 12, 139 ModTime: time.Unix(1360600916, 0), 140 Typeflag: TypeReg, 141 }, 142 fm: 0644, 143 }, 144 // hard link. 145 { 146 h: &Header{ 147 Name: "hard.txt", 148 Mode: 0644 | c_ISLNK, 149 Size: 0, 150 ModTime: time.Unix(1360600916, 0), 151 Typeflag: TypeLink, 152 }, 153 fm: 0644 | os.ModeSymlink, 154 }, 155 // symbolic link. 156 { 157 h: &Header{ 158 Name: "link.txt", 159 Mode: 0777 | c_ISLNK, 160 Size: 0, 161 ModTime: time.Unix(1360600852, 0), 162 Typeflag: TypeSymlink, 163 }, 164 fm: 0777 | os.ModeSymlink, 165 }, 166 // character device node. 167 { 168 h: &Header{ 169 Name: "dev/null", 170 Mode: 0666 | c_ISCHR, 171 Size: 0, 172 ModTime: time.Unix(1360578951, 0), 173 Typeflag: TypeChar, 174 }, 175 fm: 0666 | os.ModeDevice | os.ModeCharDevice, 176 }, 177 // block device node. 178 { 179 h: &Header{ 180 Name: "dev/sda", 181 Mode: 0660 | c_ISBLK, 182 Size: 0, 183 ModTime: time.Unix(1360578954, 0), 184 Typeflag: TypeBlock, 185 }, 186 fm: 0660 | os.ModeDevice, 187 }, 188 // directory. 189 { 190 h: &Header{ 191 Name: "dir/", 192 Mode: 0755 | c_ISDIR, 193 Size: 0, 194 ModTime: time.Unix(1360601116, 0), 195 Typeflag: TypeDir, 196 }, 197 fm: 0755 | os.ModeDir, 198 }, 199 // fifo node. 200 { 201 h: &Header{ 202 Name: "dev/initctl", 203 Mode: 0600 | c_ISFIFO, 204 Size: 0, 205 ModTime: time.Unix(1360578949, 0), 206 Typeflag: TypeFifo, 207 }, 208 fm: 0600 | os.ModeNamedPipe, 209 }, 210 // setuid. 211 { 212 h: &Header{ 213 Name: "bin/su", 214 Mode: 0755 | c_ISREG | c_ISUID, 215 Size: 23232, 216 ModTime: time.Unix(1355405093, 0), 217 Typeflag: TypeReg, 218 }, 219 fm: 0755 | os.ModeSetuid, 220 }, 221 // setguid. 222 { 223 h: &Header{ 224 Name: "group.txt", 225 Mode: 0750 | c_ISREG | c_ISGID, 226 Size: 0, 227 ModTime: time.Unix(1360602346, 0), 228 Typeflag: TypeReg, 229 }, 230 fm: 0750 | os.ModeSetgid, 231 }, 232 // sticky. 233 { 234 h: &Header{ 235 Name: "sticky.txt", 236 Mode: 0600 | c_ISREG | c_ISVTX, 237 Size: 7, 238 ModTime: time.Unix(1360602540, 0), 239 Typeflag: TypeReg, 240 }, 241 fm: 0600 | os.ModeSticky, 242 }, 243 } 244 245 for i, g := range golden { 246 fi := g.h.FileInfo() 247 h2, err := FileInfoHeader(fi, "") 248 if err != nil { 249 t.Error(err) 250 continue 251 } 252 if got, want := h2.Name, g.h.Name; got != want { 253 t.Errorf("i=%d: Name: got %v, want %v", i, got, want) 254 } 255 if got, want := h2.Size, g.h.Size; got != want { 256 t.Errorf("i=%d: Size: got %v, want %v", i, got, want) 257 } 258 if got, want := h2.Mode, g.h.Mode; got != want { 259 t.Errorf("i=%d: Mode: got %o, want %o", i, got, want) 260 } 261 if got, want := fi.Mode(), g.fm; got != want { 262 t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want) 263 } 264 if got, want := h2.ModTime, g.h.ModTime; got != want { 265 t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want) 266 } 267 if sysh, ok := fi.Sys().(*Header); !ok || sysh != g.h { 268 t.Errorf("i=%d: Sys didn't return original *Header", i) 269 } 270 } 271 }