Giter Site home page Giter Site logo

hel's Introduction

Hel has moved to sr.ht!

I don't trust or support Microsoft. I've weight the options and decided to move hel to sr.ht. Please submit issues and pull requests there.

No more releases will be made on github.

See the main repo's README.md for details about hel!

hel's People

Contributors

anon1efergwerfwer avatar jasonkeene avatar nelsam avatar peefourtee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

hel's Issues

Panic when generating mock in different package

We are trying to land the mock in a package other than where the interface is defined.

my_interface.go

package xyz

//go:generate hel -o ../anotherpackage/mock_my_test.go -t MyInterface

type MyInterface interface {
    DoSomething() (err error)
}

Nested Types Need Local Package Name

Our local package name logic is working in most cases, but I've just encountered a case where chan (chan<- LocalType) does not have the local name prepended.

Support Types Implementing Interface Types

We usually don't want to generate mocks for interface types in other packages, to help reduce the urge to use massive interface types as the source of truth for what a type can do. However, there's an exception to this:

// foo/foo.go

type Baz interface{
    //...
}

type Bar interface {
    Bar(Baz)
}

type Foo struct {
    //...
}

func NewFoo(bar Bar) Foo {
    //...
}

// bar/bar.go

type Bar struct {}

func (b *Bar) Bar(foo.Baz)

In this case, Bar has a method that must accept an interface type from another package. Testing this code with hel becomes extremely difficult.

For cases like this, we should provide some way to relate the concrete type back to the interface type that is being implemented. It's easy enough to construct an interface type from the implemented methods, but searching all packages for interface types that are a subset of those methods may not be feasible. We may have to handle some syntax in the local code to deal with that.

As a worst case, we could handle something like this:

// Window is a type to handle windows.
//
// implements: (git.sr.ht/~nelsam/grpc).Window
type Window struct{}

Imports for packaged structs

Vaguely speaking: when i have an interface whose return type is a struct that lives in the same package as the interface, go generate with nelsam/hel will create mock objects without importing the package and its struct. So, the mock object's return type will be not-found, instead of specifically imported (from the same package).

Example:

package foo

type Bar struct {}
type Gaz interface {
  Whatever() []Bar
}

Will output something like:

package foo_test

type mockGaz struct {
    WhateverCalled chan bool
        WhateverOutput struct {
        Ret0 chan []Bar
    }
}

When it should be:

package foo_test 

import "foo"

type mockGaz struct {
    WhateverCalled chan bool
        WhateverOutput struct {
        Ret0 chan []foo.Bar
    }
}

Fix Types Which Return Directional Channels

Given:

type Foo interface {
    Foo() (<-chan struct{})
}

The generated type looks like:

type mockFoo struct {
    FooOutput struct {
        ret0 chan<- chan struct{}
    }
}

This could be an upstream issue with goimports/gofmt, or it could be that making a chan of directional chans isn't supported.

Wrong Package Selector for Inputs/Outputs

The package selector for inputs/outputs is wrong for functions/methods returning types from other packages.

I think this should be a fairly uncommon occurrence, but it's sometimes unavoidable.

Relative Imports

We need to support relative imports for things like flattening imports and resolving dependent types.

Variadic function parameters

When mocking a function with variadic parameters, the arguments channel is created a channel of a variadic type.

Package Alias Issues

When mocking a type which has other interface types as dependencies, the package name used as a selector is the local alias. This causes issues with the later call to goimports, which can't find a matching package.

v2 is not go gettable

I got a 410 when attempting to go get hel:

go get -v -u github.com/nelsam/[email protected]
go: finding github.com v2.3.3
go: finding github.com/nelsam v2.3.3
go: finding github.com/nelsam/hel v2.3.3
go get github.com/nelsam/[email protected]: github.com/nelsam/[email protected]: reading https://proxy.golang.org/github.com/nelsam/hel/@v/v2.3.3.info: 410 Gone

I set GOPROXY to direct and got the following:

