Skip to content

Commit

Permalink
feat: allow providing a IDGenerator function
Browse files Browse the repository at this point in the history
For services with user-settable IDs, there might be requirements on how
the format of that ID should look. Providing this function, i.e. it is
non-nil, will call it and fill in the returned ID during creation steps.

It is expected (and documented) that the function should return unique
IDs. It is up to the user to fulfill this requirement. One provided
example is to use a counter and include that in the ID.

This feature makes it possible to use this test suite for APIs where
user-settable ID is required, which wasn't possible before.
  • Loading branch information
radhus committed Sep 19, 2022
1 parent 6c097c1 commit fc9a6ca
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 9 deletions.
12 changes: 12 additions & 0 deletions example/freight_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package example

import (
"context"
"fmt"
"sync/atomic"
"testing"

examplefreightv1 "github.com/einride/protoc-gen-go-aip-test/proto/gen/einride/example/freight/v1"
Expand All @@ -18,6 +20,9 @@ func Test_FreightService(t *testing.T) {
Server: server,
}

// counter to keep track of unique IDs.
var idCounter uint64

// run tests for each resource in the service
ctx := context.Background()
suite.TestShipper(ctx, examplefreightv1.ShipperTestSuiteConfig{
Expand All @@ -29,6 +34,13 @@ func Test_FreightService(t *testing.T) {
BillingAccount: "billingAccounts/12345",
}
},
// IDGenerator should return a valid and unique ID to use in the Create call.
// If non-nil, this function will be called to set the ID on all Create calls.
// If the ID field is required, tests will fail if this is nil.
IDGenerator: func() string {
id := atomic.AddUint64(&idCounter, 1)
return fmt.Sprintf("valid-id-%d", id)
},
// Update should return a resource which is valid to update, i.e.
// all required fields set.
Update: func() *examplefreightv1.Shipper {
Expand Down
9 changes: 8 additions & 1 deletion internal/plugin/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (r *resourceGenerator) generateFixture(f *protogen.GeneratedFile) {
f.P("// provided the test will fail.")
f.P("Parents []string")
}
_, hasCreate := util.StandardMethod(r.service, r.resource, aipreflect.MethodTypeCreate)
createMethod, hasCreate := util.StandardMethod(r.service, r.resource, aipreflect.MethodTypeCreate)
if hasCreate {
f.P("// Create should return a resource which is valid to create, i.e.")
f.P("// all required fields set.")
Expand All @@ -62,6 +62,13 @@ func (r *resourceGenerator) generateFixture(f *protogen.GeneratedFile) {
} else {
f.P("Create func() *", r.message.GoIdent)
}

if util.HasUserSettableIDField(r.resource, createMethod.Input.Desc) {
f.P("// IDGenerator should return a valid and unique ID to use in the Create call.")
f.P("// If non-nil, this function will be called to set the ID on all Create calls.")
f.P("// If the ID field is required, tests will fail if this is nil.")
f.P("IDGenerator func() string")
}
} else {
f.P("// CreateResource should create a ", r.message.Desc.Name(), " and return it.")
f.P("// If the field is not set, some tests will be skipped.")
Expand Down
14 changes: 12 additions & 2 deletions internal/util/method.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ type MethodCreate struct {
}

func (m MethodCreate) Generate(f *protogen.GeneratedFile, response, err, assign string) {
userSetID := m.UserSettableID
if userSetID == "" && HasUserSettableIDField(m.Resource, m.Method.Input.Desc) {
userSetID = "userSetID"
f.P(userSetID + " := \"\"")
f.P("if fx.IDGenerator != nil {")
f.P(userSetID + " = fx.IDGenerator()")
f.P("}")
}

f.P(response, ", ", err, " ", assign, " fx.service.", m.Method.GoName, "(fx.ctx, &", m.Method.Input.GoIdent, "{")
if HasParent(m.Resource) {
f.P("Parent: ", m.Parent, ",")
Expand All @@ -35,9 +44,10 @@ func (m MethodCreate) Generate(f *protogen.GeneratedFile, response, err, assign
f.P(upper, ": fx.Create(", m.Parent, "),")
}

if m.UserSettableID != "" && HasUserSettableIDField(m.Resource, m.Method.Input.Desc) {
f.P(upper, "Id: ", m.UserSettableID, ",")
if userSetID != "" && HasUserSettableIDField(m.Resource, m.Method.Input.Desc) {
f.P(upper, "Id: ", userSetID, ",")
}

f.P("})")
}

Expand Down
46 changes: 40 additions & 6 deletions proto/gen/einride/example/freight/v1/freight_service_aiptest.pb.go

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

0 comments on commit fc9a6ca

Please sign in to comment.