From 96f76bdbcbbb18413191c3fe037e1b1668b7049f Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Fri, 17 Jul 2020 08:57:44 -0700 Subject: [PATCH 1/2] Support variadic parameters in augmented mock client This PR adds support for variadic parameters in the augmented mock client `MockClientWithFixture`. This feature applies to any type of clients that has methods of variadic parameters, but particularly applies to generated gRPC clients, where each client method accepts the variadic parameter of type `yarpc.CallOption`. One caveat is that Go does not support function comparsion (even `reflect.DeepEqual` won't work), see details in https://github.com/golang/mock/issues/324. So in the case of gRPC mock clients, it is not possible to match the `yarpc.CallOption` variadic parameters, because it internally has a function field. The workout is to always set `Arg{n}Any` in the fixture pacakge to the number of variadic parameters so that macther checks pass for them. --- codegen/mockgen.go | 13 +- codegen/template_bundle/template_files.go | 28 ++++- codegen/templates/augmented_mock.tmpl | 14 ++- codegen/templates/fixture_types.tmpl | 10 ++ .../mock-client/mock_client_with_fixture.go | 115 ++++++++++++++++++ .../build/clients/echo/mock-client/types.go | 57 +++++++++ .../bounce_bounce_workflow_mock.go | 3 +- .../endpoints/bounce/mock-workflow/type.go | 2 +- .../mock-service/mock_init.go | 5 +- .../clients/echo/client-config.yaml | 5 + .../clients/echo/fixture/fixture.go | 21 ++++ .../endpoints/bounce/bounce.go | 4 +- .../endpoints/bounce/bounce_test.go | 4 +- 13 files changed, 267 insertions(+), 14 deletions(-) create mode 100644 examples/selective-gateway/build/clients/echo/mock-client/mock_client_with_fixture.go create mode 100644 examples/selective-gateway/build/clients/echo/mock-client/types.go create mode 100644 examples/selective-gateway/clients/echo/fixture/fixture.go diff --git a/codegen/mockgen.go b/codegen/mockgen.go index 80c986851..a4cc12ee4 100644 --- a/codegen/mockgen.go +++ b/codegen/mockgen.go @@ -119,13 +119,20 @@ func (m MockgenBin) AugmentMockWithFixture(pkg *model.Package, f *Fixture, intf outString = append(outString, ret) } - methods = append(methods, &reflectMethod{ + method := &reflectMethod{ Name: m.Name, In: in, Out: out, InString: strings.Join(inString, " ,"), OutString: strings.Join(outString, " ,"), - }) + } + + if m.Variadic != nil { + method.Variadic = "arg" + strconv.Itoa(len(m.In)) + method.VariadicType = m.Variadic.Type.String(pkgPathToAlias, "") + } + + methods = append(methods, method) } data := map[string]interface{}{ @@ -148,6 +155,8 @@ func (m MockgenBin) AugmentMockWithFixture(pkg *model.Package, f *Fixture, intf type reflectMethod struct { Name string In, Out map[string]string + Variadic string + VariadicType string InString, OutString string } diff --git a/codegen/template_bundle/template_files.go b/codegen/template_bundle/template_files.go index ca7447856..60a8ba746 100644 --- a/codegen/template_bundle/template_files.go +++ b/codegen/template_bundle/template_files.go @@ -161,12 +161,24 @@ func (s *{{$methodMockType}}) {{$scenarioMethod}}() Call { {{$argName}} = gomock.Any() } {{- end}} + {{- if $method.Variadic}} + var {{$method.Variadic}} []interface{} + if f.{{title $method.Variadic}} != nil { + for _, v := range f.{{title $method.Variadic}} { + {{$method.Variadic}} = append({{$method.Variadic}}, v) + } + } else if f.{{title $method.Variadic}}Any > 0 { + for i := 0; i < f.{{title $method.Variadic}}Any; i++ { + {{$method.Variadic}} = append({{$method.Variadic}}, gomock.Any()) + } + } + {{- end}} {{range $retName, $retType := $method.Out}} {{$retName}} := f.{{title $retName}} {{- end}} - return Call{call: s.mockClient.EXPECT().{{$methodName}}({{$method.InString}}).Return({{$method.OutString}})} + return Call{call: s.mockClient.EXPECT().{{$methodName}}({{$method.InString}}{{if $method.Variadic}}, {{$method.Variadic}}...{{end}}).Return({{$method.OutString}})} } {{- end -}} {{- end -}} @@ -182,7 +194,7 @@ func augmented_mockTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "augmented_mock.tmpl", size: 3157, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "augmented_mock.tmpl", size: 3627, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1149,11 +1161,21 @@ type {{$methodName}}Fixture struct { {{title $argName}} {{$argType}} {{- end}} + {{- if $method.Variadic}} + {{title $method.Variadic}} []{{$method.VariadicType}} + {{- end}} + // Arg{n}Any indicates the nth argument could be gomock.Any {{- range $argName, $argType := $method.In}} {{title $argName}}Any bool {{- end}} + {{- if $method.Variadic}} + // {{title $method.Variadic}}Any indicates the variadic argument is a number of gomock.Any + {{title $method.Variadic}}Any int + {{- end}} + + {{range $retName, $retType := $method.Out}} {{title $retName}} {{$retType}} {{- end}} @@ -1171,7 +1193,7 @@ func fixture_typesTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "fixture_types.tmpl", size: 1379, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + info := bindataFileInfo{name: "fixture_types.tmpl", size: 1640, mode: os.FileMode(420), modTime: time.Unix(1, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/codegen/templates/augmented_mock.tmpl b/codegen/templates/augmented_mock.tmpl index 7a87f9de1..ed4e36f97 100644 --- a/codegen/templates/augmented_mock.tmpl +++ b/codegen/templates/augmented_mock.tmpl @@ -89,12 +89,24 @@ func (s *{{$methodMockType}}) {{$scenarioMethod}}() Call { {{$argName}} = gomock.Any() } {{- end}} + {{- if $method.Variadic}} + var {{$method.Variadic}} []interface{} + if f.{{title $method.Variadic}} != nil { + for _, v := range f.{{title $method.Variadic}} { + {{$method.Variadic}} = append({{$method.Variadic}}, v) + } + } else if f.{{title $method.Variadic}}Any > 0 { + for i := 0; i < f.{{title $method.Variadic}}Any; i++ { + {{$method.Variadic}} = append({{$method.Variadic}}, gomock.Any()) + } + } + {{- end}} {{range $retName, $retType := $method.Out}} {{$retName}} := f.{{title $retName}} {{- end}} - return Call{call: s.mockClient.EXPECT().{{$methodName}}({{$method.InString}}).Return({{$method.OutString}})} + return Call{call: s.mockClient.EXPECT().{{$methodName}}({{$method.InString}}{{if $method.Variadic}}, {{$method.Variadic}}...{{end}}).Return({{$method.OutString}})} } {{- end -}} {{- end -}} diff --git a/codegen/templates/fixture_types.tmpl b/codegen/templates/fixture_types.tmpl index 18fb186d3..a5422a7dc 100644 --- a/codegen/templates/fixture_types.tmpl +++ b/codegen/templates/fixture_types.tmpl @@ -40,11 +40,21 @@ type {{$methodName}}Fixture struct { {{title $argName}} {{$argType}} {{- end}} + {{- if $method.Variadic}} + {{title $method.Variadic}} []{{$method.VariadicType}} + {{- end}} + // Arg{n}Any indicates the nth argument could be gomock.Any {{- range $argName, $argType := $method.In}} {{title $argName}}Any bool {{- end}} + {{- if $method.Variadic}} + // {{title $method.Variadic}}Any indicates the variadic argument is a number of gomock.Any + {{title $method.Variadic}}Any int + {{- end}} + + {{range $retName, $retType := $method.Out}} {{title $retName}} {{$retType}} {{- end}} diff --git a/examples/selective-gateway/build/clients/echo/mock-client/mock_client_with_fixture.go b/examples/selective-gateway/build/clients/echo/mock-client/mock_client_with_fixture.go new file mode 100644 index 000000000..0ece54ead --- /dev/null +++ b/examples/selective-gateway/build/clients/echo/mock-client/mock_client_with_fixture.go @@ -0,0 +1,115 @@ +// Code generated by zanzibar +// @generated + +// Copyright (c) 2018 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package clientmock + +import ( + "github.com/golang/mock/gomock" +) + +// MockClientWithFixture is a mock of Client interface with preset fixture +type MockClientWithFixture struct { + *MockClient + fixture *ClientFixture + + echoEchoMock *EchoEchoMock +} + +// Call is a thin wrapper around gomock.Call for exposing the methods that do not mutate the fixture related information +// like Return(). +type Call struct { + call *gomock.Call +} + +// MaxTimes marks a fixture as callable up to a maximum number of times. +func (c Call) MaxTimes(max int) { + c.call.MaxTimes(max) +} + +// MinTimes marks a fixture as must be called a minimum number of times. +func (c Call) MinTimes(max int) { + c.call.MinTimes(max) +} + +// New creates a new mock instance +func New(ctrl *gomock.Controller, fixture *ClientFixture) *MockClientWithFixture { + return &MockClientWithFixture{ + MockClient: NewMockClient(ctrl), + fixture: fixture, + } +} + +// EXPECT shadows the EXPECT method on the underlying mock client. +// It should not be called directly. +func (m *MockClientWithFixture) EXPECT() { + panic("should not call EXPECT directly.") +} + +// EchoEchoMock mocks the EchoEcho method +type EchoEchoMock struct { + scenarios *EchoEchoScenarios + mockClient *MockClient +} + +// ExpectEchoEcho returns an object that allows the caller to choose expected scenario for EchoEcho +func (m *MockClientWithFixture) ExpectEchoEcho() *EchoEchoMock { + if m.echoEchoMock == nil { + m.echoEchoMock = &EchoEchoMock{ + scenarios: m.fixture.EchoEcho, + mockClient: m.MockClient, + } + } + return m.echoEchoMock +} + +// Success sets the expected scenario as defined in the concrete fixture package +// github.com/uber/zanzibar/examples/selective-gateway/clients/echo/fixture +func (s *EchoEchoMock) Success() Call { + f := s.scenarios.Success + + var arg0 interface{} + arg0 = f.Arg0 + if f.Arg0Any { + arg0 = gomock.Any() + } + var arg1 interface{} + arg1 = f.Arg1 + if f.Arg1Any { + arg1 = gomock.Any() + } + var arg2 []interface{} + if f.Arg2 != nil { + for _, v := range f.Arg2 { + arg2 = append(arg2, v) + } + } else if f.Arg2Any > 0 { + for i := 0; i < f.Arg2Any; i++ { + arg2 = append(arg2, gomock.Any()) + } + } + + ret0 := f.Ret0 + ret1 := f.Ret1 + + return Call{call: s.mockClient.EXPECT().EchoEcho(arg0, arg1, arg2...).Return(ret0, ret1)} +} diff --git a/examples/selective-gateway/build/clients/echo/mock-client/types.go b/examples/selective-gateway/build/clients/echo/mock-client/types.go new file mode 100644 index 000000000..f7dd6bd94 --- /dev/null +++ b/examples/selective-gateway/build/clients/echo/mock-client/types.go @@ -0,0 +1,57 @@ +// Code generated by zanzibar +// @generated + +// Copyright (c) 2018 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package clientmock + +import ( + context "context" + + echo "github.com/uber/zanzibar/examples/selective-gateway/build/proto-gen/clients/echo" + yarpc "go.uber.org/yarpc" +) + +// ClientFixture defines the client fixture type +type ClientFixture struct { + EchoEcho *EchoEchoScenarios +} + +// EchoEchoScenarios defines all fixture scenarios for EchoEcho +type EchoEchoScenarios struct { + Success *EchoEchoFixture `scenario:"success"` +} + +// EchoEchoFixture defines the fixture type for EchoEcho +type EchoEchoFixture struct { + Arg0 context.Context + Arg1 *echo.Request + Arg2 []yarpc.CallOption + + // Arg{n}Any indicates the nth argument could be gomock.Any + Arg0Any bool + Arg1Any bool + // Arg2Any indicates the variadic argument is a number of gomock.Any + Arg2Any int + + Ret0 *echo.Response + Ret1 error +} diff --git a/examples/selective-gateway/build/endpoints/bounce/mock-workflow/bounce_bounce_workflow_mock.go b/examples/selective-gateway/build/endpoints/bounce/mock-workflow/bounce_bounce_workflow_mock.go index 3bb78da3d..999429fb2 100644 --- a/examples/selective-gateway/build/endpoints/bounce/mock-workflow/bounce_bounce_workflow_mock.go +++ b/examples/selective-gateway/build/endpoints/bounce/mock-workflow/bounce_bounce_workflow_mock.go @@ -35,6 +35,7 @@ import ( mirrorclientgeneratedmock "github.com/uber/zanzibar/examples/selective-gateway/build/clients/mirror/mock-client" module "github.com/uber/zanzibar/examples/selective-gateway/build/endpoints/bounce/module" workflow "github.com/uber/zanzibar/examples/selective-gateway/build/endpoints/bounce/workflow" + fixtureechoclientgenerated "github.com/uber/zanzibar/examples/selective-gateway/clients/echo/fixture" bounceendpointstatic "github.com/uber/zanzibar/examples/selective-gateway/endpoints/bounce" ) @@ -51,7 +52,7 @@ func NewBounceBounceWorkflowMock(t *testing.T) (workflow.BounceBounceWorkflow, * initializedClientDependencies := &clientDependenciesNodes{} mockClientNodes := &MockClientNodes{ - Echo: echoclientgeneratedmock.NewMockClient(ctrl), + Echo: echoclientgeneratedmock.New(ctrl, fixtureechoclientgenerated.Fixture), Mirror: mirrorclientgeneratedmock.NewMockClient(ctrl), } initializedClientDependencies.Echo = mockClientNodes.Echo diff --git a/examples/selective-gateway/build/endpoints/bounce/mock-workflow/type.go b/examples/selective-gateway/build/endpoints/bounce/mock-workflow/type.go index 34b206711..a2ce500b3 100644 --- a/examples/selective-gateway/build/endpoints/bounce/mock-workflow/type.go +++ b/examples/selective-gateway/build/endpoints/bounce/mock-workflow/type.go @@ -32,7 +32,7 @@ import ( // MockClientNodes contains mock client dependencies for the bounce endpoint module type MockClientNodes struct { - Echo *echoclientgeneratedmock.MockClient + Echo *echoclientgeneratedmock.MockClientWithFixture Mirror *mirrorclientgeneratedmock.MockClient } diff --git a/examples/selective-gateway/build/services/selective-gateway/mock-service/mock_init.go b/examples/selective-gateway/build/services/selective-gateway/mock-service/mock_init.go index 51dc91ff9..e2e2f6fbc 100644 --- a/examples/selective-gateway/build/services/selective-gateway/mock-service/mock_init.go +++ b/examples/selective-gateway/build/services/selective-gateway/mock-service/mock_init.go @@ -32,11 +32,12 @@ import ( mirrorclientgenerated "github.com/uber/zanzibar/examples/selective-gateway/build/clients/mirror/mock-client" bounceendpointgenerated "github.com/uber/zanzibar/examples/selective-gateway/build/endpoints/bounce" bounceendpointmodule "github.com/uber/zanzibar/examples/selective-gateway/build/endpoints/bounce/module" + fixtureechoclientgenerated "github.com/uber/zanzibar/examples/selective-gateway/clients/echo/fixture" ) // MockClientNodes contains mock client dependencies type MockClientNodes struct { - Echo *echoclientgenerated.MockClient + Echo *echoclientgenerated.MockClientWithFixture Mirror *mirrorclientgenerated.MockClient } @@ -62,7 +63,7 @@ func InitializeDependenciesMock( } mockClientNodes := &MockClientNodes{ - Echo: echoclientgenerated.NewMockClient(ctrl), + Echo: echoclientgenerated.New(ctrl, fixtureechoclientgenerated.Fixture), Mirror: mirrorclientgenerated.NewMockClient(ctrl), } initializedClientDependencies := &module.ClientDependenciesNodes{} diff --git a/examples/selective-gateway/clients/echo/client-config.yaml b/examples/selective-gateway/clients/echo/client-config.yaml index bc27aa61b..119761254 100644 --- a/examples/selective-gateway/clients/echo/client-config.yaml +++ b/examples/selective-gateway/clients/echo/client-config.yaml @@ -4,3 +4,8 @@ config: idlFile: clients/echo/echo.proto exposedMethods: "EchoEcho": "Echo::Echo" + fixture: + importPath: github.com/uber/zanzibar/examples/selective-gateway/clients/echo/fixture + scenarios: + EchoEcho: + - success diff --git a/examples/selective-gateway/clients/echo/fixture/fixture.go b/examples/selective-gateway/clients/echo/fixture/fixture.go new file mode 100644 index 000000000..ca8e68a98 --- /dev/null +++ b/examples/selective-gateway/clients/echo/fixture/fixture.go @@ -0,0 +1,21 @@ +package fixture + +import ( + mc "github.com/uber/zanzibar/examples/selective-gateway/build/clients/echo/mock-client" + gen "github.com/uber/zanzibar/examples/selective-gateway/build/proto-gen/clients/echo" +) + +var echoEchoFixtures = &mc.EchoEchoScenarios{ + Success: &mc.EchoEchoFixture{ + Arg0Any: true, + Arg1Any: true, + Arg2Any: 1, + + Ret0: &gen.Response{Message: "hello"}, + }, +} + +// Fixture ... +var Fixture = &mc.ClientFixture{ + EchoEcho: echoEchoFixtures, +} diff --git a/examples/selective-gateway/endpoints/bounce/bounce.go b/examples/selective-gateway/endpoints/bounce/bounce.go index f66e65272..12a3d92c0 100644 --- a/examples/selective-gateway/endpoints/bounce/bounce.go +++ b/examples/selective-gateway/endpoints/bounce/bounce.go @@ -23,6 +23,8 @@ package bounce import ( "context" + "go.uber.org/yarpc" + echoclient "github.com/uber/zanzibar/examples/selective-gateway/build/clients/echo" mirrorclient "github.com/uber/zanzibar/examples/selective-gateway/build/clients/mirror" "github.com/uber/zanzibar/examples/selective-gateway/build/endpoints/bounce/module" @@ -52,7 +54,7 @@ func (w bounceWorkflow) Handle( reqHeaders zanzibar.Header, req *bounce.Bounce_Bounce_Args, ) (string, zanzibar.Header, error) { - res, err := w.echo.EchoEcho(ctx, &echo.Request{Message: req.Msg}) + res, err := w.echo.EchoEcho(ctx, &echo.Request{Message: req.Msg}, yarpc.WithRoutingKey("echo")) if err != nil { return "", nil, err } diff --git a/examples/selective-gateway/endpoints/bounce/bounce_test.go b/examples/selective-gateway/endpoints/bounce/bounce_test.go index 5ffb9373b..82490729e 100644 --- a/examples/selective-gateway/endpoints/bounce/bounce_test.go +++ b/examples/selective-gateway/endpoints/bounce/bounce_test.go @@ -10,7 +10,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/uber/zanzibar/examples/selective-gateway/build/gen-code/endpoints/bounce/bounce" - "github.com/uber/zanzibar/examples/selective-gateway/build/proto-gen/clients/echo" "github.com/uber/zanzibar/examples/selective-gateway/build/proto-gen/clients/mirror" ) @@ -27,8 +26,7 @@ func TestEcho(t *testing.T) { ctx := context.Background() var result bounce.Bounce_Bounce_Result - ms.MockClients().Echo.EXPECT().EchoEcho(gomock.Any(), &echo.Request{Message: message}). - Return(&echo.Response{Message: message}, nil) + ms.MockClients().Echo.ExpectEchoEcho().Success() ms.MockClients().Mirror.EXPECT().MirrorMirror(gomock.Any(), &mirror.Request{Message: message}). Return(&mirror.Response{Message: message}, nil) ms.MockClients().Mirror.EXPECT().MirrorInternalMirror(gomock.Any(), &mirror.InternalRequest{Message: message}). From 905b50e7deff71d603a8cc8d5db45c147feec43d Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Fri, 17 Jul 2020 09:16:57 -0700 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a5c28cd2..50b983d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 0.6.2 - 2020-07-17 +### Added +- Added support for variadic parameters in augmented mock clients. https://github.com/uber/zanzibar/pull/731. + +## 0.6.1 - 2020-07-15 +### Added +- Added support for grpc clients that have multiple services defined in proto. https://github.com/uber/zanzibar/pull/730. + +## 0.6.0 - 2020-07-13 ### Added - Added support for circuit breaker, logging, and metrics similar to other protocol clients for gRPC clients ([#627](https://github.com/uber/zanzibar/pull/627)) ### Fixed @@ -12,7 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - **BREAKING** `NewDefaultModuleSystemWithMockHook` API changed to add option for which hooks to execute. ([#638](https://github.com/uber/zanzibar/pull/638)) - `resolve_thrift` tool will now check if the given file has the `.thrift` extension. ([#634](https://github.com/uber/zanzibar/pull/634)) -- **BREAKING** The `genCodePackage` field type in application config file (build.yaml) is now `object` with properties `".thrift"` and `".proto"` to support separated gen code dirs for different idl types. +- **BREAKING** The `thriftRootDir` field type in application config file (build.yaml) is now `idlRootDir` since both thrift and protobuf are suppported (client idl only for now) different idl types. https://github.com/uber/zanzibar/pull/728. +- **BREAKING** The `genCodePackage` field type in application config file (build.yaml) is now `object` with properties `".thrift"` and `".proto"` to support separated gen code dirs for different idl types. https://github.com/uber/zanzibar/pull/728. ## 0.4.0 - 2019-08-21