go get -v -u github.com/nelsam/[email protected]
go: finding github.com/nelsam/hel v2.3.3
go get github.com/nelsam/[email protected]: github.com/nelsam/[email protected]: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2

Thanks Sam!

Doesn't include package name if interface 'A' uses interface 'B'

Sender (used in SenderStore) should have package name.

package routing_test

type mockSender struct {
    SendCalled chan bool
    SendInput  struct {
        Data chan []byte
    }
}

func newMockSender() *mockSender {
    m := &mockSender{}
    m.SendCalled = make(chan bool, 100)
    m.SendInput.Data = make(chan []byte, 100)
    return m
}
func (m *mockSender) Send(data []byte) {
    m.SendCalled <- true
    m.SendInput.Data <- data
}

type mockSenderStore struct {
    TraverseCalled chan bool
    TraverseInput  struct {
        Callback chan func(sender Sender)
    }
}

func newMockSenderStore() *mockSenderStore {
    m := &mockSenderStore{}
    m.TraverseCalled = make(chan bool, 100)
    m.TraverseInput.Callback = make(chan func(sender Sender), 100)
    return m
}
func (m *mockSenderStore) Traverse(callback func(sender Sender)) {
    m.TraverseCalled <- true
    m.TraverseInput.Callback <- callback
}

Panics when embedding interface

With the below interfaces:

type A interface{
   Something() error
}

type B interface{
  AnotherThing()(A, error)
}

I get the following Panic:

Loading interface types in matching directories.panic: Can't find anonymous type error
	panic: interface conversion: ast.Expr is *ast.Ident, not *ast.FuncType

goroutine 1 [running]:
panic(0x1f55e0, 0xc4249c8780)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
github.com/nelsam/hel/types.dependencies(0xc420a433c0, 0xc4200a6000, 0xc, 0x14, 0xc420bc7a40, 0x6, 0x8, 0x31e060, 0xc4200154b0, 0x34faf0, ...)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:160 +0x542
github.com/nelsam/hel/types.loadPkgTypeSpecs.func1(0xc420c94260, 0xc420ad2178, 0xc420ad1f98, 0x31e060, 0xc4200154b0)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:251 +0x138
panic(0x1ef020, 0xc420c92420)
	/usr/local/go/src/runtime/panic.go:458 +0x243
