Skip to content

Commit 9bd518f

Browse files
committed
Adds new conformance/client module
- This contains the new conformance client, for the new conformance tests - The base module has all of the logic and uses the Java Lite runtime (since it is lowest common denominator) - There are google-java and google-javalite modules which have the main functions for running the clients. The google-java module swaps out the javalite runtime for the java runtime. The client module (with shared logic) can convert from javalite generated messages to java generated messages by serializing and deserializing - The adapt package in the client module provides a glimpse of what I think better stream APIs would look like. I'd like to update the actual stream interfaces to more closely match this in the future. For now, the code just adapts exising interfaces to these. - To test the different unary invocation styles, there is an enum for each style and a method in UnaryClient that is an adapter: a single interface for the actual conformance client to use (that looks like the Callback style), but under the hood it will call the suspend, callback, or blocking methods based on the desired invocation style. - The actual client logic is TODO, in various handle* methods of the Client class. This felt like a big enough chunk already, so I figured it would be good to get this reviewed before plowing through the rest.
1 parent 4f9af3d commit 9bd518f

30 files changed

+1408
-0
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ generate: $(PROTOC) buildplugin generateconformance generateexamples ## Generate
7474
.PHONY: generateconformance
7575
generateconformance: $(PROTOC) buildplugin ## Generate protofiles for conformance tests.
7676
buf generate --template conformance/buf.gen.yaml -o conformance conformance/proto
77+
buf generate --template conformance/client/buf.gen.yaml -o conformance/client buf.build/connectrpc/conformance:v1.0.0-rc1
78+
buf generate --template conformance/client/buf.gen.lite.yaml -o conformance/client buf.build/connectrpc/conformance:v1.0.0-rc1
7779

7880
.PHONY: generateexamples
7981
generateexamples: $(PROTOC) buildplugin ## Generate proto files for example apps.

conformance/client/buf.gen.lite.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
version: v1
2+
managed:
3+
enabled: true
4+
java_package_prefix: com.connectrpc.lite
5+
plugins:
6+
- plugin: connect-kotlin
7+
out: build/generated/sources/bufgen
8+
path: ./protoc-gen-connect-kotlin/build/install/protoc-gen-connect-kotlin/bin/protoc-gen-connect-kotlin
9+
opt:
10+
- generateCallbackMethods=true
11+
- generateCoroutineMethods=true
12+
- generateBlockingUnaryMethods=true
13+
- plugin: java
14+
out: build/generated/sources/bufgen
15+
protoc_path: .tmp/bin/protoc
16+
opt: lite
17+
- plugin: kotlin
18+
out: build/generated/sources/bufgen
19+
protoc_path: .tmp/bin/protoc
20+
opt: lite

conformance/client/buf.gen.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
version: v1
2+
managed:
3+
enabled: true
4+
plugins:
5+
- plugin: connect-kotlin
6+
out: google-java/build/generated/sources/bufgen
7+
path: ./protoc-gen-connect-kotlin/build/install/protoc-gen-connect-kotlin/bin/protoc-gen-connect-kotlin
8+
opt:
9+
- generateCallbackMethods=true
10+
- generateCoroutineMethods=true
11+
- generateBlockingUnaryMethods=true
12+
- plugin: java
13+
out: google-java/build/generated/sources/bufgen
14+
protoc_path: .tmp/bin/protoc
15+
- plugin: kotlin
16+
out: google-java/build/generated/sources/bufgen
17+
protoc_path: .tmp/bin/protoc

