github.com/wedaly/gospelunk@v0.0.0-20240506220214-89e2d4a79789/pkg/list/list_test.go (about) 1 package list 2 3 import ( 4 "os" 5 "path/filepath" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 "github.com/wedaly/gospelunk/pkg/file" 12 ) 13 14 func TestList(t *testing.T) { 15 pkg := Package{ 16 Name: "testmodule001", 17 ID: "github.com/wedaly/gospelunk/pkg/list/testdata/testmodule001", 18 } 19 20 testPkg := Package{ 21 Name: "testmodule001", 22 ID: "github.com/wedaly/gospelunk/pkg/list/testdata/testmodule001 [github.com/wedaly/gospelunk/pkg/list/testdata/testmodule001.test]", 23 } 24 25 pkgPath := func(p string) string { 26 path := filepath.Join("testdata", "testmodule001", p) 27 absPath, err := filepath.Abs(path) 28 require.NoError(t, err) 29 return absPath 30 } 31 32 testCases := []struct { 33 name string 34 dir string 35 patterns []string 36 opts Options 37 expected Result 38 }{ 39 { 40 name: "public only", 41 dir: "testdata/testmodule001", 42 patterns: []string{"./..."}, 43 opts: Options{}, 44 expected: Result{ 45 Defs: []Definition{ 46 {Name: "MyVar", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 3, Column: 5}}, 47 {Name: "MyConst", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 5, Column: 7}}, 48 {Name: "MyStruct", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 7, Column: 6}}, 49 {Name: "MyInterface", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 17, Column: 6}}, 50 {Name: "MyFunc", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 21, Column: 1}}, 51 }, 52 }, 53 }, 54 { 55 name: "include struct fields", 56 dir: "testdata/testmodule001", 57 patterns: []string{"./..."}, 58 opts: Options{IncludeStructFields: true}, 59 expected: Result{ 60 Defs: []Definition{ 61 {Name: "MyVar", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 3, Column: 5}}, 62 {Name: "MyConst", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 5, Column: 7}}, 63 {Name: "MyStruct", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 7, Column: 6}}, 64 {Name: "MyStruct.MyField", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 8, Column: 2}}, 65 {Name: "MyInterface", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 17, Column: 6}}, 66 {Name: "MyFunc", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 21, Column: 1}}, 67 }, 68 }, 69 }, 70 { 71 name: "include interface methods", 72 dir: "testdata/testmodule001", 73 patterns: []string{"./..."}, 74 opts: Options{IncludeInterfaceMethods: true}, 75 expected: Result{ 76 Defs: []Definition{ 77 {Name: "MyVar", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 3, Column: 5}}, 78 {Name: "MyConst", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 5, Column: 7}}, 79 {Name: "MyStruct", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 7, Column: 6}}, 80 {Name: "MyInterface", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 17, Column: 6}}, 81 {Name: "MyInterface.String", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 18, Column: 2}}, 82 {Name: "MyFunc", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 21, Column: 1}}, 83 }, 84 }, 85 }, 86 { 87 name: "include private", 88 dir: "testdata/testmodule001", 89 patterns: []string{"./..."}, 90 opts: Options{IncludePrivate: true, IncludeStructFields: true}, 91 expected: Result{ 92 Defs: []Definition{ 93 {Name: "MyVar", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 3, Column: 5}}, 94 {Name: "MyConst", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 5, Column: 7}}, 95 {Name: "MyStruct", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 7, Column: 6}}, 96 {Name: "MyStruct.MyField", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 8, Column: 2}}, 97 {Name: "MyStruct.privateField", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 9, Column: 2}}, 98 {Name: "privateStruct", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 12, Column: 6}}, 99 {Name: "privateStruct.PublicField", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 13, Column: 2}}, 100 {Name: "privateStruct.privateField", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 14, Column: 2}}, 101 {Name: "MyInterface", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 17, Column: 6}}, 102 {Name: "MyFunc", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 21, Column: 1}}, 103 {Name: "privateFunc", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 25, Column: 1}}, 104 }, 105 }, 106 }, 107 { 108 name: "include tests", 109 dir: "testdata/testmodule001", 110 patterns: []string{"./..."}, 111 opts: Options{IncludeTests: true}, 112 expected: Result{ 113 Defs: []Definition{ 114 {Name: "MyVar", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 3, Column: 5}}, 115 {Name: "MyConst", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 5, Column: 7}}, 116 {Name: "MyStruct", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 7, Column: 6}}, 117 {Name: "MyInterface", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 17, Column: 6}}, 118 {Name: "MyFunc", Pkg: pkg, Loc: file.Loc{Path: pkgPath("defs.go"), Line: 21, Column: 1}}, 119 {Name: "TestStruct", Pkg: testPkg, Loc: file.Loc{Path: pkgPath("defs_test.go"), Line: 3, Column: 6}}, 120 }, 121 }, 122 }, 123 } 124 125 for _, tc := range testCases { 126 t.Run(tc.name, func(t *testing.T) { 127 withWorkingDir(t, tc.dir, func(t *testing.T) { 128 result, err := List(tc.patterns, tc.opts) 129 require.NoError(t, err) 130 assert.Equal(t, tc.expected, result) 131 }) 132 }) 133 } 134 } 135 136 func TestListWithCGo(t *testing.T) { 137 cgoRelPath := filepath.Join("testdata", "testmodule002", "cgo.go") 138 cgoPath, err := filepath.Abs(cgoRelPath) 139 require.NoError(t, err) 140 141 withWorkingDir(t, "testdata/testmodule002", func(t *testing.T) { 142 result, err := List([]string{"."}, Options{}) 143 require.NoError(t, err) 144 145 expected := Result{ 146 Defs: []Definition{ 147 { 148 Loc: file.Loc{Path: cgoPath, Line: 6, Column: 6}, 149 Name: "MyStruct", 150 Pkg: Package{ 151 Name: "testmodule002", 152 ID: "github.com/wedaly/gospelunk/pkg/list/testdata/testmodule002", 153 }, 154 }, 155 { 156 Loc: file.Loc{Path: cgoPath, Line: 8, Column: 1}, 157 Name: "Random", 158 Pkg: Package{ 159 Name: "testmodule002", 160 ID: "github.com/wedaly/gospelunk/pkg/list/testdata/testmodule002", 161 }, 162 }, 163 }, 164 } 165 assert.Equal(t, expected, result) 166 }) 167 } 168 169 func TestListWithImports(t *testing.T) { 170 withWorkingDir(t, "testdata/testmodule003", func(t *testing.T) { 171 result, err := List([]string{"."}, Options{OnlyImports: true}) 172 require.NoError(t, err) 173 174 // Exact definitions may vary based on Go stdlib, so check that imported packages are included. 175 defPkgs := make(map[string][]string) 176 for _, def := range result.Defs { 177 defPkgs[def.Pkg.ID] = append(defPkgs[def.Pkg.ID], def.Name) 178 } 179 assert.Equal(t, 2, len(defPkgs)) 180 assert.Equal(t, []string{"SubFunc"}, defPkgs["github.com/wedaly/gospelunk/pkg/list/testdata/testmodule003/subpkg"]) 181 assert.Greater(t, len(defPkgs["fmt"]), 1) 182 }) 183 } 184 185 func TestListFileOutsideGoModule(t *testing.T) { 186 withWorkingDir(t, "testdata", func(t *testing.T) { 187 result, err := List([]string{"file=testmodule004/first.go"}, Options{}) 188 require.NoError(t, err) 189 190 // Expect definitions from both files in the package. 191 var defNames []string 192 for _, def := range result.Defs { 193 defNames = append(defNames, def.Name) 194 } 195 expected := []string{"FirstFunc", "SecondFunc"} 196 assert.Equal(t, expected, defNames) 197 }) 198 } 199 200 func withWorkingDir(t *testing.T, dir string, f func(t *testing.T)) { 201 oldWd, err := os.Getwd() 202 require.NoError(t, err) 203 defer os.Chdir(oldWd) 204 err = os.Chdir(dir) 205 require.NoError(t, err) 206 f(t) 207 }