Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add conformance tests for lite runtime #148

Merged
merged 4 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ jobs:
${{ runner.os }}-go-
- name: Run conformance tests
run: make conformancerun
- name: Upload test reports
uses: actions/upload-artifact@v3
if: always()
with:
name: conformance-test-reports
path: |
conformance/google-java/build/reports/tests
conformance/google-javalite/build/reports/tests
retention-days: 7
license-headers:
runs-on: ubuntu-latest
steps:
Expand Down
7 changes: 2 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,8 @@ clean: ## Cleans the underlying build.
./gradlew $(GRADLE_ARGS) clean

.PHONY: conformancerun
conformancerun: conformancerunjava ## Run the conformance tests.

.PHONY: conformancerunjava
conformancerunjava: generate ## Run the conformance tests for protoc-gen-java integration.
./gradlew $(GRADLE_ARGS) conformance:google-java:test
conformancerun: generate ## Run the conformance tests.
./gradlew $(GRADLE_ARGS) conformance:google-java:test conformance:google-javalite:test

ifeq ($(UNAME_OS),Darwin)
PROTOC_OS := osx
Expand Down
4 changes: 4 additions & 0 deletions conformance/buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ plugins:
- plugin: connect-kotlin
out: google-javalite/build/generated/sources/bufgen
path: ./protoc-gen-connect-kotlin/build/install/protoc-gen-connect-kotlin/bin/protoc-gen-connect-kotlin
opt:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the lite tests to use generated code with the same args as the full runtime tests.

