github.com/Capventis/moq@v0.2.6-0.20220316100624-05dd47497214/pkg/moq/moq_test.go (about)

     1  package moq
     2  
     3  import (
     4  	"bytes"
     5  	"flag"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"path/filepath"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/pmezard/go-difflib/difflib"
    16  )
    17  
    18  var update = flag.Bool("update", false, "Update golden files.")
    19  
    20  func TestMoq(t *testing.T) {
    21  	m, err := New(Config{SrcDir: "testpackages/example"})
    22  	if err != nil {
    23  		t.Fatalf("moq.New: %s", err)
    24  	}
    25  	var buf bytes.Buffer
    26  	err = m.Mock(&buf, "PersonStore")
    27  	if err != nil {
    28  		t.Errorf("m.Mock: %s", err)
    29  	}
    30  	s := buf.String()
    31  	// assertions of things that should be mentioned
    32  	var strs = []string{
    33  		"package example",
    34  		"type PersonStoreMock struct",
    35  		"CreateFunc func(ctx context.Context, person *Person, confirm bool) error",
    36  		"GetFunc func(ctx context.Context, id string) (*Person, error)",
    37  		"func (mock *PersonStoreMock) Create(ctx context.Context, person *Person, confirm bool) error",
    38  		"func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*Person, error)",
    39  		"panic(\"PersonStoreMock.CreateFunc: method is nil but PersonStore.Create was just called\")",
    40  		"panic(\"PersonStoreMock.GetFunc: method is nil but PersonStore.Get was just called\")",
    41  		"mock.lockGet.Lock()",
    42  		"mock.calls.Get = append(mock.calls.Get, callInfo)",
    43  		"mock.lockGet.Unlock()",
    44  		"// ID is the id argument value",
    45  	}
    46  	for _, str := range strs {
    47  		if !strings.Contains(s, str) {
    48  			t.Errorf("expected but missing: \"%s\"", str)
    49  		}
    50  	}
    51  }
    52  
    53  func TestMoqWithStaticCheck(t *testing.T) {
    54  	m, err := New(Config{SrcDir: "testpackages/example"})
    55  	if err != nil {
    56  		t.Fatalf("moq.New: %s", err)
    57  	}
    58  	var buf bytes.Buffer
    59  	err = m.Mock(&buf, "PersonStore")
    60  	if err != nil {
    61  		t.Errorf("m.Mock: %s", err)
    62  	}
    63  	s := buf.String()
    64  	// assertions of things that should be mentioned
    65  	var strs = []string{
    66  		"package example",
    67  		"var _ PersonStore = &PersonStoreMock{}",
    68  		"type PersonStoreMock struct",
    69  		"CreateFunc func(ctx context.Context, person *Person, confirm bool) error",
    70  		"GetFunc func(ctx context.Context, id string) (*Person, error)",
    71  		"func (mock *PersonStoreMock) Create(ctx context.Context, person *Person, confirm bool) error",
    72  		"func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*Person, error)",
    73  		"panic(\"PersonStoreMock.CreateFunc: method is nil but PersonStore.Create was just called\")",
    74  		"panic(\"PersonStoreMock.GetFunc: method is nil but PersonStore.Get was just called\")",
    75  		"mock.lockGet.Lock()",
    76  		"mock.calls.Get = append(mock.calls.Get, callInfo)",
    77  		"mock.lockGet.Unlock()",
    78  		"// ID is the id argument value",
    79  	}
    80  	for _, str := range strs {
    81  		if !strings.Contains(s, str) {
    82  			t.Errorf("expected but missing: \"%s\"", str)
    83  		}
    84  	}
    85  }
    86  
    87  func TestMoqWithAlias(t *testing.T) {
    88  	m, err := New(Config{SrcDir: "testpackages/example"})
    89  	if err != nil {
    90  		t.Fatalf("moq.New: %s", err)
    91  	}
    92  	var buf bytes.Buffer
    93  	err = m.Mock(&buf, "PersonStore:AnotherPersonStoreMock")
    94  	if err != nil {
    95  		t.Errorf("m.Mock: %s", err)
    96  	}
    97  	s := buf.String()
    98  	// assertions of things that should be mentioned
    99  	var strs = []string{
   100  		"package example",
   101  		"type AnotherPersonStoreMock struct",
   102  		"CreateFunc func(ctx context.Context, person *Person, confirm bool) error",
   103  		"GetFunc func(ctx context.Context, id string) (*Person, error)",
   104  		"func (mock *AnotherPersonStoreMock) Create(ctx context.Context, person *Person, confirm bool) error",
   105  		"func (mock *AnotherPersonStoreMock) Get(ctx context.Context, id string) (*Person, error)",
   106  		"panic(\"AnotherPersonStoreMock.CreateFunc: method is nil but PersonStore.Create was just called\")",
   107  		"panic(\"AnotherPersonStoreMock.GetFunc: method is nil but PersonStore.Get was just called\")",
   108  		"mock.lockGet.Lock()",
   109  		"mock.calls.Get = append(mock.calls.Get, callInfo)",
   110  		"mock.lockGet.Unlock()",
   111  		"// ID is the id argument value",
   112  	}
   113  	for _, str := range strs {
   114  		if !strings.Contains(s, str) {
   115  			t.Errorf("expected but missing: \"%s\"", str)
   116  		}
   117  	}
   118  }
   119  
   120  func TestMoqExplicitPackage(t *testing.T) {
   121  	m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different"})
   122  	if err != nil {
   123  		t.Fatalf("moq.New: %s", err)
   124  	}
   125  	var buf bytes.Buffer
   126  	err = m.Mock(&buf, "PersonStore")
   127  	if err != nil {
   128  		t.Errorf("m.Mock: %s", err)
   129  	}
   130  	s := buf.String()
   131  	// assertions of things that should be mentioned
   132  	var strs = []string{
   133  		"package different",
   134  		"type PersonStoreMock struct",
   135  		"CreateFunc func(ctx context.Context, person *example.Person, confirm bool) error",
   136  		"GetFunc func(ctx context.Context, id string) (*example.Person, error)",
   137  		"func (mock *PersonStoreMock) Create(ctx context.Context, person *example.Person, confirm bool) error",
   138  		"func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*example.Person, error)",
   139  	}
   140  	for _, str := range strs {
   141  		if !strings.Contains(s, str) {
   142  			t.Errorf("expected but missing: \"%s\"", str)
   143  		}
   144  	}
   145  }
   146  
   147  func TestMoqExplicitPackageWithStaticCheck(t *testing.T) {
   148  	m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different"})
   149  	if err != nil {
   150  		t.Fatalf("moq.New: %s", err)
   151  	}
   152  	var buf bytes.Buffer
   153  	err = m.Mock(&buf, "PersonStore")
   154  	if err != nil {
   155  		t.Errorf("m.Mock: %s", err)
   156  	}
   157  	s := buf.String()
   158  	// assertions of things that should be mentioned
   159  	var strs = []string{
   160  		"package different",
   161  		"var _ example.PersonStore = &PersonStoreMock{}",
   162  		"type PersonStoreMock struct",
   163  		"CreateFunc func(ctx context.Context, person *example.Person, confirm bool) error",
   164  		"GetFunc func(ctx context.Context, id string) (*example.Person, error)",
   165  		"func (mock *PersonStoreMock) Create(ctx context.Context, person *example.Person, confirm bool) error",
   166  		"func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*example.Person, error)",
   167  	}
   168  	for _, str := range strs {
   169  		if !strings.Contains(s, str) {
   170  			t.Errorf("expected but missing: \"%s\"", str)
   171  		}
   172  	}
   173  }
   174  
   175  func TestMoqSkipEnsure(t *testing.T) {
   176  	m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different", SkipEnsure: true})
   177  	if err != nil {
   178  		t.Fatalf("moq.New: %s", err)
   179  	}
   180  	var buf bytes.Buffer
   181  	err = m.Mock(&buf, "PersonStore")
   182  	if err != nil {
   183  		t.Errorf("m.Mock: %s", err)
   184  	}
   185  	s := buf.String()
   186  	// assertions of things that should be mentioned
   187  	var strs = []string{
   188  		"package different",
   189  		"type PersonStoreMock struct",
   190  		"CreateFunc func(ctx context.Context, person *example.Person, confirm bool) error",
   191  		"GetFunc func(ctx context.Context, id string) (*example.Person, error)",
   192  		"func (mock *PersonStoreMock) Create(ctx context.Context, person *example.Person, confirm bool) error",
   193  		"func (mock *PersonStoreMock) Get(ctx context.Context, id string) (*example.Person, error)",
   194  	}
   195  	for _, str := range strs {
   196  		if !strings.Contains(s, str) {
   197  			t.Errorf("expected but missing: \"%s\"", str)
   198  		}
   199  	}
   200  }
   201  
   202  func TestNotCreatingEmptyDirWhenPkgIsGiven(t *testing.T) {
   203  	m, err := New(Config{SrcDir: "testpackages/example", PkgName: "different"})
   204  	if err != nil {
   205  		t.Fatalf("moq.New: %s", err)
   206  	}
   207  	var buf bytes.Buffer
   208  	err = m.Mock(&buf, "PersonStore")
   209  	if err != nil {
   210  		t.Errorf("m.Mock: %s", err)
   211  	}
   212  	s := buf.String()
   213  	if len(s) == 0 {
   214  		t.Fatalf("mock should be generated")
   215  	}
   216  	if _, err := os.Stat("testpackages/example/different"); !os.IsNotExist(err) {
   217  		t.Fatalf("no empty dir should be created by moq")
   218  	}
   219  }
   220  
   221  // TestVariadicArguments tests to ensure variadic work as
   222  // expected.
   223  // see https://github.com/matryer/moq/issues/5
   224  func TestVariadicArguments(t *testing.T) {
   225  	m, err := New(Config{SrcDir: "testpackages/variadic"})
   226  	if err != nil {
   227  		t.Fatalf("moq.New: %s", err)
   228  	}
   229  	var buf bytes.Buffer
   230  	err = m.Mock(&buf, "Greeter")
   231  	if err != nil {
   232  		t.Errorf("m.Mock: %s", err)
   233  	}
   234  	s := buf.String()
   235  	// assertions of things that should be mentioned
   236  	var strs = []string{
   237  		"package variadic",
   238  		"type GreeterMock struct",
   239  		"GreetFunc func(ctx context.Context, names ...string) string",
   240  		"return mock.GreetFunc(ctx, names...)",
   241  	}
   242  	for _, str := range strs {
   243  		if !strings.Contains(s, str) {
   244  			t.Errorf("expected but missing: \"%s\"", str)
   245  		}
   246  	}
   247  }
   248  
   249  func TestNothingToReturn(t *testing.T) {
   250  	m, err := New(Config{SrcDir: "testpackages/example"})
   251  	if err != nil {
   252  		t.Fatalf("moq.New: %s", err)
   253  	}
   254  	var buf bytes.Buffer
   255  	err = m.Mock(&buf, "PersonStore")
   256  	if err != nil {
   257  		t.Errorf("m.Mock: %s", err)
   258  	}
   259  	s := buf.String()
   260  	if strings.Contains(s, `return mock.ClearCacheFunc(id)`) {
   261  		t.Errorf("should not have return for items that have no return arguments")
   262  	}
   263  	// assertions of things that should be mentioned
   264  	var strs = []string{
   265  		"mock.ClearCacheFunc(id)",
   266  	}
   267  	for _, str := range strs {
   268  		if !strings.Contains(s, str) {
   269  			t.Errorf("expected but missing: \"%s\"", str)
   270  		}
   271  	}
   272  }
   273  
   274  func TestImports(t *testing.T) {
   275  	m, err := New(Config{SrcDir: "testpackages/imports/two"})
   276  	if err != nil {
   277  		t.Fatalf("moq.New: %s", err)
   278  	}
   279  	var buf bytes.Buffer
   280  	err = m.Mock(&buf, "DoSomething")
   281  	if err != nil {
   282  		t.Errorf("m.Mock: %s", err)
   283  	}
   284  	s := buf.String()
   285  	var strs = []string{
   286  		`	"sync"`,
   287  		`	"github.com/matryer/moq/pkg/moq/testpackages/imports/one"`,
   288  	}
   289  	for _, str := range strs {
   290  		if !strings.Contains(s, str) {
   291  			t.Errorf("expected but missing: \"%s\"", str)
   292  		}
   293  		if len(strings.Split(s, str)) > 2 {
   294  			t.Errorf("more than one: \"%s\"", str)
   295  		}
   296  	}
   297  }
   298  
   299  func TestMockGolden(t *testing.T) {
   300  	cases := []struct {
   301  		name       string
   302  		cfg        Config
   303  		interfaces []string
   304  		goldenFile string
   305  	}{
   306  		{
   307  			// Tests to ensure slice return data type works as expected.
   308  			// See https://github.com/matryer/moq/issues/124
   309  			name:       "SliceResult",
   310  			cfg:        Config{SrcDir: "testpackages/variadic"},
   311  			interfaces: []string{"Echoer"},
   312  			goldenFile: filepath.Join("testpackages/variadic", "echoer.golden.go"),
   313  		},
   314  		{
   315  			// Tests generation of mock where a method on the interface uses a
   316  			// blank identifier.
   317  			// See https://github.com/matryer/moq/issues/70
   318  			name:       "BlankID",
   319  			cfg:        Config{SrcDir: "testpackages/blankid"},
   320  			interfaces: []string{"Swallower"},
   321  			goldenFile: filepath.Join("testpackages/blankid", "swallower.golden.go"),
   322  		},
   323  		{
   324  			name:       "ChannelNames",
   325  			cfg:        Config{SrcDir: "testpackages/channels", StubImpl: true},
   326  			interfaces: []string{"Queuer"},
   327  			goldenFile: filepath.Join("testpackages/channels", "queuer_moq.golden.go"),
   328  		},
   329  		{
   330  			// Tests generation of mock when the interface imports a different
   331  			// package by the same name as it's own.
   332  			// See https://github.com/matryer/moq/issues/94
   333  			name:       "PkgShadow",
   334  			cfg:        Config{SrcDir: "testpackages/shadow/http", PkgName: "mock"},
   335  			interfaces: []string{"Thing"},
   336  			goldenFile: filepath.Join("testpackages/shadow/mock", "thing_moq.golden.go"),
   337  		},
   338  		{
   339  			// Tests generation of mock when a method parameter shadows an
   340  			// imported package name.
   341  			name:       "ParamShadow",
   342  			cfg:        Config{SrcDir: "testpackages/shadow"},
   343  			interfaces: []string{"Shadower"},
   344  			goldenFile: filepath.Join("testpackages/shadow", "shadower_moq.golden.go"),
   345  		},
   346  		{
   347  			name:       "ImportAlias",
   348  			cfg:        Config{SrcDir: "testpackages/importalias"},
   349  			interfaces: []string{"MiddleMan"},
   350  			goldenFile: filepath.Join("testpackages/importalias", "middleman_moq.golden.go"),
   351  		},
   352  		{
   353  			// Tests conflict resolution for generated names of method
   354  			// parameters.
   355  			name:       "ParamNameConflict",
   356  			cfg:        Config{SrcDir: "testpackages/paramconflict"},
   357  			interfaces: []string{"Interface"},
   358  			goldenFile: filepath.Join("testpackages/paramconflict", "iface_moq.golden.go"),
   359  		},
   360  		{
   361  			// Tests generation of names for unnamed method parameters.
   362  			name:       "GenerateParamNames",
   363  			cfg:        Config{SrcDir: "testpackages/genparamname"},
   364  			interfaces: []string{"Interface"},
   365  			goldenFile: filepath.Join("testpackages/genparamname", "iface_moq.golden.go"),
   366  		},
   367  		{
   368  			name:       "SyncImport",
   369  			cfg:        Config{SrcDir: "testpackages/syncimport"},
   370  			interfaces: []string{"Syncer"},
   371  			goldenFile: filepath.Join("testpackages/syncimport", "syncer_moq.golden.go"),
   372  		},
   373  		{
   374  			// Tests anonymous imports are not included in the generated mock.
   375  			name:       "AnonymousImport",
   376  			cfg:        Config{SrcDir: "testpackages/anonimport"},
   377  			interfaces: []string{"Example"},
   378  			goldenFile: filepath.Join("testpackages/anonimport", "iface_moq.golden.go"),
   379  		},
   380  		{
   381  			name:       "ShadowTypes",
   382  			cfg:        Config{SrcDir: "testpackages/shadowtypes"},
   383  			interfaces: []string{"ShadowTypes"},
   384  			goldenFile: filepath.Join("testpackages/shadowtypes", "shadowtypes_moq.golden.go"),
   385  		},
   386  	}
   387  	for _, tc := range cases {
   388  		t.Run(tc.name, func(t *testing.T) {
   389  			m, err := New(tc.cfg)
   390  			if err != nil {
   391  				t.Fatalf("moq.New: %s", err)
   392  			}
   393  
   394  			var buf bytes.Buffer
   395  			if err = m.Mock(&buf, tc.interfaces...); err != nil {
   396  				t.Errorf("m.Mock: %s", err)
   397  				return
   398  			}
   399  
   400  			if err := matchGoldenFile(tc.goldenFile, buf.Bytes()); err != nil {
   401  				t.Errorf("check golden file: %s", err)
   402  			}
   403  		})
   404  	}
   405  }
   406  
   407  func TestFormatter(t *testing.T) {
   408  	cases := []struct {
   409  		name string
   410  		conf Config
   411  	}{
   412  		{name: "gofmt", conf: Config{SrcDir: "testpackages/imports/two"}},
   413  		{name: "goimports", conf: Config{SrcDir: "testpackages/imports/two", Formatter: "goimports"}},
   414  		{name: "noop", conf: Config{SrcDir: "testpackages/imports/two", Formatter: "noop"}},
   415  	}
   416  	for _, tc := range cases {
   417  		t.Run(tc.name, func(t *testing.T) {
   418  			m, err := New(tc.conf)
   419  			if err != nil {
   420  				t.Fatalf("moq.New: %s", err)
   421  			}
   422  			var buf bytes.Buffer
   423  			err = m.Mock(&buf, "DoSomething:"+tc.name+"Mock")
   424  			if err != nil {
   425  				t.Errorf("m.Mock: %s", err)
   426  			}
   427  
   428  			golden := filepath.Join("testpackages/imports/two", tc.name+".golden.go")
   429  			if err := matchGoldenFile(golden, buf.Bytes()); err != nil {
   430  				t.Errorf("check golden file: %s", err)
   431  			}
   432  		})
   433  	}
   434  }
   435  
   436  func matchGoldenFile(goldenFile string, actual []byte) error {
   437  	// To update golden files, run the following:
   438  	// go test -v -run '^<Test-Name>$' github.com/matryer/moq/pkg/moq -update
   439  	if *update {
   440  		if err := os.MkdirAll(filepath.Dir(goldenFile), 0750); err != nil {
   441  			return fmt.Errorf("create dir: %s", err)
   442  		}
   443  		if err := ioutil.WriteFile(goldenFile, actual, 0600); err != nil {
   444  			return fmt.Errorf("write: %s", err)
   445  		}
   446  
   447  		return nil
   448  	}
   449  
   450  	expected, err := ioutil.ReadFile(goldenFile)
   451  	if err != nil {
   452  		return fmt.Errorf("read: %s: %s", goldenFile, err)
   453  	}
   454  
   455  	// Normalise newlines
   456  	actual, expected = normalize(actual), normalize(expected)
   457  	if !bytes.Equal(expected, actual) {
   458  		diff, err := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
   459  			A:        difflib.SplitLines(string(expected)),
   460  			B:        difflib.SplitLines(string(actual)),
   461  			FromFile: "Expected",
   462  			ToFile:   "Actual",
   463  			Context:  1,
   464  		})
   465  		if err != nil {
   466  			return fmt.Errorf("diff: %s", err)
   467  		}
   468  		return fmt.Errorf("match: %s:\n%s", goldenFile, diff)
   469  	}
   470  
   471  	return nil
   472  }
   473  
   474  func TestVendoredPackages(t *testing.T) {
   475  	m, err := New(Config{SrcDir: "testpackages/vendoring/user"})
   476  	if err != nil {
   477  		t.Fatalf("moq.New: %s", err)
   478  	}
   479  	var buf bytes.Buffer
   480  	err = m.Mock(&buf, "Service")
   481  	if err != nil {
   482  		t.Errorf("mock error: %s", err)
   483  	}
   484  	s := buf.String()
   485  	// assertions of things that should be mentioned
   486  	var strs = []string{
   487  		`"github.com/sudo-suhas/moq-test-pkgs/somerepo"`,
   488  	}
   489  	for _, str := range strs {
   490  		if !strings.Contains(s, str) {
   491  			t.Errorf("expected but missing: \"%s\"", str)
   492  		}
   493  	}
   494  }
   495  
   496  func TestVendoredInterface(t *testing.T) {
   497  	m, err := New(Config{
   498  		SrcDir:  "testpackages/vendoring/vendor/github.com/sudo-suhas/moq-test-pkgs/somerepo",
   499  		PkgName: "someother",
   500  	})
   501  	if err != nil {
   502  		t.Fatalf("moq.New: %s", err)
   503  	}
   504  	var buf bytes.Buffer
   505  	err = m.Mock(&buf, "SomeService")
   506  	if err != nil {
   507  		t.Errorf("mock error: %s", err)
   508  	}
   509  	s := buf.String()
   510  	// assertions of things that should be mentioned
   511  	var strs = []string{
   512  		`"github.com/sudo-suhas/moq-test-pkgs/somerepo"`,
   513  	}
   514  	for _, str := range strs {
   515  		if !strings.Contains(s, str) {
   516  			t.Errorf("expected but missing: \"%s\"", str)
   517  		}
   518  	}
   519  	incorrectImport := `"github.com/matryer/moq/pkg/moq/testpackages/vendoring/vendor/github.com/sudo-suhas/moq-test-pkgs/somerepo"`
   520  	if strings.Contains(s, incorrectImport) {
   521  		t.Errorf("unexpected import: %s", incorrectImport)
   522  	}
   523  }
   524  
   525  func TestVendoredBuildConstraints(t *testing.T) {
   526  	m, err := New(Config{SrcDir: "testpackages/buildconstraints/user"})
   527  	if err != nil {
   528  		t.Fatalf("moq.New: %s", err)
   529  	}
   530  	var buf bytes.Buffer
   531  	err = m.Mock(&buf, "Service")
   532  	if err != nil {
   533  		t.Errorf("mock error: %s", err)
   534  	}
   535  	s := buf.String()
   536  	// assertions of things that should be mentioned
   537  	var strs = []string{
   538  		`"github.com/sudo-suhas/moq-test-pkgs/buildconstraints"`,
   539  	}
   540  	for _, str := range strs {
   541  		if !strings.Contains(s, str) {
   542  			t.Errorf("expected but missing: \"%s\"", str)
   543  		}
   544  	}
   545  }
   546  
   547  // TestDotImports tests for https://github.com/matryer/moq/issues/21.
   548  func TestDotImports(t *testing.T) {
   549  	preDir, err := os.Getwd()
   550  	if err != nil {
   551  		t.Errorf("Getwd: %s", err)
   552  	}
   553  	err = os.Chdir("testpackages/dotimport")
   554  	if err != nil {
   555  		t.Errorf("Chdir: %s", err)
   556  	}
   557  	defer func() {
   558  		err := os.Chdir(preDir)
   559  		if err != nil {
   560  			t.Errorf("Chdir back: %s", err)
   561  		}
   562  	}()
   563  	m, err := New(Config{SrcDir: ".", PkgName: "moqtest_test"})
   564  	if err != nil {
   565  		t.Fatalf("moq.New: %s", err)
   566  	}
   567  	var buf bytes.Buffer
   568  	err = m.Mock(&buf, "Service")
   569  	if err != nil {
   570  		t.Errorf("mock error: %s", err)
   571  	}
   572  	s := buf.String()
   573  	if strings.Contains(s, `"."`) {
   574  		t.Error("contains invalid dot import")
   575  	}
   576  }
   577  
   578  func TestEmptyInterface(t *testing.T) {
   579  	m, err := New(Config{SrcDir: "testpackages/emptyinterface"})
   580  	if err != nil {
   581  		t.Fatalf("moq.New: %s", err)
   582  	}
   583  	var buf bytes.Buffer
   584  	err = m.Mock(&buf, "Empty")
   585  	if err != nil {
   586  		t.Errorf("mock error: %s", err)
   587  	}
   588  	s := buf.String()
   589  	if strings.Contains(s, `"sync"`) {
   590  		t.Error("contains sync import, although this package isn't used")
   591  	}
   592  }
   593  
   594  func TestGoGenerateVendoredPackages(t *testing.T) {
   595  	cmd := exec.Command("go", "generate", "./...")
   596  	cmd.Dir = "testpackages/gogenvendoring"
   597  	stdout, err := cmd.StdoutPipe()
   598  	if err != nil {
   599  		t.Errorf("StdoutPipe: %s", err)
   600  	}
   601  	defer stdout.Close()
   602  	err = cmd.Start()
   603  	if err != nil {
   604  		t.Errorf("Start: %s", err)
   605  	}
   606  	buf := bytes.NewBuffer(nil)
   607  	io.Copy(buf, stdout)
   608  	err = cmd.Wait()
   609  	if err != nil {
   610  		if exitErr, ok := err.(*exec.ExitError); ok {
   611  			t.Errorf("Wait: %s %s", exitErr, string(exitErr.Stderr))
   612  		} else {
   613  			t.Errorf("Wait: %s", err)
   614  		}
   615  	}
   616  	s := buf.String()
   617  	if strings.Contains(s, `vendor/`) {
   618  		t.Error("contains vendor directory in import path")
   619  	}
   620  }
   621  
   622  func TestImportedPackageWithSameName(t *testing.T) {
   623  	m, err := New(Config{SrcDir: "testpackages/samenameimport"})
   624  	if err != nil {
   625  		t.Fatalf("moq.New: %s", err)
   626  	}
   627  	var buf bytes.Buffer
   628  	err = m.Mock(&buf, "Example")
   629  	if err != nil {
   630  		t.Errorf("mock error: %s", err)
   631  	}
   632  	s := buf.String()
   633  	if !strings.Contains(s, `a samename.A`) {
   634  		t.Error("missing samename.A to address the struct A from the external package samename")
   635  	}
   636  }
   637  
   638  func TestParseError(t *testing.T) {
   639  	_, err := New(Config{SrcDir: "testpackages/_parseerror/service"})
   640  	if err == nil {
   641  		t.Errorf("expected error but got nil")
   642  		return
   643  	}
   644  	if !strings.Contains(err.Error(), `could not import github.com/matryer/notexist (invalid package name: "")`) {
   645  		t.Errorf("unexpected error: %s", err.Error())
   646  	}
   647  }
   648  
   649  func TestMockError(t *testing.T) {
   650  	m, err := New(Config{SrcDir: "testpackages/example"})
   651  	if err != nil {
   652  		t.Fatalf("moq.New: %s", err)
   653  	}
   654  	cases := []struct {
   655  		name     string
   656  		namePair string
   657  		wantErr  string
   658  	}{
   659  		{
   660  			name:     "TypeNotFound",
   661  			namePair: "DoesNotExist",
   662  			wantErr:  "interface not found: DoesNotExist",
   663  		},
   664  		{
   665  			name:     "UnexpectedType",
   666  			namePair: "Person",
   667  			wantErr:  "Person (github.com/matryer/moq/pkg/moq/testpackages/example.Person) is not an interface",
   668  		},
   669  	}
   670  	for _, tc := range cases {
   671  		t.Run(tc.name, func(t *testing.T) {
   672  			err := m.Mock(ioutil.Discard, tc.namePair)
   673  			if err == nil {
   674  				t.Errorf("expected error but got nil")
   675  				return
   676  			}
   677  			if !strings.Contains(err.Error(), tc.wantErr) {
   678  				t.Errorf("unexpected error: %s", err.Error())
   679  			}
   680  		})
   681  	}
   682  }
   683  
   684  // normalize normalizes \r\n (windows) and \r (mac)
   685  // into \n (unix)
   686  func normalize(d []byte) []byte {
   687  	// Source: https://www.programming-books.io/essential/go/normalize-newlines-1d3abcf6f17c4186bb9617fa14074e48
   688  	// replace CR LF \r\n (windows) with LF \n (unix)
   689  	d = bytes.Replace(d, []byte{13, 10}, []byte{10}, -1)
   690  	// replace CF \r (mac) with LF \n (unix)
   691  	d = bytes.Replace(d, []byte{13}, []byte{10}, -1)
   692  	return d
   693  }