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

mobile: Rewrite the JNI code for XdsTestServer #33197

Merged
merged 1 commit into from
Mar 29, 2024
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
4 changes: 1 addition & 3 deletions mobile/test/common/integration/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,12 @@ envoy_cc_test_library(
)

envoy_cc_test_library(
name = "xds_test_server_interface_lib",
name = "xds_test_server_lib",
srcs = [
"xds_test_server.cc",
"xds_test_server_interface.cc",
],
hdrs = [
"xds_test_server.h",
"xds_test_server_interface.h",
],
repository = "@envoy",
deps = [
Expand Down
58 changes: 0 additions & 58 deletions mobile/test/common/integration/xds_test_server_interface.cc

This file was deleted.

42 changes: 0 additions & 42 deletions mobile/test/common/integration/xds_test_server_interface.h

This file was deleted.

20 changes: 18 additions & 2 deletions mobile/test/java/io/envoyproxy/envoymobile/engine/testing/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ android_library(
data = [
"//test/jni:libenvoy_jni_http_test_server_factory.so",
],
visibility = ["//test:__subpackages__"],
visibility = ["//visibility:public"],
deps = [
"//library/java/io/envoyproxy/envoymobile/engine:envoy_base_engine_lib",
"//library/kotlin/io/envoyproxy/envoymobile:envoy_lib",
Expand All @@ -46,7 +46,23 @@ android_library(
data = [
"//test/jni:libenvoy_jni_http_proxy_test_server_factory.so",
],
visibility = ["//test:__subpackages__"],
visibility = ["//visibility:public"],
deps = [
"//library/java/io/envoyproxy/envoymobile/engine:envoy_base_engine_lib",
"//library/kotlin/io/envoyproxy/envoymobile:envoy_lib",
],
)

android_library(
name = "xds_test_server_factory_lib",
testonly = True,
srcs = [
"XdsTestServerFactory.java",
],
data = [
"//test/jni:libenvoy_jni_xds_test_server_factory.so",
],
visibility = ["//visibility:public"],
deps = [
"//library/java/io/envoyproxy/envoymobile/engine:envoy_base_engine_lib",
"//library/kotlin/io/envoyproxy/envoymobile:envoy_lib",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,84 +1,15 @@
package io.envoyproxy.envoymobile.engine.testing;

import java.util.concurrent.atomic.AtomicBoolean;
import io.envoyproxy.envoymobile.engine.EnvoyConfiguration;

/**
* Wrapper class for test JNI functions
*/
public final class TestJni {
private static final AtomicBoolean xdsServerRunning = new AtomicBoolean();

/**
* Initializes the xDS test server.
*
* @throws IllegalStateException if it's already started.
*/
public static void initXdsTestServer() {
if (xdsServerRunning.get()) {
throw new IllegalStateException("xDS server is already running");
}
nativeInitXdsTestServer();
}

/**
* Starts the xDS test server.
*
* @throws IllegalStateException if it's already started.
*/
public static void startXdsTestServer() {
if (!xdsServerRunning.compareAndSet(false, true)) {
throw new IllegalStateException("xDS server is already running");
}
nativeStartXdsTestServer();
}

/**
* Sends the `DiscoveryResponse` message in the YAML format.
*/
public static void sendDiscoveryResponse(String yaml) {
if (!xdsServerRunning.get()) {
throw new IllegalStateException("xDS server is not running");
}
nativeSendDiscoveryResponse(yaml);
}

/**
* Shutdowns the xDS test server. No-op if the server is already shutdown.
*/
public static void shutdownXdsTestServer() {
if (!xdsServerRunning.compareAndSet(true, false)) {
return;
}
nativeShutdownXdsTestServer();
}

/**
* Gets the xDS test server host.
*/
public static String getXdsTestServerHost() { return nativeGetXdsTestServerHost(); }

/**
* Gets the xDS test server port.
*/
public static int getXdsTestServerPort() { return nativeGetXdsTestServerPort(); }

public static String createYaml(EnvoyConfiguration envoyConfiguration) {
return nativeCreateYaml(envoyConfiguration.createBootstrap());
}

private static native void nativeInitXdsTestServer();

private static native String nativeGetXdsTestServerHost();

private static native int nativeGetXdsTestServerPort();

private static native void nativeStartXdsTestServer();

private static native void nativeSendDiscoveryResponse(String yaml);

private static native int nativeShutdownXdsTestServer();

private static native String nativeCreateYaml(long bootstrap);

private TestJni() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.envoyproxy.envoymobile.engine.testing;

/** An xDS test server factory. */
public class XdsTestServerFactory {
/** The instance of {@link XdsTestServer}. */
public static class XdsTestServer {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering if it would be better to have the XdsTestServer as a top-level class, outside of XdsTestServerFactory? Same for the other HTTP servers from previous PRs. I think it'll make the code easier to read, but just a personal preference. I consider the XdsTestServer to be a top level construct, not dependent on XdsTestServerFactory. It's just that XdsTestServerFactory gives us XdsTestServer instances

Copy link
Member Author

Choose a reason for hiding this comment

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

Unfortunately it's not possible to do it in Java unless we create two separate files. Having a single file is better IMO.

Copy link
Member Author

@fredyw fredyw Mar 29, 2024

Choose a reason for hiding this comment

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

Another reason Xds|Http|HttpProxy is inside the factory is so that it can have a private constructor. That's because there's no way to manually create the instance without having to use the factory (the handle will need to come from the native code). If we were about to make Xds|Http|HttpProxy outside, the constructor would have to be public. IOW, we want the Factory to be the only way to create the instance.

Copy link
Contributor

Choose a reason for hiding this comment

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

ah ok, yeah agree, this is better then, thanks for the explanation!

private final long handle; // Used by the native code.
private final String host;
private final int port;

private XdsTestServer(long handle, String host, int port) {
this.handle = handle;
this.host = host;
this.port = port;
}

/** Starts the xDS server. */
public native void start();

/** Gets the xDS host. */
public String getHost() { return host; }

/** Gets the xDS port. */
public int getPort() { return port; }

/**
* Sends a static `envoy::service::discovery::v3::DiscoveryResponse` message with the specified
* cluster name.
*
* TODO(fredyw): Update to take a DiscoveryResponse proto.
*/
public native void sendDiscoveryResponse(String clusterName);

/** Shuts down the xDS server. */
public native void shutdown();
}

static { System.loadLibrary("envoy_jni_xds_test_server_factory"); }

/** Creates a new instance of {@link XdsTestServer}. */
public static native XdsTestServer create();
}
40 changes: 35 additions & 5 deletions mobile/test/jni/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ cc_library(
name = "envoy_jni_with_test_extensions_lib",
testonly = True,
deps = [
":server_envoy_jni_lib",
":test_jni_impl_lib",
"//library/jni:envoy_jni_lib",
"@envoy_build_config//:test_extensions",
],
)

# Library which contains all the JNI related targets.
cc_library(
name = "server_envoy_jni_lib",
name = "test_jni_impl_lib",
testonly = True,
srcs = [
"test_jni_impl.cc",
Expand All @@ -29,8 +29,7 @@ cc_library(
}),
deps = [
"//library/jni:envoy_jni_lib",
"//test/common/integration:test_server_lib",
"//test/common/integration:xds_test_server_interface_lib",
"@envoy//test/test_common:utility_lib",
],
# We need this to ensure that we link this into the .so even though there are no code references.
alwayslink = True,
Expand Down Expand Up @@ -98,6 +97,37 @@ cc_binary(
],
)

# Library which contains JNI functions for the XdsTestServer.
cc_library(
name = "jni_xds_test_server_factory_lib",
testonly = True,
srcs = [
"jni_xds_test_server_factory.cc",
],
linkopts = select({
"@envoy//bazel:dbg_build": ["-Wl,--build-id=sha1"],
"//conditions:default": [],
}),
deps = [
"//library/jni:envoy_jni_lib",
"//library/jni:jni_helper_lib",
"//library/jni:jni_utility_lib",
"//test/common/integration:xds_test_server_lib",
],
# We need this to ensure that we link this into the .so even though there are no code references.
alwayslink = True,
)

cc_binary(
name = "libenvoy_jni_xds_test_server_factory.so",
testonly = True,
linkshared = True,
deps = [
":jni_xds_test_server_factory_lib",
"@envoy_mobile_extra_jni_deps//:extra_jni_dep",
],
)

# Base binary (.so) for testing
cc_binary(
name = "libenvoy_jni_with_test_extensions.so",
Expand All @@ -124,7 +154,7 @@ cc_library(
name = "envoy_jni_with_test_and_listener_extensions_lib",
testonly = True,
deps = [
":server_envoy_jni_lib",
":test_jni_impl_lib",
"//library/jni:envoy_jni_lib",
"@envoy//source/common/listener_manager:listener_manager_lib",
],
Expand Down
Loading