func ClientMockGenHook()

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 := &parallelize.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 := &parallelize.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
}