github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/core/ls/ls_test.go (about)

     1  // Copyright 2017 the u-root 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 main
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"os"
    12  	"path/filepath"
    13  	"strings"
    14  	"testing"
    15  
    16  	"github.com/mvdan/u-root-coreutils/pkg/ls"
    17  	"golang.org/x/sys/unix"
    18  )
    19  
    20  type ttflags struct {
    21  	all       bool
    22  	human     bool
    23  	directory bool
    24  	long      bool
    25  	quoted    bool
    26  	recurse   bool
    27  	classify  bool
    28  }
    29  
    30  // Test listName func
    31  func TestListName(t *testing.T) {
    32  	// Create some directorys.
    33  	tmpDir := t.TempDir()
    34  	if err := os.Mkdir(filepath.Join(tmpDir, "d1"), 0777); err != nil {
    35  		t.Fatalf("err in os.Mkdir: %v", err)
    36  	}
    37  	// Create some files.
    38  	files := []string{"f1", "f2", "f3\nline 2", ".f4", "d1/f4"}
    39  	for _, file := range files {
    40  		if _, err := os.Create(filepath.Join(tmpDir, file)); err != nil {
    41  			t.Fatalf("err in os.Create: %v", err)
    42  		}
    43  	}
    44  
    45  	// Creating test table
    46  	for _, tt := range []struct {
    47  		name   string
    48  		input  string
    49  		want   string
    50  		flag   ttflags
    51  		prefix bool
    52  	}{
    53  		{
    54  			name:  "ls without arguments",
    55  			input: tmpDir,
    56  			want:  fmt.Sprintf("%s\n%s\n%s\n%s\n", "d1", "f1", "f2", "f3?line 2"),
    57  			flag:  ttflags{},
    58  		},
    59  		{
    60  			name:  "ls osfi.IsDir() path, quoted = true",
    61  			input: tmpDir,
    62  			want:  fmt.Sprintf("\"%s\"\n\"%s\"\n\"%s\"\n\"%s\"\n", "d1", "f1", "f2", "f3\\nline 2"),
    63  			flag: ttflags{
    64  				quoted: true,
    65  			},
    66  		},
    67  		{
    68  			name:  "ls osfi.IsDir() path, quoted = true, prefix = true ",
    69  			input: tmpDir,
    70  			want:  fmt.Sprintf("\"%s\":\n\"%s\"\n\"%s\"\n\"%s\"\n\"%s\"\n", tmpDir, "d1", "f1", "f2", "f3\\nline 2"),
    71  			flag: ttflags{
    72  				quoted: true,
    73  			},
    74  			prefix: true,
    75  		},
    76  		{
    77  			name:   "ls osfi.IsDir() path, quoted = false, prefix = true ",
    78  			input:  tmpDir,
    79  			want:   fmt.Sprintf("%s:\n%s\n%s\n%s\n%s\n", tmpDir, "d1", "f1", "f2", "f3?line 2"),
    80  			prefix: true,
    81  		},
    82  		{
    83  			name:  "ls recurse = true",
    84  			input: tmpDir,
    85  			want: fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n", tmpDir, filepath.Join(tmpDir, ".f4"), filepath.Join(tmpDir, "d1"),
    86  				filepath.Join(tmpDir, "d1/f4"), filepath.Join(tmpDir, "f1"), filepath.Join(tmpDir, "f2"), filepath.Join(tmpDir, "f3?line 2")),
    87  			flag: ttflags{
    88  				all:     true,
    89  				recurse: true,
    90  			},
    91  		},
    92  		{
    93  			name:  "ls directory = true",
    94  			input: tmpDir,
    95  			want:  fmt.Sprintf("%s\n", "tmpDir"),
    96  			flag: ttflags{
    97  				directory: true,
    98  			},
    99  		},
   100  		{
   101  			name:  "ls classify = true",
   102  			input: tmpDir,
   103  			want:  fmt.Sprintf("%s\n%s\n%s\n%s\n", "d1/", "f1", "f2", "f3?line 2"),
   104  			flag: ttflags{
   105  				classify: true,
   106  			},
   107  		},
   108  		{
   109  			name:  "file does not exist",
   110  			input: "dir",
   111  			flag:  ttflags{},
   112  		},
   113  	} {
   114  		// Setting the flags
   115  		*all = tt.flag.all
   116  		*human = tt.flag.human
   117  		*directory = tt.flag.directory
   118  		*long = tt.flag.long
   119  		*quoted = tt.flag.quoted
   120  		*recurse = tt.flag.recurse
   121  		*classify = tt.flag.classify
   122  
   123  		// Running the tests
   124  		t.Run(tt.name, func(t *testing.T) {
   125  			// Write output in buffer.
   126  			var buf bytes.Buffer
   127  			var s ls.Stringer = ls.NameStringer{}
   128  			if *quoted {
   129  				s = ls.QuotedStringer{}
   130  			}
   131  			if *long {
   132  				s = ls.LongStringer{Human: *human, Name: s}
   133  			}
   134  			if err := listName(s, tt.input, &buf, tt.prefix); err != nil {
   135  				if buf.String() != tt.want {
   136  					t.Errorf("listName() = '%v', want: '%v'", buf.String(), tt.want)
   137  				}
   138  			}
   139  		})
   140  	}
   141  }
   142  
   143  // Test list func
   144  func TestList(t *testing.T) {
   145  	// Creating test table
   146  	for _, tt := range []struct {
   147  		name   string
   148  		input  []string
   149  		err    error
   150  		flag   ttflags
   151  		prefix bool
   152  	}{
   153  		{
   154  			name:  "input empty, quoted = true, long = true",
   155  			input: []string{},
   156  			err:   nil,
   157  			flag: ttflags{
   158  				quoted: true,
   159  				long:   true,
   160  			},
   161  		},
   162  		{
   163  			name:  "input empty, quoted = true, long = true",
   164  			input: []string{"dir"},
   165  			err:   os.ErrNotExist,
   166  		},
   167  	} {
   168  
   169  		// Setting the flags
   170  		*long = tt.flag.long
   171  		*quoted = tt.flag.quoted
   172  
   173  		// Running the tests
   174  		t.Run(tt.name, func(t *testing.T) {
   175  			var buf bytes.Buffer
   176  			if err := list(&buf, tt.input); err != nil {
   177  				if !errors.Is(err, tt.err) {
   178  					t.Errorf("list() = '%v', want: '%v'", err, tt.err)
   179  				}
   180  			}
   181  		})
   182  	}
   183  }
   184  
   185  // Test indicator func
   186  func TestIndicator(t *testing.T) {
   187  	// Creating test table
   188  	for _, test := range []struct {
   189  		lsInfo ls.FileInfo
   190  		symbol string
   191  	}{
   192  		{
   193  			ls.FileInfo{
   194  				Mode: os.ModeDir,
   195  			},
   196  			"/",
   197  		},
   198  		{
   199  			ls.FileInfo{
   200  				Mode: os.ModeNamedPipe,
   201  			},
   202  			"|",
   203  		},
   204  		{
   205  			ls.FileInfo{
   206  				Mode: os.ModeSymlink,
   207  			},
   208  			"@",
   209  		},
   210  		{
   211  			ls.FileInfo{
   212  				Mode: os.ModeSocket,
   213  			},
   214  			"=",
   215  		},
   216  		{
   217  			ls.FileInfo{
   218  				Mode: 0b110110100,
   219  			},
   220  			"",
   221  		},
   222  		{
   223  			ls.FileInfo{
   224  				Mode: 0b111111101,
   225  			},
   226  			"*",
   227  		},
   228  	} {
   229  		// Run tests
   230  		got := indicator(test.lsInfo)
   231  		if got != test.symbol {
   232  			t.Errorf("for mode '%b' expected '%q', got '%q'", test.lsInfo.Mode, test.symbol, got)
   233  		}
   234  	}
   235  }
   236  
   237  // Make sure if perms fail in a dir, we still list the dir.
   238  func TestPermHandling(t *testing.T) {
   239  	d := t.TempDir()
   240  	for _, v := range []string{"a", "c", "d"} {
   241  		if err := os.Mkdir(filepath.Join(d, v), 0777); err != nil {
   242  			t.Fatal(err)
   243  		}
   244  	}
   245  	if err := os.Mkdir(filepath.Join(d, "b"), 0); err != nil {
   246  		t.Fatal(err)
   247  	}
   248  	for _, v := range []string{"0", "1", "2"} {
   249  		if err := os.Mkdir(filepath.Join(d, v), 0777); err != nil {
   250  			t.Fatal(err)
   251  		}
   252  	}
   253  	b := &bytes.Buffer{}
   254  	if err := listName(ls.NameStringer{}, d, b, false); err != nil {
   255  		t.Fatalf("listName(ls.NameString{}, %q, w, false): %v != nil", d, err)
   256  	}
   257  	// the output varies very widely between kernels and Go versions :-(
   258  	// Just look for 'permission denied' and more than 6 lines of output ...
   259  	if !strings.Contains(b.String(), "0\n1\n2\na\nb\nc\nd\n") {
   260  		t.Errorf("ls %q: output %q did not contain %q", d, b.String(), "0\n1\n2\na\nb\nc\nd\n")
   261  	}
   262  }
   263  
   264  func TestNotExist(t *testing.T) {
   265  	d := t.TempDir()
   266  	b := &bytes.Buffer{}
   267  	if err := listName(ls.NameStringer{}, filepath.Join(d, "b"), b, false); err != nil {
   268  		t.Fatalf("listName(ls.NameString{}, %q/b, w, false): nil != %v", d, err)
   269  	}
   270  	// yeesh.
   271  	// errors not consistent and ... the error has this gratuitous 'lstat ' in front
   272  	// of the filename ...
   273  	eexist := fmt.Sprintf("%s:%v", filepath.Join(d, "b"), os.ErrNotExist)
   274  	enoent := fmt.Sprintf("%s: %v", filepath.Join(d, "b"), unix.ENOENT)
   275  	if !strings.Contains(b.String(), eexist) && !strings.Contains(b.String(), enoent) {
   276  		t.Fatalf("ls of bad name: %q does not contain %q or %q", b.String(), eexist, enoent)
   277  	}
   278  }