github.com/nelsam/hel/types.findAnonMethods(0xc420a43280, 0xc4200a6000, 0xc, 0x14, 0xc420bc7a40, 0x6, 0x8, 0x31e060, 0xc4200154b0, 0xc420c07b10, ...)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:391 +0x22a
github.com/nelsam/hel/types.flatten(0xc420a433c0, 0xc4200a6000, 0xc, 0x14, 0xc420bc7a40, 0x6, 0x8, 0x31e060, 0xc4200154b0)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:308 +0x544
github.com/nelsam/hel/types.flattenAnon(0xc420c8d840, 0x7, 0x8, 0xc4200a6000, 0xc, 0x14, 0xc420bc7a40, 0x6, 0x8, 0x31e060, ...)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:294 +0xd5
github.com/nelsam/hel/types.loadPkgTypeSpecs.func2(0xc420c8d840, 0x7, 0x8, 0xc420c94260, 0xc420bc7a40, 0x6, 0x8, 0x31e060, 0xc4200154b0)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:269 +0xa6
github.com/nelsam/hel/types.loadPkgTypeSpecs(0xc420fb1e00, 0x31e060, 0xc4200154b0, 0x0, 0x0, 0x0, 0xc420c90570, 0x1)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:274 +0x28e
github.com/nelsam/hel/types.Dir.addPkg(0x0, 0x0, 0x0, 0x0, 0xc420c923a0, 0x8, 0x0, 0x0, 0x0, 0xc420c90540, ...)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:81 +0x90
github.com/nelsam/hel/types.loadDependencies(0xc4201bbfb0, 0xc4200d6000, 0x18, 0x18, 0xc42049cc00, 0x15, 0x20, 0x31e060, 0xc4200154b0, 0x0, ...)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:220 +0x74e
github.com/nelsam/hel/types.dependencies(0xc420763ac0, 0xc4200d6000, 0x18, 0x18, 0xc42049cc00, 0x15, 0x20, 0x31e060, 0xc4200154b0, 0x34faf0, ...)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:162 +0x246
github.com/nelsam/hel/types.loadPkgTypeSpecs.func1(0xc420ae9060, 0xc420ad2bc8, 0xc420ad29e8, 0x31e060, 0xc4200154b0)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:251 +0x138
github.com/nelsam/hel/types.loadPkgTypeSpecs(0xc42022e420, 0x31e060, 0xc4200154b0, 0x0, 0x0, 0x0, 0xc420ae2d50, 0x1)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:274 +0x28e
github.com/nelsam/hel/types.Dir.addPkg(0x0, 0x0, 0x0, 0x0, 0xc420ae4bb3, 0x9, 0x0, 0x0, 0x0, 0xc420ae2d20, ...)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:81 +0x90
github.com/nelsam/hel/types.loadDependencies(0xc420102420, 0xc420030208, 0x1, 0x1, 0xc420015e90, 0x2, 0x2, 0x31e060, 0xc4200154b0, 0xc4200dd060, ...)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:220 +0x74e
github.com/nelsam/hel/types.dependencies(0xc4200fd7c0, 0xc420030208, 0x1, 0x1, 0xc420015e90, 0x2, 0x2, 0x31e060, 0xc4200154b0, 0x29a91, ...)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:161 +0x19a
github.com/nelsam/hel/types.loadPkgTypeSpecs.func1(0xc4201060c0, 0xc420ad3618, 0xc420ad3438, 0x31e060, 0xc4200154b0)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:251 +0x138
github.com/nelsam/hel/types.loadPkgTypeSpecs(0xc420102300, 0x31e060, 0xc4200154b0, 0x0, 0x0, 0x0, 0xc420102ab0, 0x0)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:274 +0x28e
github.com/nelsam/hel/types.Dir.addPkg(0xc420016a80, 0x30, 0xc420015537, 0x9, 0xc420015537, 0x9, 0x0, 0x0, 0x0, 0xc4200119b0, ...)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:81 +0x90
github.com/nelsam/hel/types.Load(0xc4200154a0, 0x1, 0x1, 0x31e060, 0xc4200154b0, 0x1)
	/Users/ninok/go/src/github.com/nelsam/hel/types/types.go:127 +0x232
main.init.1.func1.2()
	/Users/ninok/go/src/github.com/nelsam/hel/main.go:88 +0x21d
main.progress(0xc420ad3c80)
	/Users/ninok/go/src/github.com/nelsam/hel/main.go:147 +0xc8
main.init.1.func1(0xc42009c400, 0xc4200169c0, 0x0, 0x4)
	/Users/ninok/go/src/github.com/nelsam/hel/main.go:89 +0x810
github.com/spf13/cobra.(*Command).execute(0xc42009c400, 0xc42000c150, 0x4, 0x4, 0xc42009c400, 0xc42000c150)
	/Users/ninok/go/src/github.com/spf13/cobra/command.go:565 +0x411
github.com/spf13/cobra.(*Command).ExecuteC(0xc42009c400, 0x0, 0x0, 0x0)
	/Users/ninok/go/src/github.com/spf13/cobra/command.go:651 +0x367
github.com/spf13/cobra.(*Command).Execute(0xc42009c400, 0x0, 0xc420000340)
	/Users/ninok/go/src/github.com/spf13/cobra/command.go:610 +0x2b
main.main()
	/Users/ninok/go/src/github.com/nelsam/hel/main.go:184 +0x2d
session_handler.go:9: running "hel": exit status 2

Any suggestions?

Add comment to generated code

Hey Sam,

Could we get a comment added to the top of each generated file indicating the source of the generated code and some sort of warning about altering the code?

Hope all is well.

Thanks,
Dwayne

