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