conformance/client/build.gradle.kts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
plugins {
2+
kotlin("jvm")
3+
}
4+
5+
// This base project contains generated code for the lite runtime
6+
// and depends on the Google Protobuf Java Lite runtime.
7+
// The main client logic is implemented in terms of generated
8+
// code for that lite runtime.
9+
//
10+
// The non-lite runtime excludes the Google Protobuf Java Lite
11+
// runtime and instead uses the full Java runtime. It then can
12+
// adapt from the lite-runtime-generated code by serializing to
13+
// bytes and then de-serializing into non-lite-generated types.
14+
15+
sourceSets {
16+
main {
17+
java {
18+
srcDir("build/generated/sources/bufgen")
19+
}
20+
}
21+
}
22+
23+
dependencies {
24+
implementation(project(":okhttp"))
25+
implementation(libs.kotlin.coroutines.core)
26+
implementation(libs.protobuf.kotlin)
27+
implementation(libs.protobuf.javalite)
28+
implementation(libs.okio.core)
29+
implementation(libs.okhttp.tls)
30+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
plugins {
2+
kotlin("jvm")
3+
}
4+
5+
tasks {
6+
compileKotlin {
7+
kotlinOptions {
8+
// Generated Kotlin code for protobufs uses OptIn annotation
9+
freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
10+
}
11+
}
12+
}
13+
14+
// This project contains an alternate copy of the generated
15+
// types, generated for the non-lite runtime.
16+
sourceSets {
17+
main {
18+
java {
19+
srcDir("build/generated/sources/bufgen")
20+
}
21+
}
22+
}
23+
24+
dependencies {
25+
implementation(project(":conformance:client")) {
26+
exclude(group = "com.google.protobuf", module = "protobuf-javalite")
27+
}
28+
implementation(project(":extensions:google-java"))
29+
implementation(project(":okhttp"))
30+
implementation(libs.kotlin.coroutines.core)
31+
implementation(libs.protobuf.kotlin)
32+
implementation(libs.protobuf.java)
33+
implementation(libs.okio.core)
34+
implementation(libs.okhttp.tls)
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2022-2023 The Connect Authors
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 com.connectrpc.conformance.client.java
16+
17+
import com.connectrpc.Headers
18+
import com.connectrpc.conformance.client.adapt.BidiStreamClient
19+
import com.connectrpc.conformance.v1.BidiStreamRequest
20+
import com.connectrpc.conformance.v1.BidiStreamResponse
21+
import com.connectrpc.conformance.v1.ConformanceServiceClient
22+
23+
class JavaBidiStreamClient(
24+
private val client: ConformanceServiceClient,
25+
) : BidiStreamClient<BidiStreamRequest, BidiStreamResponse>(
26+
BidiStreamRequest.getDefaultInstance(),
27+
BidiStreamResponse.getDefaultInstance(),
28+
) {
29+
override suspend fun execute(headers: Headers): BidiStream<BidiStreamRequest, BidiStreamResponse> {
30+
return BidiStream.new(client.bidiStream(headers))
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2022-2023 The Connect Authors
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 com.connectrpc.conformance.client.java
16+
17+
import com.connectrpc.Headers
18+
import com.connectrpc.conformance.client.adapt.ClientStreamClient
19+
import com.connectrpc.conformance.v1.ClientStreamRequest
20+
import com.connectrpc.conformance.v1.ClientStreamResponse
21+
import com.connectrpc.conformance.v1.ConformanceServiceClient
22+
23+
class JavaClientStreamClient(
24+
private val client: ConformanceServiceClient,
25+
) : ClientStreamClient<ClientStreamRequest, ClientStreamResponse>(
26+
ClientStreamRequest.getDefaultInstance(),
27+
ClientStreamResponse.getDefaultInstance(),
28+
) {
29+
override suspend fun execute(headers: Headers): ClientStream<ClientStreamRequest, ClientStreamResponse> {
30+
return ClientStream.new(client.clientStream(headers))
31+
}
32+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2022-2023 The Connect Authors
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 com.connectrpc.conformance.client.java
16+
17+
import com.connectrpc.SerializationStrategy
18+
import com.connectrpc.conformance.client.adapt.BidiStreamClient
19+
import com.connectrpc.conformance.client.adapt.ClientStreamClient
20+
import com.connectrpc.conformance.client.adapt.Invoker
21+
import com.connectrpc.conformance.client.adapt.ServerStreamClient
22+
import com.connectrpc.conformance.client.adapt.UnaryClient
23+
import com.connectrpc.conformance.v1.ConformanceServiceClient
24+
import com.connectrpc.extensions.GoogleJavaJSONStrategy
25+
import com.connectrpc.extensions.GoogleJavaProtobufStrategy
26+
import com.connectrpc.impl.ProtocolClient
27+
import com.connectrpc.lite.connectrpc.conformance.v1.Codec
28+
29+
class JavaInvoker(
30+
protocolClient: ProtocolClient,
31+
) : Invoker {
32+
private val client = ConformanceServiceClient(protocolClient)
33+
override fun unaryClient(): UnaryClient<*, *> {
34+
return JavaUnaryClient(client)
35+
}
36+
37+
override fun unimplementedClient(): UnaryClient<*, *> {
38+
return JavaUnimplementedClient(client)
39+
}
40+
41+
override fun clientStreamClient(): ClientStreamClient<*, *> {
42+
return JavaClientStreamClient(client)
43+
}
44+
45+
override fun serverStreamClient(): ServerStreamClient<*, *> {
46+
return JavaServerStreamClient(client)
47+
}
48+
49+
override fun bidiStreamClient(): BidiStreamClient<*, *> {
50+
return JavaBidiStreamClient(client)
51+
}
52+
53+
companion object {
54+
fun serializationStrategy(codec: Codec): SerializationStrategy {
55+
return when (codec) {
56+
Codec.CODEC_PROTO -> GoogleJavaProtobufStrategy()
57+
Codec.CODEC_JSON -> GoogleJavaJSONStrategy()
58+
else -> throw RuntimeException("unsupported codec $codec")
59+
}
60+
}
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2022-2023 The Connect Authors
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 com.connectrpc.conformance.client.java
16+
17+
import com.connectrpc.Headers
18+
import com.connectrpc.conformance.client.adapt.ResponseStream
19+
import com.connectrpc.conformance.client.adapt.ServerStreamClient
20+
import com.connectrpc.conformance.v1.ConformanceServiceClient
21+
import com.connectrpc.conformance.v1.ServerStreamRequest
22+
import com.connectrpc.conformance.v1.ServerStreamResponse
23+
24+
class JavaServerStreamClient(
25+
private val client: ConformanceServiceClient,
26+
) : ServerStreamClient<ServerStreamRequest, ServerStreamResponse>(
27+
ServerStreamRequest.getDefaultInstance(),
28+
ServerStreamResponse.getDefaultInstance(),
29+
) {
30+
override suspend fun execute(req: ServerStreamRequest, headers: Headers): ResponseStream<ServerStreamResponse> {
31+
val stream = client.serverStream(headers)
32+
stream.sendAndClose(req)
33+
return ResponseStream.new(stream)
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2022-2023 The Connect Authors
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 com.connectrpc.conformance.client.java
16+
17+
import com.connectrpc.Headers
18+
import com.connectrpc.ResponseMessage
19+
import com.connectrpc.UnaryBlockingCall
20+
import com.connectrpc.conformance.client.adapt.UnaryClient
21+
import com.connectrpc.conformance.v1.ConformanceServiceClient
22+
import com.connectrpc.conformance.v1.UnaryRequest
23+
import com.connectrpc.conformance.v1.UnaryResponse
24+
import com.connectrpc.http.Cancelable
25+
26+
class JavaUnaryClient(
27+
private val client: ConformanceServiceClient,
28+
) : UnaryClient<UnaryRequest, UnaryResponse>(
29+
UnaryRequest.getDefaultInstance(),
30+
UnaryResponse.getDefaultInstance(),
31+
) {
32+
override suspend fun execute(req: UnaryRequest, headers: Headers): ResponseMessage<UnaryResponse> {
33+
return client.unary(req, headers)
34+
}
35+
36+
override fun execute(
37+
req: UnaryRequest,
38+
headers: Headers,
39+
onFinish: (ResponseMessage<UnaryResponse>) -> Unit,
40+
): Cancelable {
41+
return client.unary(req, headers, onFinish)
42+
}
43+
44+
override fun blocking(req: UnaryRequest, headers: Headers): UnaryBlockingCall<UnaryResponse> {
45+
return client.unaryBlocking(req, headers)
46+
}
47+
}

0 commit comments

Comments
 (0)