in codegen/post_gen_hooks.go [70:205]
func ClientMockGenHook(h *PackageHelper, t *Template, parallelizeFactor int) (PostGenHook, error) {
return func(instances map[string][]*ModuleInstance) error {
clientInstances := instances["client"]
mockCount := len(clientInstances)
if mockCount == 0 {
return nil
}
fmt.Printf("Generating %d client mocks:\n", mockCount)
bin, err := NewMockgenBin(h, t)
if err != nil {
return errors.Wrap(err, "error building mockgen binary")
}
importPathMap := make(map[string]string, mockCount)
fixtureMap := make(map[string]*Fixture, mockCount)
clientInterfaceMap := make(map[string]string, mockCount)
pathSymbolMap := make(map[string]string, mockCount)
runner := parallelize.NewUnboundedRunner(mockCount)
var mutex sync.Mutex
for _, instance := range clientInstances {
f := func(instanceInf interface{}) (interface{}, error) {
instance := instanceInf.(*ModuleInstance)
key := instance.ClassType + instance.InstanceName
client, errClient := newMockableClient(instance.YAMLFileRaw)
if errClient != nil {
return nil, errors.Wrapf(
err,
"error parsing client-config for client %q",
instance.InstanceName,
)
}
importPath := instance.PackageInfo.ImportPackagePath()
customInterface := client.Config.CustomInterface
if instance.ClassType == custom {
importPath = client.Config.CustomImportPath
}
clientInterface := defaultClientInterface
// if an interfaces name is provided use that, else use "Client"
if customInterface != "" {
clientInterface = customInterface
}
mutex.Lock()
defer mutex.Unlock()
importPathMap[key] = importPath
clientInterfaceMap[key] = clientInterface
// gather all modules that need to generate fixture types
f := client.Config.Fixture
if f != nil && f.Scenarios != nil {
pathSymbolMap[importPath] = clientInterface
fixtureMap[key] = f
}
return nil, nil
}
wrk := ¶llelize.SingleParamWork{Data: instance, Func: f}
runner.SubmitWork(wrk)
}
if _, err := runner.GetResult(); err != nil {
return err
}
// only run reflect program once to gather interface info for all clients
pkgs, err := ReflectInterface("", pathSymbolMap)
if err != nil {
return errors.Wrap(err, "error parsing Client interfaces")
}
var idx int32 = 1
var files sync.Map
runner = parallelize.NewBoundedRunner(mockCount, parallelizeFactor*runtime.NumCPU())
for _, instance := range clientInstances {
f := func(instanceInf interface{}) (interface{}, error) {
instance := instanceInf.(*ModuleInstance)
key := instance.ClassType + instance.InstanceName
buildDir := h.CodeGenTargetPath()
genDir := filepath.Join(buildDir, instance.Directory, "mock-client")
importPath := importPathMap[key]
// generate mock client, this starts a sub process.
mock, err := bin.GenMock(importPath, "clientmock", clientInterfaceMap[key])
if err != nil {
return nil, errors.Wrapf(
err,
"error generating mocks for client %q",
instance.InstanceName,
)
}
files.Store(filepath.Join(genDir, "mock_client.go"), mock)
// generate fixture types and augmented mock client
if f, ok := fixtureMap[key]; ok {
types, augMock, err := bin.AugmentMockWithFixture(pkgs[importPath], f, clientInterfaceMap[key])
if err != nil {
return nil, errors.Wrapf(
err,
"error generating fixture types for client %q",
instance.InstanceName,
)
}
files.Store(filepath.Join(genDir, "types.go"), types)
files.Store(filepath.Join(genDir, "mock_client_with_fixture.go"), augMock)
}
PrintGenLine(
"mock",
instance.ClassName,
instance.InstanceName,
path.Join(path.Base(buildDir), instance.Directory, "mock-client"),
int(atomic.LoadInt32(&idx)), mockCount,
)
atomic.AddInt32(&idx, 1)
return nil, nil
}
wrk := ¶llelize.SingleParamWork{Data: instance, Func: f}
runner.SubmitWork(wrk)
}
if _, err := runner.GetResult(); err != nil {
return errors.Wrap(err, "encountered errors when generating mock clients")
}
files.Range(func(p, data interface{}) bool {
if err = WriteAndFormat(p.(string), data.([]byte)); err != nil {
return false
}
return true
})
return err
}, nil
}