1+ // Copyright 2025 Google LLC
2+ //
3+ // Licensed under the Apache License, Version 2.0 (the "License");
4+ // you may not use this file except in compliance with the License.
5+ // You may obtain a copy of the License at
6+ //
7+ // http://www.apache.org/licenses/LICENSE-2.0
8+ //
9+ // Unless required by applicable law or agreed to in writing, software
10+ // distributed under the License is distributed on an "AS IS" BASIS,
11+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ // See the License for the specific language governing permissions and
13+ // limitations under the License.
14+
15+ package protoc
16+
17+ import (
18+ "path/filepath"
19+ "strings"
20+ "testing"
21+
22+ "github.com/google/go-cmp/cmp"
23+ )
24+
25+ // mockConfigProvider is a mock implementation of the ConfigProvider interface for testing.
26+ type mockConfigProvider struct {
27+ serviceYAML string
28+ gapicYAML string
29+ grpcServiceConfig string
30+ transport string
31+ restNumericEnums bool
32+ hasGAPIC bool
33+ }
34+
35+ func (m * mockConfigProvider ) ServiceYAML () string { return m .serviceYAML }
36+ func (m * mockConfigProvider ) GapicYAML () string { return m .gapicYAML }
37+ func (m * mockConfigProvider ) GRPCServiceConfig () string { return m .grpcServiceConfig }
38+ func (m * mockConfigProvider ) Transport () string { return m .transport }
39+ func (m * mockConfigProvider ) HasRESTNumericEnums () bool { return m .restNumericEnums }
40+ func (m * mockConfigProvider ) HasGAPIC () bool { return m .hasGAPIC }
41+
42+ func TestBuild (t * testing.T ) {
43+ // The testdata directory is a curated version of a valid protoc
44+ // import path that contains all the necessary proto definitions.
45+ sourceDir , err := filepath .Abs ("../testdata/generate/source" )
46+ if err != nil {
47+ t .Fatalf ("failed to get absolute path for sourceDir: %v" , err )
48+ }
49+ tests := []struct {
50+ name string
51+ apiPath string
52+ config mockConfigProvider
53+ want []string
54+ }{
55+ {
56+ name : "java_grpc_library rule" ,
57+ apiPath : "google/cloud/workflows/v1" ,
58+ config : mockConfigProvider {
59+ transport : "grpc" ,
60+ grpcServiceConfig : "workflows_grpc_service_config.json" ,
61+ gapicYAML : "workflows_gapic.yaml" ,
62+ serviceYAML : "workflows_v1.yaml" ,
63+ restNumericEnums : true ,
64+ hasGAPIC : true ,
65+ },
66+ want : []string {
67+ "protoc" ,
68+ "--experimental_allow_proto3_optional" ,
69+ "--java_out=/output" ,
70+ "--java_gapic_out=metadata:/output/java_gapic.zip" ,
71+ "--java_gapic_opt=" + strings .Join ([]string {
72+ "api-service-config=" + filepath .Join (sourceDir , "google/cloud/workflows/v1/workflows_v1.yaml" ),
73+ "gapic-config=" + filepath .Join (sourceDir , "google/cloud/workflows/v1/workflows_gapic.yaml" ),
74+ "grpc-service-config=" + filepath .Join (sourceDir , "google/cloud/workflows/v1/workflows_grpc_service_config.json" ),
75+ "transport=grpc" ,
76+ "rest-numeric-enums" ,
77+ }, "," ),
78+ "-I=" + sourceDir ,
79+ filepath .Join (sourceDir , "google/cloud/workflows/v1/workflows.proto" ),
80+ },
81+ },
82+ {
83+ name : "java_proto_library rule with legacy gRPC" ,
84+ apiPath : "google/cloud/secretmanager/v1beta2" ,
85+ config : mockConfigProvider {
86+ transport : "grpc" ,
87+ grpcServiceConfig : "secretmanager_grpc_service_config.json" ,
88+ serviceYAML : "secretmanager_v1beta2.yaml" ,
89+ restNumericEnums : true ,
90+ hasGAPIC : true ,
91+ },
92+ want : []string {
93+ "protoc" ,
94+ "--experimental_allow_proto3_optional" ,
95+ "--java_out=/output" ,
96+ "--java_gapic_out=metadata:/output/java_gapic.zip" ,
97+ "--java_gapic_opt=" + strings .Join ([]string {
98+ "api-service-config=" + filepath .Join (sourceDir , "google/cloud/secretmanager/v1beta2/secretmanager_v1beta2.yaml" ),
99+ "grpc-service-config=" + filepath .Join (sourceDir , "google/cloud/secretmanager/v1beta2/secretmanager_grpc_service_config.json" ),
100+ "transport=grpc" ,
101+ "rest-numeric-enums" ,
102+ }, "," ),
103+ "-I=" + sourceDir ,
104+ filepath .Join (sourceDir , "google/cloud/secretmanager/v1beta2/secretmanager.proto" ),
105+ },
106+ },
107+ {
108+ // Note: we don't have a separate test directory with a proto-only library;
109+ // the config is used to say "don't generate GAPIC".
110+ name : "proto-only" ,
111+ apiPath : "google/cloud/secretmanager/v1beta2" ,
112+ config : mockConfigProvider {
113+ hasGAPIC : false ,
114+ },
115+ want : []string {
116+ "protoc" ,
117+ "--experimental_allow_proto3_optional" ,
118+ "--java_out=/output" ,
119+ "-I=" + sourceDir ,
120+ filepath .Join (sourceDir , "google/cloud/secretmanager/v1beta2/secretmanager.proto" ),
121+ },
122+ },
123+ }
124+
125+ for _ , tt := range tests {
126+ t .Run (tt .name , func (t * testing.T ) {
127+ got , err := Build (filepath .Join (sourceDir , tt .apiPath ), & tt .config , sourceDir , "/output" )
128+ if err != nil {
129+ t .Fatalf ("Build() failed: %v" , err )
130+ }
131+
132+ if diff := cmp .Diff (tt .want , got ); diff != "" {
133+ t .Errorf ("Build() mismatch (-want +got):\n %s" , diff )
134+ }
135+ })
136+ }
137+ }
0 commit comments