1// Copyright 2016 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
5package vfs_test
6
7import (
8	"fmt"
9	"strings"
10	"testing"
11	"time"
12
13	"golang.org/x/tools/godoc/vfs"
14	"golang.org/x/tools/godoc/vfs/mapfs"
15)
16
17func TestNewNameSpace(t *testing.T) {
18
19	// We will mount this filesystem under /fs1
20	mount := mapfs.New(map[string]string{"fs1file": "abcdefgh"})
21
22	// Existing process. This should give error on Stat("/")
23	t1 := vfs.NameSpace{}
24	t1.Bind("/fs1", mount, "/", vfs.BindReplace)
25
26	// using NewNameSpace. This should work fine.
27	t2 := vfs.NewNameSpace()
28	t2.Bind("/fs1", mount, "/", vfs.BindReplace)
29
30	testcases := map[string][]bool{
31		"/":            {false, true},
32		"/fs1":         {true, true},
33		"/fs1/fs1file": {true, true},
34	}
35
36	fss := []vfs.FileSystem{t1, t2}
37
38	for j, fs := range fss {
39		for k, v := range testcases {
40			_, err := fs.Stat(k)
41			result := err == nil
42			if result != v[j] {
43				t.Errorf("fs: %d, testcase: %s, want: %v, got: %v, err: %s", j, k, v[j], result, err)
44			}
45		}
46	}
47
48	fi, err := t2.Stat("/")
49	if err != nil {
50		t.Fatal(err)
51	}
52
53	if fi.Name() != "/" {
54		t.Errorf("t2.Name() : want:%s got:%s", "/", fi.Name())
55	}
56
57	if !fi.ModTime().IsZero() {
58		t.Errorf("t2.ModTime() : want:%v got:%v", time.Time{}, fi.ModTime())
59	}
60}
61
62func TestReadDirUnion(t *testing.T) {
63	for _, tc := range []struct {
64		desc       string
65		ns         vfs.NameSpace
66		path, want string
67	}{
68		{
69			desc: "no_go_files",
70			ns: func() vfs.NameSpace {
71				rootFs := mapfs.New(map[string]string{
72					"doc/a.txt":       "1",
73					"doc/b.txt":       "1",
74					"doc/dir1/d1.txt": "",
75				})
76				docFs := mapfs.New(map[string]string{
77					"doc/a.txt":       "22",
78					"doc/dir2/d2.txt": "",
79				})
80				ns := vfs.NameSpace{}
81				ns.Bind("/", rootFs, "/", vfs.BindReplace)
82				ns.Bind("/doc", docFs, "/doc", vfs.BindBefore)
83				return ns
84			}(),
85			path: "/doc",
86			want: "a.txt:2,b.txt:1,dir1:0,dir2:0",
87		}, {
88			desc: "have_go_files",
89			ns: func() vfs.NameSpace {
90				a := mapfs.New(map[string]string{
91					"src/x/a.txt":        "",
92					"src/x/suba/sub.txt": "",
93				})
94				b := mapfs.New(map[string]string{
95					"src/x/b.go":         "package b",
96					"src/x/subb/sub.txt": "",
97				})
98				c := mapfs.New(map[string]string{
99					"src/x/c.txt":        "",
100					"src/x/subc/sub.txt": "",
101				})
102				ns := vfs.NameSpace{}
103				ns.Bind("/", a, "/", vfs.BindReplace)
104				ns.Bind("/", b, "/", vfs.BindAfter)
105				ns.Bind("/", c, "/", vfs.BindAfter)
106				return ns
107			}(),
108			path: "/src/x",
109			want: "b.go:9,suba:0,subb:0,subc:0",
110		}, {
111			desc: "empty_mount",
112			ns: func() vfs.NameSpace {
113				ns := vfs.NameSpace{}
114				ns.Bind("/empty", mapfs.New(nil), "/empty", vfs.BindReplace)
115				return ns
116			}(),
117			path: "/",
118			want: "empty:0",
119		},
120	} {
121		t.Run(tc.desc, func(t *testing.T) {
122			fis, err := tc.ns.ReadDir(tc.path)
123			if err != nil {
124				t.Fatal(err)
125			}
126			buf := &strings.Builder{}
127			sep := ""
128			for _, fi := range fis {
129				fmt.Fprintf(buf, "%s%s:%d", sep, fi.Name(), fi.Size())
130				sep = ","
131			}
132			if got := buf.String(); got != tc.want {
133				t.Errorf("got %q; want %q", got, tc.want)
134			}
135		})
136	}
137}
138