コード例 #1
0
ファイル: types_test.go プロジェクト: nelsam/hel
func TestLoad_TestFilesInTestPackage(t *testing.T) {
	expect := expect.New(t)

	mockGoDir := newMockGoDir()
	mockGoDir.PathOutput.Path <- "/some/path"
	mockGoDir.PackagesOutput.Packages <- map[string]*ast.Package{
		"foo": {
			Name: "foo",
			Files: map[string]*ast.File{
				"foo.go": parse(expect, "type Foo interface{}"),
			},
		},
		"foo_test": {
			Name: "foo_test",
			Files: map[string]*ast.File{
				"foo_test.go": parse(expect, "type Bar interface{}"),
			},
		},
	}
	found := types.Load(mockGoDir)
	expect(found).To.Have.Len(1).Else.FailNow()
	expect(found[0].Len()).To.Equal(1)
	expect(found[0].Package()).To.Equal("foo")
	expect(found[0].TestPackage()).To.Equal("foo_test")
}
コード例 #2
0
ファイル: types_test.go プロジェクト: nelsam/hel
// TestAnonymousError is testing the only case (as of go 1.7) where
// a builtin is an interface type.
func TestAnonymousError(t *testing.T) {
	expect := expect.New(t)

	mockGoDir := newMockGoDir()
	mockGoDir.PathOutput.Path <- "/some/path"
	mockGoDir.PackagesOutput.Packages <- map[string]*ast.Package{
		"foo": {
			Name: "foo",
			Files: map[string]*ast.File{
				"foo.go": parse(expect, `
    type Foo interface{
        error
    }`),
			},
		},
	}
	found := types.Load(mockGoDir)
	expect(found).To.Have.Len(1).Else.FailNow()

	typs := found[0].ExportedTypes()
	expect(typs).To.Have.Len(1).Else.FailNow()

	spec := typs[0]
	expect(spec).Not.To.Be.Nil().Else.FailNow()

	inter := spec.Type.(*ast.InterfaceType)
	expect(inter.Methods.List).To.Have.Len(1).Else.FailNow()
	err := inter.Methods.List[0]
	expect(err.Names[0].String()).To.Equal("Error")
	_, isFunc := err.Type.(*ast.FuncType)
	expect(isFunc).To.Be.Ok()
}
コード例 #3
0
ファイル: types_test.go プロジェクト: nelsam/hel
func TestAliasedImportedDependencies(t *testing.T) {
	expect := expect.New(t)

	mockGoDir := newMockGoDir()
	mockGoDir.PathOutput.Path <- "/some/path"
	mockGoDir.PackagesOutput.Packages <- map[string]*ast.Package{
		"bar": {
			Name: "bar",
			Files: map[string]*ast.File{
				"foo.go": parse(expect, `

    import baz "some/path/to/foo"

    type Bar interface{
        Bar(baz.Foo) baz.Bar
    }`),
			},
		},
	}

	close(mockGoDir.ImportOutput.Err)
	pkgName := "foo"
	pkg := &ast.Package{
		Name: pkgName,
		Files: map[string]*ast.File{
			"foo.go": parse(expect, `
    type Foo interface {
        Foo()
    }

	type Bar interface {
		Bar()
	}`),
		},
	}
	mockGoDir.ImportOutput.Pkg <- pkg
	mockGoDir.ImportOutput.Name <- pkgName
	mockGoDir.ImportOutput.Pkg <- pkg
	mockGoDir.ImportOutput.Name <- pkgName

	found := types.Load(mockGoDir)
	expect(mockGoDir.ImportCalled).To.Have.Len(2)
	expect(<-mockGoDir.ImportInput.Path).To.Equal("some/path/to/foo")

	expect(found).To.Have.Len(1).Else.FailNow()
	mockables := found[0].ExportedTypes()
	expect(mockables).To.Have.Len(1)

	dependencies := found[0].Dependencies(mockables[0].Type.(*ast.InterfaceType))
	expect(dependencies).To.Have.Len(2)

	names := make(map[string]bool)
	for _, dependent := range dependencies {
		expect(dependent.PkgName).To.Equal("baz")
		expect(dependent.PkgPath).To.Equal("some/path/to/foo")
		names[dependent.Type.Name.String()] = true
	}
	expect(names).To.Equal(map[string]bool{"Foo": true, "Bar": true})
}
コード例 #4
0
ファイル: types_test.go プロジェクト: nelsam/hel
func TestFilter(t *testing.T) {
	expect := expect.New(t)

	mockGoDir := newMockGoDir()
	mockGoDir.PathOutput.Path <- "/some/path"
	mockGoDir.PackagesOutput.Packages <- map[string]*ast.Package{
		"foo": {
			Name: "foo",
			Files: map[string]*ast.File{
				"foo.go": parse(expect, `
    type Foo interface {}
    type Bar interface {}
    type FooBar interface {}
    type BarFoo interface {}
    `),
			},
		},
	}
	found := types.Load(mockGoDir)
	expect(found).To.Have.Len(1).Else.FailNow()
	expect(found[0].Len()).To.Equal(4)

	notFiltered := found.Filter()
	expect(notFiltered).To.Have.Len(1).Else.FailNow()
	expect(notFiltered[0].Len()).To.Equal(4)

	foos := found.Filter("Foo")
	expect(foos).To.Have.Len(1).Else.FailNow()
	expect(foos[0].Len()).To.Equal(1)
	expect(foos[0].ExportedTypes()[0].Name.String()).To.Equal("Foo")

	fooPrefixes := found.Filter("Foo.*")
	expect(fooPrefixes).To.Have.Len(1).Else.FailNow()
	expect(fooPrefixes[0].Len()).To.Equal(2)
	expectNamesToMatch(expect, fooPrefixes[0].ExportedTypes(), "Foo", "FooBar")

	fooPostfixes := found.Filter(".*Foo")
	expect(fooPostfixes).To.Have.Len(1).Else.FailNow()
	expect(fooPostfixes[0].Len()).To.Equal(2)
	expectNamesToMatch(expect, fooPostfixes[0].ExportedTypes(), "Foo", "BarFoo")

	fooContainers := found.Filter("Foo.*", ".*Foo")
	expect(fooContainers).To.Have.Len(1).Else.FailNow()
	expect(fooContainers[0].Len()).To.Equal(3)
	expectNamesToMatch(expect, fooContainers[0].ExportedTypes(), "Foo", "FooBar", "BarFoo")
}
コード例 #5
0
ファイル: types_test.go プロジェクト: nelsam/hel
func TestLocalDependencies(t *testing.T) {
	expect := expect.New(t)

	mockGoDir := newMockGoDir()
	mockGoDir.PathOutput.Path <- "/some/path"
	mockGoDir.PackagesOutput.Packages <- map[string]*ast.Package{
		"bar": {
			Name: "bar",
			Files: map[string]*ast.File{
				"bar.go": parse(expect, `

    type Bar interface{
        Bar(Foo) Foo
    }`),
				"foo.go": parse(expect, `

    type Foo interface {
        Foo()
    }`),
			},
		},
	}

	found := types.Load(mockGoDir)

	expect(found).To.Have.Len(1).Else.FailNow()
	mockables := found[0].ExportedTypes()
	expect(mockables).To.Have.Len(2)

	var foo, bar *ast.TypeSpec
	for _, mockable := range mockables {
		switch mockable.Name.String() {
		case "Bar":
			bar = mockable
		case "Foo":
			foo = mockable
		}
	}
	expect(bar).Not.To.Be.Nil().Else.FailNow()

	dependencies := found[0].Dependencies(bar.Type.(*ast.InterfaceType))
	expect(dependencies).To.Have.Len(1).Else.FailNow()
	expect(dependencies[0].Type).To.Equal(foo)
	expect(dependencies[0].PkgName).To.Equal("")
	expect(dependencies[0].PkgPath).To.Equal("")
}
コード例 #6
0
ファイル: types_test.go プロジェクト: jasonkeene/hel
func TestAnonymousLocalTypes(t *testing.T) {
	expect := expect.New(t)

	mockGoDir := newMockGoDir()
	mockGoDir.PathOutput.ret0 <- "/some/path"
	mockGoDir.PackagesOutput.ret0 <- map[string]*ast.Package{
		"foo": {
			Name: "foo",
			Files: map[string]*ast.File{
				"bar.go": parse(expect, `
    type Bar interface{
        Foo
        Bar()
    }`),
				"foo.go": parse(expect, `
    type Foo interface{
        Foo()
    }`),
			},
		},
	}
	found := types.Load(mockGoDir)
	expect(found).To.Have.Len(1)

	typs := found[0].ExportedTypes()
	expect(typs).To.Have.Len(2)

	spec := find(expect, typs, "Bar")
	expect(spec).Not.To.Be.Nil()
	inter := spec.Type.(*ast.InterfaceType)
	expect(inter.Methods.List).To.Have.Len(2)
	foo := inter.Methods.List[0]
	expect(foo.Names[0].String()).To.Equal("Foo")
	_, isFunc := foo.Type.(*ast.FuncType)
	expect(isFunc).To.Be.Ok()
}
コード例 #7
0
ファイル: main.go プロジェクト: jasonkeene/hel
func init() {
	output, err := exec.Command("which", "goimports").Output()
	if err != nil {
		fmt.Println("Could not locate goimports: ", err.Error())
		fmt.Println("If goimports is not installed, please install it somewhere in your path.  " +
			"See https://godoc.org/golang.org/x/tools/cmd/goimports.")
		os.Exit(1)
	}
	goimportsPath = strings.TrimSpace(string(output))

	cmd = &cobra.Command{
		Use:   "hel",
		Short: "A mock generator for Go",
		Long: "A simple mock generator.  The origin of the name is the Norse goddess, Hel, " +
			"who guards over the souls of those unworthy to enter Valhalla.  You can probably " +
			"guess how much I like mocks.",
		Run: func(cmd *cobra.Command, args []string) {
			if len(args) > 0 {
				fmt.Println("Invalid usage.\n")
				err := cmd.Help()
				if err != nil {
					panic(err)
				}
				os.Exit(1)
			}
			packagePatterns, err := cmd.Flags().GetStringSlice("package")
			if err != nil {
				panic(err)
			}
			typePatterns, err := cmd.Flags().GetStringSlice("type")
			if err != nil {
				panic(err)
			}
			outputName, err := cmd.Flags().GetString("output")
			if err != nil {
				panic(err)
			}
			chanSize, err := cmd.Flags().GetInt("chan-size")
			if err != nil {
				panic(err)
			}
			blockingReturn, err := cmd.Flags().GetBool("blocking-return")
			if err != nil {
				panic(err)
			}
			fmt.Printf("Loading directories matching pattern"+pluralize(packagePatterns, "", "s")+" %v", packagePatterns)
			var dirList []packages.Dir
			progress(func() {
				dirList = packages.Load(packagePatterns...)
			})
			fmt.Print("\n")
			fmt.Println("Found directories:")
			for _, dir := range dirList {
				fmt.Println("  " + dir.Path())
			}
			fmt.Print("\n")

			fmt.Printf("Loading interface types in matching directories")
			var typeDirs types.Dirs
			progress(func() {
				godirs := make([]types.GoDir, 0, len(dirList))
				for _, dir := range dirList {
					godirs = append(godirs, dir)
				}
				typeDirs = types.Load(godirs...).Filter(typePatterns...)
			})
			fmt.Print("\n\n")

			fmt.Printf("Generating mocks in output file %s", outputName)
			progress(func() {
				for _, typeDir := range typeDirs {
					mockPath, err := makeMocks(typeDir, outputName, chanSize, blockingReturn)
					if err != nil {
						panic(err)
					}
					if mockPath != "" {
						if err = exec.Command(goimportsPath, "-w", mockPath).Run(); err != nil {
							panic(err)
						}
					}
				}
			})
			fmt.Print("\n")
		},
	}
	cmd.Flags().StringSliceP("package", "p", []string{"."}, "The package(s) to generate mocks for.")
	cmd.Flags().StringSliceP("type", "t", []string{}, "The type(s) to generate mocks for.  If no types "+
		"are passed in, all exported interface types will be generated.")
	cmd.Flags().StringP("output", "o", "helheim_test.go", "The file to write generated mocks to.  Since hel does "+
		"not generate exported types, this file will be saved directly in all packages with generated mocks.  "+
		"Also note that, since the types are not exported, you will want the file to end in '_test.go'.")
	cmd.Flags().IntP("chan-size", "s", 100, "The size of channels used for method calls.")
	cmd.Flags().BoolP("blocking-return", "b", false, "Always block when returning from mock even if there is no return value.")
}
コード例 #8
0
ファイル: types_test.go プロジェクト: nelsam/hel
func TestAnonymousImportedTypes_Recursion(t *testing.T) {
	expect := expect.New(t)

	mockGoDir := newMockGoDir()
	mockGoDir.PathOutput.Path <- "/some/path"
	mockGoDir.PackagesOutput.Packages <- map[string]*ast.Package{
		"bar": {
			Name: "bar",
			Files: map[string]*ast.File{
				"foo.go": parse(expect, `

    import "some/path/to/foo"

    type Bar interface{
        foo.Foo
        Bar()
    }`),
			},
		},
	}

	close(mockGoDir.ImportOutput.Err)
	pkgName := "foo"
	pkg := &ast.Package{
		Name: pkgName,
		Files: map[string]*ast.File{
			"foo.go": parse(expect, `
    type Foo interface {
        Foo(func(X) Y) func(Y) X
    }`),
		},
	}
	mockGoDir.ImportOutput.Pkg <- pkg
	mockGoDir.ImportOutput.Name <- pkgName
	mockGoDir.ImportOutput.Pkg <- pkg
	mockGoDir.ImportOutput.Name <- pkgName
	mockGoDir.ImportOutput.Pkg <- pkg
	mockGoDir.ImportOutput.Name <- pkgName
	mockGoDir.ImportOutput.Pkg <- pkg
	mockGoDir.ImportOutput.Name <- pkgName
	mockGoDir.ImportOutput.Pkg <- pkg
	mockGoDir.ImportOutput.Name <- pkgName

	found := types.Load(mockGoDir)

	// One call for the initial import, four more for dependency checking
	expect(mockGoDir.ImportCalled).To.Have.Len(5)
	expect(<-mockGoDir.ImportInput.Path).To.Equal("some/path/to/foo")

	expect(found).To.Have.Len(1).Else.FailNow()
	typs := found[0].ExportedTypes()
	expect(typs).To.Have.Len(1).Else.FailNow()

	spec := typs[0]
	expect(spec).Not.To.Be.Nil().Else.FailNow()
	inter := spec.Type.(*ast.InterfaceType)
	expect(inter.Methods.List).To.Have.Len(2).Else.FailNow()

	foo := inter.Methods.List[0]
	expect(foo.Names[0].String()).To.Equal("Foo")
	f, isFunc := foo.Type.(*ast.FuncType)
	expect(isFunc).To.Be.Ok().Else.FailNow()
	expect(f.Params.List).To.Have.Len(1).Else.FailNow()
	expect(f.Results.List).To.Have.Len(1).Else.FailNow()

	input := f.Params.List[0]
	in, isFunc := input.Type.(*ast.FuncType)
	expect(isFunc).To.Be.Ok().Else.FailNow()

	expr, isSelector := in.Params.List[0].Type.(*ast.SelectorExpr)
	expect(isSelector).To.Be.Ok().Else.FailNow()
	expect(expr.X.(*ast.Ident).String()).To.Equal("foo")
	expect(expr.Sel.String()).To.Equal("X")
	expr, isSelector = in.Results.List[0].Type.(*ast.SelectorExpr)
	expect(isSelector).To.Be.Ok().Else.FailNow()
	expect(expr.X.(*ast.Ident).String()).To.Equal("foo")
	expect(expr.Sel.String()).To.Equal("Y")

	output := f.Params.List[0]
	out, isFunc := output.Type.(*ast.FuncType)
	expect(isFunc).To.Be.Ok().Else.FailNow()

	expr, isSelector = out.Params.List[0].Type.(*ast.SelectorExpr)
	expect(isSelector).To.Be.Ok().Else.FailNow()
	expect(expr.X.(*ast.Ident).String()).To.Equal("foo")
	expect(expr.Sel.String()).To.Equal("X")
	expr, isSelector = out.Results.List[0].Type.(*ast.SelectorExpr)
	expect(isSelector).To.Be.Ok().Else.FailNow()
	expect(expr.X.(*ast.Ident).String()).To.Equal("foo")
	expect(expr.Sel.String()).To.Equal("Y")
}
コード例 #9
0
ファイル: types_test.go プロジェクト: nelsam/hel
func TestAnonymousAliasedImportedTypes(t *testing.T) {
	expect := expect.New(t)

	mockGoDir := newMockGoDir()
	mockGoDir.PathOutput.Path <- "/some/path"
	mockGoDir.PackagesOutput.Packages <- map[string]*ast.Package{
		"bar": {
			Name: "bar",
			Files: map[string]*ast.File{
				"foo.go": parse(expect, `

    import baz "some/path/to/foo"

    type Bar interface{
        baz.Foo
        Bar()
    }`),
			},
		},
	}

	close(mockGoDir.ImportOutput.Err)
	pkgName := "foo"
	pkg := &ast.Package{
		Name: pkgName,
		Files: map[string]*ast.File{
			"foo.go": parse(expect, `
    type Foo interface {
        Foo(x X) Y
    }

	type X int
	type Y int`),
		},
	}
	mockGoDir.ImportOutput.Pkg <- pkg
	mockGoDir.ImportOutput.Name <- pkgName
	mockGoDir.ImportOutput.Pkg <- pkg
	mockGoDir.ImportOutput.Name <- pkgName
	mockGoDir.ImportOutput.Pkg <- pkg
	mockGoDir.ImportOutput.Name <- pkgName

	found := types.Load(mockGoDir)

	// 3 calls: 1 for the initial import, then deps imports for X and Y
	expect(mockGoDir.ImportCalled).To.Have.Len(3)
	expect(<-mockGoDir.ImportInput.Path).To.Equal("some/path/to/foo")

	expect(found).To.Have.Len(1).Else.FailNow()
	typs := found[0].ExportedTypes()
	expect(typs).To.Have.Len(1).Else.FailNow()

	spec := typs[0]
	expect(spec).Not.To.Be.Nil().Else.FailNow()
	inter := spec.Type.(*ast.InterfaceType)
	expect(inter.Methods.List).To.Have.Len(2).Else.FailNow()

	foo := inter.Methods.List[0]
	expect(foo.Names[0].String()).To.Equal("Foo")
	f, isFunc := foo.Type.(*ast.FuncType)
	expect(isFunc).To.Be.Ok().Else.FailNow()
	expect(f.Params.List).To.Have.Len(1).Else.FailNow()
	expect(f.Results.List).To.Have.Len(1).Else.FailNow()
	expr, isSelector := f.Params.List[0].Type.(*ast.SelectorExpr)
	expect(isSelector).To.Be.Ok().Else.FailNow()
	expect(expr.X.(*ast.Ident).String()).To.Equal("baz")
	expect(expr.Sel.String()).To.Equal("X")
	expr, isSelector = f.Results.List[0].Type.(*ast.SelectorExpr)
	expect(isSelector).To.Be.Ok().Else.FailNow()
	expect(expr.X.(*ast.Ident).String()).To.Equal("baz")
	expect(expr.Sel.String()).To.Equal("Y")
}
コード例 #10
0
ファイル: types_test.go プロジェクト: jasonkeene/hel
func TestAnonymousImportedTypes_Recursion(t *testing.T) {
	expect := expect.New(t)

	mockGoDir := newMockGoDir()
	mockGoDir.PathOutput.ret0 <- "/some/path"
	mockGoDir.PackagesOutput.ret0 <- map[string]*ast.Package{
		"bar": {
			Name: "bar",
			Files: map[string]*ast.File{
				"foo.go": parse(expect, `

    import "some/path/to/foo"

    type Bar interface{
        foo.Foo
        Bar()
    }`),
			},
		},
	}

	close(mockGoDir.ImportOutput.ret1)
	mockGoDir.ImportOutput.ret0 <- &ast.Package{
		Name: "foo",
		Files: map[string]*ast.File{
			"foo.go": parse(expect, `
    type Foo interface {
        Foo(func(X) Y) func(Y) X
    }`),
		},
	}

	found := types.Load(mockGoDir)
	expect(mockGoDir.ImportCalled).To.Have.Len(1)
	expect(<-mockGoDir.ImportInput.path).To.Equal("some/path/to/foo")
	expect(<-mockGoDir.ImportInput.pkg).To.Equal("foo")

	expect(found).To.Have.Len(1)
	typs := found[0].ExportedTypes()
	expect(typs).To.Have.Len(1)

	spec := typs[0]
	expect(spec).Not.To.Be.Nil()
	inter := spec.Type.(*ast.InterfaceType)
	expect(inter.Methods.List).To.Have.Len(2)

	foo := inter.Methods.List[0]
	expect(foo.Names[0].String()).To.Equal("Foo")
	f, isFunc := foo.Type.(*ast.FuncType)
	expect(isFunc).To.Be.Ok()
	expect(f.Params.List).To.Have.Len(1)
	expect(f.Results.List).To.Have.Len(1)

	input := f.Params.List[0]
	in, isFunc := input.Type.(*ast.FuncType)
	expect(isFunc).To.Be.Ok()

	expr, isSelector := in.Params.List[0].Type.(*ast.SelectorExpr)
	expect(isSelector).To.Be.Ok()
	expect(expr.X.(*ast.Ident).String()).To.Equal("foo")
	expect(expr.Sel.String()).To.Equal("X")
	expr, isSelector = in.Results.List[0].Type.(*ast.SelectorExpr)
	expect(isSelector).To.Be.Ok()
	expect(expr.X.(*ast.Ident).String()).To.Equal("foo")
	expect(expr.Sel.String()).To.Equal("Y")

	output := f.Params.List[0]
	out, isFunc := output.Type.(*ast.FuncType)
	expect(isFunc).To.Be.Ok()

	expr, isSelector = out.Params.List[0].Type.(*ast.SelectorExpr)
	expect(isSelector).To.Be.Ok()
	expect(expr.X.(*ast.Ident).String()).To.Equal("foo")
	expect(expr.Sel.String()).To.Equal("X")
	expr, isSelector = out.Results.List[0].Type.(*ast.SelectorExpr)
	expect(isSelector).To.Be.Ok()
	expect(expr.X.(*ast.Ident).String()).To.Equal("foo")
	expect(expr.Sel.String()).To.Equal("Y")
}