Ensure that Mocks Use Package Selectors

If a mock is in a different package than the package containing the interface, some types may need the package name added as a prefix. E.g.

package bacon

type Bar int

type Foo interface {
  Foo() Bar
}

In the above, I'm pretty sure that we need some additional logic to change Foo() Bar to Foo() bacon.Bar if the generated mock is in the bacon_test package.

Creates Mocks for Unexported Types When Not In Same Package

Some of this may be easy, but I expect at least some parts to be difficult. Still, It's at least worth doing the easier stuff; and I'd like to do the more difficult stuff some day. Basically, when the mock is in a separate test package (which is the default), we should ignore any interface types that should not be implemented outside of the main package (i.e. are unexported, include unexported methods, or include unexported types in method params or results).

  • type foo interface {} should be ignored (unexported type)
  • type Foo interface { foo() } should be ignored (unexported method)
  • type Foo interface { Foo(f foo) } should be ignored (unexported type in param/return value)

No CI

Your README indicates that you plan to hook one up, so this is more of a checkbox.

Package aliases are not replicated in mock

Mock actually ends up being invalid.

Interface:

package foo

import baz "bar"

type Buz interface {
    Close() (baz.Thing)
}

Generated a mock with baz prefixes but no import for baz or bar.

Duplicate Dependencies

When two types (or even two methods on the same type?) both depend on the same type, we get a duplicate mock for that dependency. Dependencies should be de-duped.

Types local to an interface's package are not updated with the package name when writing the mock to another package

Issue #4 showed us that types local to a package containing an interface that we're mocking will not get their package name added automatically when they're written to a file with a different package name.

This means that we'll need to figure out a way to detect types being used as parameters or results that are local to an interface's package and include the package name if the test package is different from the main package.

Struct members have '_'

Struct fields are generated with an underscore to disambiguate from the receiver. This isn't necessary and fails to compile as the underscore is not included in field names when assigning to them in the mock implementations:

struct field definition:

SendMsgInput  struct {
	M_ chan interface{}
}

struct field use:

func (m *mockDopplerIngestor_PushServer) RecvMsg(m_ interface{}) error {
	m.RecvMsgCalled <- true
	m.RecvMsgInput.M <- m_
	return <-m.RecvMsgOutput.Ret0
}

/cc @jasonkeene

No Support For Anonymous Embedded Interfaces

Consider:

type Foo interface {
  Foo() string
}

type Bar interface {
  Foo
  Bar() int
}

Currently, the generated mockBar would only have the Bar() method, which is obviously wrong.

Explore Struct Types For Params and Results

Given:

type Foo interface {
    Bar(bacon string, eggs int) (int, string)
}

We currently generate (give or take):

type mockFoo interface {
    BarCalled chan bool
    BarInput struct {
        bacon chan string
        eggs chan int
    }
    BarOutput struct {
        ret0 chan int
        ret1 chan string
    }
}

func (m *mockFoo) Foo(bacon string, eggs int) (int, string) {
    m.BarCalled <- true
    m.BarInput.bacon <- bacon
    m.BarInput.eggs <- eggs
    return <-m.BarOutput.ret0, <-m.BarOutput.ret1
}

We should explore the possibility of changing that to something along the lines of:

type mockFoo_input {
    bacon string
    eggs int
}

type mockFoo_output {
    ret0 int
    ret1 string
}

type mockFoo interface {
    BarInput chan mockFoo_input
    BarOutput chan mockFoo_output
}

func (m *mockFoo) Foo(bacon string, eggs int) (int, string) {
    m.BarInput <- mockFoo_input{
        bacon: bacon,
        eggs: eggs,
    }
    ret := <-m.BarOutput
    return ret.ret0, ret.ret1
}

No way to have a test only package pull in interfaces

Say we have an integration test package that requires a mock from an interface. Hel does not analyze the test code at all.

I think I would would want to use the:

//go:generate hel --type somepackage.Foo --output mock_foo_test.go

syntax to indicate that I would want a certain mock.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.