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