blob: 5431df413b54d2d8ec74fe0dd068bf45db2b3e60 [file] [log] [blame]
package vsolver
import (
"go/build"
"os"
"path/filepath"
"reflect"
"testing"
)
// externalReach() uses an easily separable algorithm, wmToReach(), to turn a
// discovered set of packages and their imports into a proper external reach
// map.
//
// That algorithm is purely symbolic (no filesystem interaction), and thus is
// easy to test. This is that test.
func TestWorkmapToReach(t *testing.T) {
empty := func() map[string]struct{} {
return make(map[string]struct{})
}
table := map[string]struct {
name string
workmap map[string]wm
basedir string
out map[string][]string
err error
}{
"single": {
workmap: map[string]wm{
"foo": {
ex: empty(),
in: empty(),
},
},
out: map[string][]string{
"foo": {},
},
},
"no external": {
workmap: map[string]wm{
"foo": {
ex: empty(),
in: empty(),
},
"foo/bar": {
ex: empty(),
in: empty(),
},
},
out: map[string][]string{
"foo": {},
"foo/bar": {},
},
},
"no external with subpkg": {
workmap: map[string]wm{
"foo": {
ex: empty(),
in: map[string]struct{}{
"foo/bar": struct{}{},
},
},
"foo/bar": {
ex: empty(),
in: empty(),
},
},
out: map[string][]string{
"foo": {},
"foo/bar": {},
},
},
"simple base transitive": {
workmap: map[string]wm{
"foo": {
ex: empty(),
in: map[string]struct{}{
"foo/bar": struct{}{},
},
},
"foo/bar": {
ex: map[string]struct{}{
"baz": struct{}{},
},
in: empty(),
},
},
out: map[string][]string{
"foo": {
"baz",
},
"foo/bar": {
"baz",
},
},
},
}
for name, fix := range table {
out, err := wmToReach(fix.workmap, fix.basedir)
if fix.out == nil {
if err == nil {
t.Errorf("wmToReach(%q): Error expected but not received", name)
}
continue
}
if err != nil {
t.Errorf("wmToReach(%q): %v", name, err)
continue
}
if !reflect.DeepEqual(out, fix.out) {
t.Errorf("wmToReach(%q): Did not get expected reach map:\n\t(GOT): %s\n\t(WNT): %s", name, out, fix.out)
}
}
}
func TestListPackages(t *testing.T) {
srcdir := filepath.Join(getwd(t), "_testdata", "src")
j := func(s string) string {
return filepath.Join(srcdir, s)
}
table := map[string]struct {
fileRoot string
importRoot string
out PackageTree
err error
}{
"empty": {
fileRoot: j("empty"),
importRoot: "empty",
out: PackageTree{
ImportRoot: "empty",
Packages: map[string]PackageOrErr{
"empty": PackageOrErr{
Err: &build.NoGoError{
Dir: j("empty"),
},
},
},
},
err: nil,
},
"code only": {
fileRoot: j("simple"),
importRoot: "simple",
out: PackageTree{
ImportRoot: "simple",
Packages: map[string]PackageOrErr{
"simple": PackageOrErr{
P: Package{
ImportPath: "simple",
CommentPath: "",
Name: "simple",
Imports: []string{
"github.com/sdboyer/vsolver",
"sort",
},
},
},
},
},
},
"impose import path": {
fileRoot: j("simple"),
importRoot: "arbitrary",
out: PackageTree{
ImportRoot: "arbitrary",
Packages: map[string]PackageOrErr{
"arbitrary": PackageOrErr{
P: Package{
ImportPath: "arbitrary",
CommentPath: "",
Name: "simple",
Imports: []string{
"github.com/sdboyer/vsolver",
"sort",
},
},
},
},
},
},
"test only": {
fileRoot: j("t"),
importRoot: "simple",
out: PackageTree{
ImportRoot: "simple",
Packages: map[string]PackageOrErr{
"simple": PackageOrErr{
P: Package{
ImportPath: "simple",
CommentPath: "",
Name: "simple",
Imports: []string{},
TestImports: []string{
"math/rand",
"strconv",
},
},
},
},
},
},
"xtest only": {
fileRoot: j("xt"),
importRoot: "simple",
out: PackageTree{
ImportRoot: "simple",
Packages: map[string]PackageOrErr{
"simple": PackageOrErr{
P: Package{
ImportPath: "simple",
CommentPath: "",
Name: "simple",
Imports: []string{},
TestImports: []string{
"sort",
"strconv",
},
},
},
},
},
},
"code and test": {
fileRoot: j("simplet"),
importRoot: "simple",
out: PackageTree{
ImportRoot: "simple",
Packages: map[string]PackageOrErr{
"simple": PackageOrErr{
P: Package{
ImportPath: "simple",
CommentPath: "",
Name: "simple",
Imports: []string{
"github.com/sdboyer/vsolver",
"sort",
},
TestImports: []string{
"math/rand",
"strconv",
},
},
},
},
},
},
"code and xtest": {
fileRoot: j("simplext"),
importRoot: "simple",
out: PackageTree{
ImportRoot: "simple",
Packages: map[string]PackageOrErr{
"simple": PackageOrErr{
P: Package{
ImportPath: "simple",
CommentPath: "",
Name: "simple",
Imports: []string{
"github.com/sdboyer/vsolver",
"sort",
},
TestImports: []string{
"sort",
"strconv",
},
},
},
},
},
},
"code, test, xtest": {
fileRoot: j("simpleallt"),
importRoot: "simple",
out: PackageTree{
ImportRoot: "simple",
Packages: map[string]PackageOrErr{
"simple": PackageOrErr{
P: Package{
ImportPath: "simple",
CommentPath: "",
Name: "simple",
Imports: []string{
"github.com/sdboyer/vsolver",
"sort",
},
TestImports: []string{
"math/rand",
"sort",
"strconv",
},
},
},
},
},
},
"one pkg multifile": {
fileRoot: j("m1p"),
importRoot: "m1p",
out: PackageTree{
ImportRoot: "m1p",
Packages: map[string]PackageOrErr{
"m1p": PackageOrErr{
P: Package{
ImportPath: "m1p",
CommentPath: "",
Name: "m1p",
Imports: []string{
"github.com/sdboyer/vsolver",
"os",
"sort",
},
},
},
},
},
},
"one nested below": {
fileRoot: j("nest"),
importRoot: "nest",
out: PackageTree{
ImportRoot: "nest",
Packages: map[string]PackageOrErr{
"nest": PackageOrErr{
P: Package{
ImportPath: "nest",
CommentPath: "",
Name: "simple",
Imports: []string{
"github.com/sdboyer/vsolver",
"sort",
},
},
},
"nest/m1p": PackageOrErr{
P: Package{
ImportPath: "nest/m1p",
CommentPath: "",
Name: "m1p",
Imports: []string{
"github.com/sdboyer/vsolver",
"os",
"sort",
},
},
},
},
},
},
"two nested under empty root": {
fileRoot: j("ren"),
importRoot: "ren",
out: PackageTree{
ImportRoot: "ren",
Packages: map[string]PackageOrErr{
"ren": PackageOrErr{
Err: &build.NoGoError{
Dir: j("ren"),
},
},
"ren/m1p": PackageOrErr{
P: Package{
ImportPath: "ren/m1p",
CommentPath: "",
Name: "m1p",
Imports: []string{
"github.com/sdboyer/vsolver",
"os",
"sort",
},
},
},
"ren/simple": PackageOrErr{
P: Package{
ImportPath: "ren/simple",
CommentPath: "",
Name: "simple",
Imports: []string{
"github.com/sdboyer/vsolver",
"sort",
},
},
},
},
},
},
"code and ignored main": {
fileRoot: j("igmain"),
importRoot: "simple",
out: PackageTree{
ImportRoot: "simple",
Packages: map[string]PackageOrErr{
"simple": PackageOrErr{
P: Package{
ImportPath: "simple",
CommentPath: "",
Name: "simple",
Imports: []string{
"github.com/sdboyer/vsolver",
"sort",
"unicode",
},
},
},
},
},
},
"code, tests, and ignored main": {
fileRoot: j("igmaint"),
importRoot: "simple",
out: PackageTree{
ImportRoot: "simple",
Packages: map[string]PackageOrErr{
"simple": PackageOrErr{
P: Package{
ImportPath: "simple",
CommentPath: "",
Name: "simple",
Imports: []string{
"github.com/sdboyer/vsolver",
"sort",
"unicode",
},
TestImports: []string{
"math/rand",
"strconv",
},
},
},
},
},
},
"two pkgs": {
fileRoot: j("twopkgs"),
importRoot: "twopkgs",
out: PackageTree{
ImportRoot: "twopkgs",
Packages: map[string]PackageOrErr{
"twopkgs": PackageOrErr{
Err: &build.MultiplePackageError{
Dir: j("twopkgs"),
Packages: []string{"simple", "m1p"},
Files: []string{"a.go", "b.go"},
},
},
},
},
},
}
for name, fix := range table {
if _, err := os.Stat(fix.fileRoot); err != nil {
t.Errorf("listPackages(%q): error on fileRoot %s: %s", name, fix.fileRoot, err)
continue
}
out, err := listPackages(fix.fileRoot, fix.importRoot)
if err != nil && fix.err == nil {
t.Errorf("listPackages(%q): Received error but none expected: %s", name, err)
} else if fix.err != nil && err == nil {
t.Errorf("listPackages(%q): Error expected but none received", name)
} else if fix.err != nil && err != nil {
if !reflect.DeepEqual(fix.err, err) {
t.Errorf("listPackages(%q): Did not receive expected error:\n\t(GOT): %s\n\t(WNT): %s", name, err, fix.err)
}
}
if fix.out.ImportRoot != "" && fix.out.Packages != nil {
if !reflect.DeepEqual(out, fix.out) {
t.Errorf("listPackages(%q): Did not receive expected package:\n\t(GOT): %s\n\t(WNT): %s", name, out, fix.out)
}
}
}
}
func getwd(t *testing.T) string {
cwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
return cwd
}