gopkg.in/tools/godep.v41@v41.0.0-20151217180337-fe5ce707f879/Godeps/_workspace/src/github.com/kr/fs/walk_test.go (about)

     1  // Copyright 2009 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 fs_test
     6  
     7  import (
     8  	"os"
     9  	"path/filepath"
    10  	"runtime"
    11  	"testing"
    12  
    13  	"github.com/tools/godep/Godeps/_workspace/src/github.com/kr/fs"
    14  )
    15  
    16  type PathTest struct {
    17  	path, result string
    18  }
    19  
    20  type Node struct {
    21  	name    string
    22  	entries []*Node // nil if the entry is a file
    23  	mark    int
    24  }
    25  
    26  var tree = &Node{
    27  	"testdata",
    28  	[]*Node{
    29  		{"a", nil, 0},
    30  		{"b", []*Node{}, 0},
    31  		{"c", nil, 0},
    32  		{
    33  			"d",
    34  			[]*Node{
    35  				{"x", nil, 0},
    36  				{"y", []*Node{}, 0},
    37  				{
    38  					"z",
    39  					[]*Node{
    40  						{"u", nil, 0},
    41  						{"v", nil, 0},
    42  					},
    43  					0,
    44  				},
    45  			},
    46  			0,
    47  		},
    48  	},
    49  	0,
    50  }
    51  
    52  func walkTree(n *Node, path string, f func(path string, n *Node)) {
    53  	f(path, n)
    54  	for _, e := range n.entries {
    55  		walkTree(e, filepath.Join(path, e.name), f)
    56  	}
    57  }
    58  
    59  func makeTree(t *testing.T) {
    60  	walkTree(tree, tree.name, func(path string, n *Node) {
    61  		if n.entries == nil {
    62  			fd, err := os.Create(path)
    63  			if err != nil {
    64  				t.Errorf("makeTree: %v", err)
    65  				return
    66  			}
    67  			fd.Close()
    68  		} else {
    69  			os.Mkdir(path, 0770)
    70  		}
    71  	})
    72  }
    73  
    74  func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) }
    75  
    76  func checkMarks(t *testing.T, report bool) {
    77  	walkTree(tree, tree.name, func(path string, n *Node) {
    78  		if n.mark != 1 && report {
    79  			t.Errorf("node %s mark = %d; expected 1", path, n.mark)
    80  		}
    81  		n.mark = 0
    82  	})
    83  }
    84  
    85  // Assumes that each node name is unique. Good enough for a test.
    86  // If clear is true, any incoming error is cleared before return. The errors
    87  // are always accumulated, though.
    88  func mark(path string, info os.FileInfo, err error, errors *[]error, clear bool) error {
    89  	if err != nil {
    90  		*errors = append(*errors, err)
    91  		if clear {
    92  			return nil
    93  		}
    94  		return err
    95  	}
    96  	name := info.Name()
    97  	walkTree(tree, tree.name, func(path string, n *Node) {
    98  		if n.name == name {
    99  			n.mark++
   100  		}
   101  	})
   102  	return nil
   103  }
   104  
   105  func TestWalk(t *testing.T) {
   106  	makeTree(t)
   107  	errors := make([]error, 0, 10)
   108  	clear := true
   109  	markFn := func(walker *fs.Walker) (err error) {
   110  		for walker.Step() {
   111  			err = mark(walker.Path(), walker.Stat(), walker.Err(), &errors, clear)
   112  			if err != nil {
   113  				break
   114  			}
   115  		}
   116  		return err
   117  	}
   118  	// Expect no errors.
   119  	err := markFn(fs.Walk(tree.name))
   120  	if err != nil {
   121  		t.Fatalf("no error expected, found: %s", err)
   122  	}
   123  	if len(errors) != 0 {
   124  		t.Fatalf("unexpected errors: %s", errors)
   125  	}
   126  	checkMarks(t, true)
   127  	errors = errors[0:0]
   128  
   129  	// Test permission errors.  Only possible if we're not root
   130  	// and only on some file systems (AFS, FAT).  To avoid errors during
   131  	// all.bash on those file systems, skip during go test -short.
   132  	if os.Getuid() > 0 && !testing.Short() {
   133  		// introduce 2 errors: chmod top-level directories to 0
   134  		os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0)
   135  		os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0)
   136  
   137  		// 3) capture errors, expect two.
   138  		// mark respective subtrees manually
   139  		markTree(tree.entries[1])
   140  		markTree(tree.entries[3])
   141  		// correct double-marking of directory itself
   142  		tree.entries[1].mark--
   143  		tree.entries[3].mark--
   144  		err := markFn(fs.Walk(tree.name))
   145  		if err != nil {
   146  			t.Fatalf("expected no error return from Walk, got %s", err)
   147  		}
   148  		if len(errors) != 2 {
   149  			t.Errorf("expected 2 errors, got %d: %s", len(errors), errors)
   150  		}
   151  		// the inaccessible subtrees were marked manually
   152  		checkMarks(t, true)
   153  		errors = errors[0:0]
   154  
   155  		// 4) capture errors, stop after first error.
   156  		// mark respective subtrees manually
   157  		markTree(tree.entries[1])
   158  		markTree(tree.entries[3])
   159  		// correct double-marking of directory itself
   160  		tree.entries[1].mark--
   161  		tree.entries[3].mark--
   162  		clear = false // error will stop processing
   163  		err = markFn(fs.Walk(tree.name))
   164  		if err == nil {
   165  			t.Fatalf("expected error return from Walk")
   166  		}
   167  		if len(errors) != 1 {
   168  			t.Errorf("expected 1 error, got %d: %s", len(errors), errors)
   169  		}
   170  		// the inaccessible subtrees were marked manually
   171  		checkMarks(t, false)
   172  		errors = errors[0:0]
   173  
   174  		// restore permissions
   175  		os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770)
   176  		os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770)
   177  	}
   178  
   179  	// cleanup
   180  	if err := os.RemoveAll(tree.name); err != nil {
   181  		t.Errorf("removeTree: %v", err)
   182  	}
   183  }
   184  
   185  func TestBug3486(t *testing.T) { // http://code.google.com/p/go/issues/detail?id=3486
   186  	root, err := filepath.EvalSymlinks(runtime.GOROOT())
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  	lib := filepath.Join(root, "lib")
   191  	src := filepath.Join(root, "src")
   192  	seenSrc := false
   193  	walker := fs.Walk(root)
   194  	for walker.Step() {
   195  		if walker.Err() != nil {
   196  			t.Fatal(walker.Err())
   197  		}
   198  
   199  		switch walker.Path() {
   200  		case lib:
   201  			walker.SkipDir()
   202  		case src:
   203  			seenSrc = true
   204  		}
   205  	}
   206  	if !seenSrc {
   207  		t.Fatalf("%q not seen", src)
   208  	}
   209  }