Source file src/io/fs/walk_test.go

     1  // Copyright 2020 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  	. "io/fs"
     9  	"os"
    10  	pathpkg "path"
    11  	"testing"
    12  	"testing/fstest"
    13  )
    14  
    15  type Node struct {
    16  	name    string
    17  	entries []*Node // nil if the entry is a file
    18  	mark    int
    19  }
    20  
    21  var tree = &Node{
    22  	"testdata",
    23  	[]*Node{
    24  		{"a", nil, 0},
    25  		{"b", []*Node{}, 0},
    26  		{"c", nil, 0},
    27  		{
    28  			"d",
    29  			[]*Node{
    30  				{"x", nil, 0},
    31  				{"y", []*Node{}, 0},
    32  				{
    33  					"z",
    34  					[]*Node{
    35  						{"u", nil, 0},
    36  						{"v", nil, 0},
    37  					},
    38  					0,
    39  				},
    40  			},
    41  			0,
    42  		},
    43  	},
    44  	0,
    45  }
    46  
    47  func walkTree(n *Node, path string, f func(path string, n *Node)) {
    48  	f(path, n)
    49  	for _, e := range n.entries {
    50  		walkTree(e, pathpkg.Join(path, e.name), f)
    51  	}
    52  }
    53  
    54  func makeTree(t *testing.T) FS {
    55  	fsys := fstest.MapFS{}
    56  	walkTree(tree, tree.name, func(path string, n *Node) {
    57  		if n.entries == nil {
    58  			fsys[path] = &fstest.MapFile{}
    59  		} else {
    60  			fsys[path] = &fstest.MapFile{Mode: ModeDir}
    61  		}
    62  	})
    63  	return fsys
    64  }
    65  
    66  func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) }
    67  
    68  func checkMarks(t *testing.T, report bool) {
    69  	walkTree(tree, tree.name, func(path string, n *Node) {
    70  		if n.mark != 1 && report {
    71  			t.Errorf("node %s mark = %d; expected 1", path, n.mark)
    72  		}
    73  		n.mark = 0
    74  	})
    75  }
    76  
    77  // Assumes that each node name is unique. Good enough for a test.
    78  // If clear is true, any incoming error is cleared before return. The errors
    79  // are always accumulated, though.
    80  func mark(entry DirEntry, err error, errors *[]error, clear bool) error {
    81  	name := entry.Name()
    82  	walkTree(tree, tree.name, func(path string, n *Node) {
    83  		if n.name == name {
    84  			n.mark++
    85  		}
    86  	})
    87  	if err != nil {
    88  		*errors = append(*errors, err)
    89  		if clear {
    90  			return nil
    91  		}
    92  		return err
    93  	}
    94  	return nil
    95  }
    96  
    97  func TestWalkDir(t *testing.T) {
    98  	tmpDir := t.TempDir()
    99  
   100  	origDir, err := os.Getwd()
   101  	if err != nil {
   102  		t.Fatal("finding working dir:", err)
   103  	}
   104  	if err = os.Chdir(tmpDir); err != nil {
   105  		t.Fatal("entering temp dir:", err)
   106  	}
   107  	defer os.Chdir(origDir)
   108  
   109  	fsys := makeTree(t)
   110  	errors := make([]error, 0, 10)
   111  	clear := true
   112  	markFn := func(path string, entry DirEntry, err error) error {
   113  		return mark(entry, err, &errors, clear)
   114  	}
   115  	// Expect no errors.
   116  	err = WalkDir(fsys, ".", markFn)
   117  	if err != nil {
   118  		t.Fatalf("no error expected, found: %s", err)
   119  	}
   120  	if len(errors) != 0 {
   121  		t.Fatalf("unexpected errors: %s", errors)
   122  	}
   123  	checkMarks(t, true)
   124  }
   125  

View as plain text