Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
thall committed Oct 11, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 263aee0 commit 5ef888d
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
2 changes: 1 addition & 1 deletion example/freight_service_test.go
Original file line number Diff line number Diff line change
@@ -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{}
70 changes: 57 additions & 13 deletions internal/plugin/generate.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package plugin

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

"github.com/einride/protoc-gen-go-aip-test/internal/util"
@@ -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 {
@@ -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
@@ -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)
4 changes: 4 additions & 0 deletions internal/plugin/name.go
Original file line number Diff line number Diff line change
@@ -31,3 +31,7 @@ func resourceTestSuiteConfigName(
func serviceTestConfigProviderName(service protoreflect.ServiceDescriptor) string {
return string(service.Name()) + "TestSuiteConfigProvider"
}

func servicesTestSuiteConfigProvidersName() string {
return "ServicesTestSuiteConfigProviders"
}
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 5ef888d

Please sign in to comment.