Skip to content

Commit

Permalink
feat: generate one test case for all services within package
Browse files Browse the repository at this point in the history
This is a continuation of [commit](f9ff1a1).

Before each service within the package had its own test function,
meaning that if you add a new service within that package, you would
need to call a newly generated function, which could easily be forgotten.

This commit introduces one test function for the whole package
which takes a interface which embeds the other services test interfaces.
With this in place, if you add a new service you will get a compilation
error that you no longer fulfil the interface.
  • Loading branch information
thall committed Oct 11, 2024
1 parent 10b9794 commit 2315f4a
Show file tree
Hide file tree
Showing 14 changed files with 267 additions and 15 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.idea
**/*.pb.go
!**/*_aiptest.pb.go
!**/*aiptest.pb.go

# files generated by go-semantic-release in release CI
.semrel
Expand Down
2 changes: 1 addition & 1 deletion example/freight_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func Test_FreightService(t *testing.T) {

func Test_FreightService_AlternativeSetup(t *testing.T) {
// Even though no implementation exists, the tests will pass but be skipped.
examplefreightv1.TestFreightService(t, &aipTests{})
examplefreightv1.TestServices(t, &aipTests{})
}

type aipTests struct{}
Expand Down
70 changes: 57 additions & 13 deletions internal/plugin/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package plugin

import (
"fmt"
"path/filepath"
"sort"

"github.com/einride/protoc-gen-go-aip-test/internal/util"
Expand All @@ -17,11 +18,11 @@ const (

func Generate(plugin *protogen.Plugin) error {
plugin.SupportedFeatures |= 1 // proto3 optional
files, err := collectServices(plugin)
filesPerPackage, err := collectServices(plugin)
if err != nil {
return err
}
return generate(plugin, files)
return generate(plugin, filesPerPackage)
}

type File struct {
Expand All @@ -32,9 +33,9 @@ type File struct {
// collectServices collects valid services to generate AIP test code for.
func collectServices(
plugin *protogen.Plugin,
) ([]File, error) {
) (map[protoreflect.FullName][]File, error) {
pkgResources := findResourcesPerPackage(plugin)
result := make([]File, 0, 10)
result := make(map[protoreflect.FullName][]File, 10)
for _, file := range plugin.Files {
if len(file.Services) == 0 || !file.Generate {
continue
Expand Down Expand Up @@ -75,25 +76,68 @@ func collectServices(
}
f.services = append(f.services, generator)
}
result = append(result, f)
result[file.Desc.Package()] = append(result[file.Desc.Package()], f)
}
return result, nil
}

func generate(plugin *protogen.Plugin, files []File) error {
for _, file := range files {
f := createServiceTestFile(plugin, file)
f.Skip()
for _, generator := range file.services {
if err := generator.Generate(f); err != nil {
return err
func generate(plugin *protogen.Plugin, filesPerPackage map[protoreflect.FullName][]File) error {
for _, files := range filesPerPackage {
generateForPackage(plugin, files)
for _, file := range files {
f := createServiceTestFile(plugin, file)
f.Skip()
for _, generator := range file.services {
if err := generator.Generate(f); err != nil {
return err
}
f.Unskip()
}
f.Unskip()
}
}
return nil
}

func generateForPackage(plugin *protogen.Plugin, files []File) {
filename := filepath.Join(filepath.Dir(files[0].GeneratedFilenamePrefix), fileSuffix)
f := plugin.NewGeneratedFile(filename, files[0].GoImportPath)
writeHeader(files[0].File, f)
generateServicesConfigProvidersInterface(f, files)
generateTestAllServices(f, files)
}

func generateServicesConfigProvidersInterface(f *protogen.GeneratedFile, files []File) {
name := servicesTestSuiteConfigProvidersName()
f.P("// ", name, " embeds providers for all services.")
f.P("type ", name, " interface {")
for _, file := range files {
for _, service := range file.services {
f.P(serviceTestConfigProviderName(service.service.Desc))
}
}
f.P("}")
f.P()
}

func generateTestAllServices(f *protogen.GeneratedFile, files []File) {
t := f.QualifiedGoIdent(protogen.GoIdent{
GoName: "T",
GoImportPath: "testing",
})
name := servicesTestSuiteConfigProvidersName()
funcName := "TestServices"
f.P("// ", funcName, " is the main entrypoint for starting the AIP tests for all services.")
f.P("func ", funcName, "(t *", t, ",s ", name, ") {")
for _, file := range files {
for _, service := range file.services {
name := "Test" + string(service.service.Desc.Name())
f.P(name, "(t, s)")
}
}
f.P("}")
f.P()
}

func createServiceTestFile(plugin *protogen.Plugin, file File) *protogen.GeneratedFile {
filename := fmt.Sprintf("%s_%s", file.GeneratedFilenamePrefix, fileSuffix)
f := plugin.NewGeneratedFile(filename, file.GoImportPath)
Expand Down
4 changes: 4 additions & 0 deletions internal/plugin/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ func resourceTestSuiteConfigName(
func serviceTestConfigProviderName(service protoreflect.ServiceDescriptor) string {
return string(service.Name()) + "TestSuiteConfigProvider"
}

func servicesTestSuiteConfigProvidersName() string {
return "ServiceConfigProviders"
}
17 changes: 17 additions & 0 deletions proto/gen/einride/example/freight/v1/aiptest.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions proto/gen/googleapis/aiplatform/apiv1/aiplatformpb/aiptest.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions proto/gen/googleapis/pubsub/apiv1/pubsubpb/aiptest.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions proto/gen/googleapis/scheduler/apiv1/schedulerpb/aiptest.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions proto/gen/googleapis/spanner/apiv1/spannerpb/aiptest.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2315f4a

Please sign in to comment.