- generateCallbackMethods=true
- generateCoroutineMethods=true
- generateBlockingUnaryMethods=true
- plugin: java
out: google-javalite/build/generated/sources/bufgen
protoc_path: .tmp/bin/protoc
Expand Down
3 changes: 3 additions & 0 deletions conformance/common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ plugins {
dependencies {
implementation(libs.okio.core)
implementation(libs.okhttp.tls)
implementation(libs.junit)
implementation(libs.assertj)
implementation(libs.testcontainers)
implementation(project(":okhttp"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright 2022-2023 The Connect Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.connectrpc.conformance

import com.connectrpc.ProtocolClientConfig
import com.connectrpc.RequestCompression
import com.connectrpc.SerializationStrategy
import com.connectrpc.compression.GzipCompressionPool
import com.connectrpc.conformance.ssl.sslContext
import com.connectrpc.impl.ProtocolClient
import com.connectrpc.okhttp.ConnectOkHttpClient
import com.connectrpc.protocols.NetworkProtocol
import okhttp3.OkHttpClient
import okhttp3.Protocol
import org.junit.ClassRule
import org.junit.runners.Parameterized
import org.testcontainers.containers.GenericContainer
import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy
import java.time.Duration
import java.util.Base64

abstract class BaseConformanceTest(
private val protocol: NetworkProtocol,
private val serverType: ServerType,
) {
lateinit var connectClient: ProtocolClient
lateinit var shortTimeoutConnectClient: ProtocolClient

companion object {
private const val CONFORMANCE_VERSION = "88f85130640b46c0837e0d58c0484d83a110f418"

@JvmStatic
@Parameterized.Parameters(name = "client={0},server={1}")
fun data(): Iterable<Array<Any>> {
return arrayListOf(
arrayOf(NetworkProtocol.CONNECT, ServerType.CONNECT_GO),
arrayOf(NetworkProtocol.GRPC, ServerType.CONNECT_GO),
arrayOf(NetworkProtocol.GRPC_WEB, ServerType.CONNECT_GO),
arrayOf(NetworkProtocol.GRPC, ServerType.GRPC_GO),
)
}

@JvmField
@ClassRule
val CONFORMANCE_CONTAINER_CONNECT = GenericContainer("connectrpc/conformance:$CONFORMANCE_VERSION")
.withExposedPorts(8080, 8081)
.withCommand(
"/usr/local/bin/serverconnect",
"--h1port",
"8080",
"--h2port",
"8081",
"--cert",
"cert/localhost.crt",
"--key",
"cert/localhost.key",
)
.waitingFor(HostPortWaitStrategy().forPorts(8081))

@JvmField
@ClassRule
val CONFORMANCE_CONTAINER_GRPC = GenericContainer("connectrpc/conformance:$CONFORMANCE_VERSION")
.withExposedPorts(8081)
.withCommand(
"/usr/local/bin/servergrpc",
"--port",
"8081",
"--cert",
"cert/localhost.crt",
"--key",
"cert/localhost.key",
)
.waitingFor(HostPortWaitStrategy().forPorts(8081))
}

fun init(serializationStrategy: SerializationStrategy) {
val serverPort = if (serverType == ServerType.CONNECT_GO) CONFORMANCE_CONTAINER_CONNECT.getMappedPort(8081) else CONFORMANCE_CONTAINER_GRPC.getMappedPort(8081)
val host = "https://localhost:$serverPort"
val (sslSocketFactory, trustManager) = sslContext()
val client = OkHttpClient.Builder()
.protocols(listOf(Protocol.HTTP_2, Protocol.HTTP_1_1))
.connectTimeout(Duration.ofMinutes(1))
.readTimeout(Duration.ofMinutes(1))
.writeTimeout(Duration.ofMinutes(1))
.callTimeout(Duration.ofMinutes(1))
.sslSocketFactory(sslSocketFactory, trustManager)
.build()
shortTimeoutConnectClient = ProtocolClient(
httpClient = ConnectOkHttpClient(
client.newBuilder()
.connectTimeout(Duration.ofMillis(1))
.readTimeout(Duration.ofMillis(1))
.writeTimeout(Duration.ofMillis(1))
.callTimeout(Duration.ofMillis(1))
.build(),
),
ProtocolClientConfig(
host = host,
serializationStrategy = serializationStrategy,
networkProtocol = protocol,
requestCompression = RequestCompression(10, GzipCompressionPool),
compressionPools = listOf(GzipCompressionPool),
),
)
connectClient = ProtocolClient(
httpClient = ConnectOkHttpClient(client),
ProtocolClientConfig(
host = host,
serializationStrategy = serializationStrategy,
networkProtocol = protocol,
requestCompression = RequestCompression(10, GzipCompressionPool),
compressionPools = listOf(GzipCompressionPool),
),
)
}

fun b64Encode(trailingValue: ByteArray): String {
return String(Base64.getEncoder().encode(trailingValue))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package com.connectrpc.conformance
package com.connectrpc.conformance.java

import com.connectrpc.Code
import com.connectrpc.ConnectException
import com.connectrpc.ProtocolClientConfig
import com.connectrpc.RequestCompression
import com.connectrpc.compression.GzipCompressionPool
import com.connectrpc.conformance.ssl.sslContext
import com.connectrpc.conformance.BaseConformanceTest
import com.connectrpc.conformance.ServerType
import com.connectrpc.conformance.v1.ErrorDetail
import com.connectrpc.conformance.v1.PayloadType
import com.connectrpc.conformance.v1.StreamingOutputCallResponse
Expand All @@ -34,8 +32,6 @@ import com.connectrpc.conformance.v1.streamingInputCallRequest
import com.connectrpc.conformance.v1.streamingOutputCallRequest
import com.connectrpc.extensions.GoogleJavaProtobufStrategy
import com.connectrpc.getOrThrow
import com.connectrpc.impl.ProtocolClient
import com.connectrpc.okhttp.ConnectOkHttpClient
import com.connectrpc.protocols.NetworkProtocol
import com.google.protobuf.ByteString
import com.google.protobuf.empty
Expand All @@ -44,120 +40,27 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Protocol
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.fail
import org.junit.Before
import org.junit.ClassRule
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters
import org.testcontainers.containers.GenericContainer
import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy
import java.time.Duration
import java.util.Base64
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

@RunWith(Parameterized::class)
class Conformance(
private val protocol: NetworkProtocol,
private val serverType: ServerType,
) {
private lateinit var connectClient: ProtocolClient
private lateinit var shortTimeoutConnectClient: ProtocolClient
class ConformanceTest(
protocol: NetworkProtocol,
serverType: ServerType,
) : BaseConformanceTest(protocol, serverType) {

private lateinit var unimplementedServiceClient: UnimplementedServiceClient
private lateinit var testServiceConnectClient: TestServiceClient

companion object {
private const val CONFORMANCE_VERSION = "88f85130640b46c0837e0d58c0484d83a110f418"

@JvmStatic
@Parameters(name = "client={0},server={1}")
fun data(): Iterable<Array<Any>> {
return arrayListOf(
arrayOf(NetworkProtocol.CONNECT, ServerType.CONNECT_GO),
arrayOf(NetworkProtocol.GRPC, ServerType.CONNECT_GO),
arrayOf(NetworkProtocol.GRPC_WEB, ServerType.CONNECT_GO),
arrayOf(NetworkProtocol.GRPC, ServerType.GRPC_GO),
)
}

@JvmField
@ClassRule
val CONFORMANCE_CONTAINER_CONNECT = GenericContainer("connectrpc/conformance:$CONFORMANCE_VERSION")
.withExposedPorts(8080, 8081)
.withCommand(
"/usr/local/bin/serverconnect",
"--h1port",
"8080",
"--h2port",
"8081",
"--cert",
"cert/localhost.crt",
"--key",
"cert/localhost.key",
)
.waitingFor(HostPortWaitStrategy().forPorts(8081))

@JvmField
@ClassRule
val CONFORMANCE_CONTAINER_GRPC = GenericContainer("connectrpc/conformance:$CONFORMANCE_VERSION")
.withExposedPorts(8081)
.withCommand(
"/usr/local/bin/servergrpc",
"--port",
"8081",
"--cert",
"cert/localhost.crt",
"--key",
"cert/localhost.key",
)
.waitingFor(HostPortWaitStrategy().forPorts(8081))
}

@Before
fun before() {
val serverPort = if (serverType == ServerType.CONNECT_GO) CONFORMANCE_CONTAINER_CONNECT.getMappedPort(8081) else CONFORMANCE_CONTAINER_GRPC.getMappedPort(8081)
val host = "https://localhost:$serverPort"
val (sslSocketFactory, trustManager) = sslContext()
val client = OkHttpClient.Builder()
.protocols(listOf(Protocol.HTTP_2, Protocol.HTTP_1_1))
.connectTimeout(Duration.ofMinutes(1))
.readTimeout(Duration.ofMinutes(1))
.writeTimeout(Duration.ofMinutes(1))
.callTimeout(Duration.ofMinutes(1))
.sslSocketFactory(sslSocketFactory, trustManager)
.build()
shortTimeoutConnectClient = ProtocolClient(
httpClient = ConnectOkHttpClient(
client.newBuilder()
.connectTimeout(Duration.ofMillis(1))
.readTimeout(Duration.ofMillis(1))
.writeTimeout(Duration.ofMillis(1))
.callTimeout(Duration.ofMillis(1))
.build(),
),
ProtocolClientConfig(
host = host,
serializationStrategy = GoogleJavaProtobufStrategy(),
networkProtocol = protocol,
requestCompression = RequestCompression(10, GzipCompressionPool),
compressionPools = listOf(GzipCompressionPool),
),
)
connectClient = ProtocolClient(
httpClient = ConnectOkHttpClient(client),
ProtocolClientConfig(
host = host,
serializationStrategy = GoogleJavaProtobufStrategy(),
networkProtocol = protocol,
requestCompression = RequestCompression(10, GzipCompressionPool),
compressionPools = listOf(GzipCompressionPool),
),
)
init(GoogleJavaProtobufStrategy())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only real change between the two clients.

testServiceConnectClient = TestServiceClient(connectClient)
unimplementedServiceClient = UnimplementedServiceClient(connectClient)
}
Expand Down Expand Up @@ -798,8 +701,4 @@ class Conformance(
assertThat(countDownLatch.count).isZero()
}
}

private fun b64Encode(trailingValue: ByteArray): String {
return String(Base64.getEncoder().encode(trailingValue))
}
}
5 changes: 3 additions & 2 deletions conformance/google-javalite/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ sourceSets {

dependencies {
implementation(libs.kotlin.coroutines.core)
implementation(libs.protobuf.kotlin)
implementation(libs.protobuf.kotlinlite)
implementation(project(":conformance:common"))
implementation(project(":extensions:google-java"))
implementation(project(":extensions:google-javalite"))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These dependencies weren't correct before.

implementation(project(":okhttp"))

testImplementation(libs.okhttp.core)
Expand All @@ -33,4 +33,5 @@ dependencies {
testImplementation(libs.mockito)
testImplementation(libs.kotlin.coroutines.core)
testImplementation(libs.testcontainers)
testImplementation(libs.slf4j.simple)
}
Loading