Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0a670eb381 | |||
| 14afb325c3 | |||
| af42891d5a | |||
| 01a51df053 |
@@ -0,0 +1,41 @@
|
|||||||
|
# Java Client
|
||||||
|
|
||||||
|
The Java client workspace contains the Gradle scaffold for the MXAccess Gateway
|
||||||
|
client library, generated protobuf/gRPC bindings, a test CLI project, and JUnit
|
||||||
|
tests.
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
```text
|
||||||
|
clients/java/
|
||||||
|
settings.gradle
|
||||||
|
build.gradle
|
||||||
|
src/main/generated/
|
||||||
|
mxgateway-client/
|
||||||
|
mxgateway-cli/
|
||||||
|
```
|
||||||
|
|
||||||
|
`mxgateway-client` generates Java protobuf and gRPC sources from
|
||||||
|
`../../src/MxGateway.Contracts/Protos`. The Gradle protobuf plugin writes those
|
||||||
|
generated sources under `src/main/generated`, which matches the client proto
|
||||||
|
manifest in `../proto/proto-inputs.json`. Do not edit generated files by hand.
|
||||||
|
|
||||||
|
`mxgateway-cli` depends on `mxgateway-client` and provides the `mxgw-java`
|
||||||
|
application entry point used by later CLI implementation work.
|
||||||
|
|
||||||
|
## Build And Test
|
||||||
|
|
||||||
|
Run the Java checks from `clients/java`:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
gradle test
|
||||||
|
```
|
||||||
|
|
||||||
|
The build uses the Java 21 Gradle toolchain, compiles generated protobuf/gRPC
|
||||||
|
code, and runs JUnit 5 tests for the scaffold and CLI entry point.
|
||||||
|
|
||||||
|
## Related Documentation
|
||||||
|
|
||||||
|
- [Client Proto Generation](../../docs/client-proto-generation.md)
|
||||||
|
- [Java Client Detailed Design](../../docs/clients-java-design.md)
|
||||||
|
- [Java Style Guide](../../docs/style-guides/JavaStyleGuide.md)
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
plugins {
|
||||||
|
id 'base'
|
||||||
|
}
|
||||||
|
|
||||||
|
ext {
|
||||||
|
grpcVersion = '1.76.0'
|
||||||
|
junitVersion = '5.14.1'
|
||||||
|
picocliVersion = '4.7.7'
|
||||||
|
protobufVersion = '4.33.1'
|
||||||
|
}
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
group = 'com.dohertylan.mxgateway'
|
||||||
|
version = '0.1.0'
|
||||||
|
|
||||||
|
pluginManager.withPlugin('java') {
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(21)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
options.encoding = 'UTF-8'
|
||||||
|
options.release = 21
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(Test).configureEach {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testImplementation platform("org.junit:junit-bom:${junitVersion}")
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
|
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
plugins {
|
||||||
|
id 'application'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(':mxgateway-client')
|
||||||
|
implementation "info.picocli:picocli:${picocliVersion}"
|
||||||
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
mainClass = 'com.dohertylan.mxgateway.cli.MxGatewayCli'
|
||||||
|
}
|
||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
package com.dohertylan.mxgateway.cli;
|
||||||
|
|
||||||
|
import com.dohertylan.mxgateway.client.MxGatewayClientVersion;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import picocli.CommandLine;
|
||||||
|
import picocli.CommandLine.Command;
|
||||||
|
import picocli.CommandLine.Model.CommandSpec;
|
||||||
|
import picocli.CommandLine.Spec;
|
||||||
|
|
||||||
|
@Command(
|
||||||
|
name = "mxgw-java",
|
||||||
|
mixinStandardHelpOptions = true,
|
||||||
|
description = "MXAccess Gateway Java test CLI.",
|
||||||
|
subcommands = MxGatewayCli.VersionCommand.class)
|
||||||
|
public final class MxGatewayCli implements Callable<Integer> {
|
||||||
|
@Spec
|
||||||
|
private CommandSpec spec;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
int exitCode = new CommandLine(new MxGatewayCli()).execute(args);
|
||||||
|
System.exit(exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int execute(PrintWriter out, PrintWriter err, String... args) {
|
||||||
|
CommandLine commandLine = new CommandLine(new MxGatewayCli());
|
||||||
|
commandLine.setOut(out);
|
||||||
|
commandLine.setErr(err);
|
||||||
|
return commandLine.execute(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer call() {
|
||||||
|
spec.commandLine().usage(spec.commandLine().getOut());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Command(name = "version", description = "Prints the Java client scaffold version.")
|
||||||
|
public static final class VersionCommand implements Callable<Integer> {
|
||||||
|
@Spec
|
||||||
|
private CommandSpec spec;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer call() {
|
||||||
|
spec.commandLine().getOut().printf(
|
||||||
|
"mxgateway-java %s gatewayProtocolVersion=%d workerProtocolVersion=%d%n",
|
||||||
|
MxGatewayClientVersion.clientVersion(),
|
||||||
|
MxGatewayClientVersion.gatewayProtocolVersion(),
|
||||||
|
MxGatewayClientVersion.workerProtocolVersion());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package com.dohertylan.mxgateway.cli;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
final class MxGatewayCliTests {
|
||||||
|
@Test
|
||||||
|
void versionCommandPrintsProtocolVersions() {
|
||||||
|
StringWriter output = new StringWriter();
|
||||||
|
StringWriter errors = new StringWriter();
|
||||||
|
|
||||||
|
int exitCode = MxGatewayCli.execute(
|
||||||
|
new PrintWriter(output, true),
|
||||||
|
new PrintWriter(errors, true),
|
||||||
|
"version");
|
||||||
|
|
||||||
|
assertEquals(0, exitCode);
|
||||||
|
assertEquals("", errors.toString());
|
||||||
|
assertTrue(output.toString().contains("mxgateway-java 0.1.0"));
|
||||||
|
assertTrue(output.toString().contains("gatewayProtocolVersion=1"));
|
||||||
|
assertTrue(output.toString().contains("workerProtocolVersion=1"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java-library'
|
||||||
|
id 'com.google.protobuf'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api "com.google.protobuf:protobuf-java:${protobufVersion}"
|
||||||
|
api "io.grpc:grpc-protobuf:${grpcVersion}"
|
||||||
|
api "io.grpc:grpc-stub:${grpcVersion}"
|
||||||
|
|
||||||
|
implementation "io.grpc:grpc-netty-shaded:${grpcVersion}"
|
||||||
|
|
||||||
|
compileOnly 'javax.annotation:javax.annotation-api:1.3.2'
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
proto {
|
||||||
|
srcDir rootProject.file('../../src/MxGateway.Contracts/Protos')
|
||||||
|
include 'mxaccess_gateway.proto'
|
||||||
|
include 'mxaccess_worker.proto'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protobuf {
|
||||||
|
protoc {
|
||||||
|
artifact = "com.google.protobuf:protoc:${protobufVersion}"
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
grpc {
|
||||||
|
artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generatedFilesBaseDir = rootProject.file('src/main/generated').absolutePath
|
||||||
|
|
||||||
|
generateProtoTasks {
|
||||||
|
all().configureEach {
|
||||||
|
plugins {
|
||||||
|
grpc {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
package com.dohertylan.mxgateway.client;
|
||||||
|
|
||||||
|
public final class MxGatewayClientVersion {
|
||||||
|
private static final int GATEWAY_PROTOCOL_VERSION = 1;
|
||||||
|
private static final int WORKER_PROTOCOL_VERSION = 1;
|
||||||
|
private static final String CLIENT_VERSION = "0.1.0";
|
||||||
|
|
||||||
|
private MxGatewayClientVersion() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String clientVersion() {
|
||||||
|
return CLIENT_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int gatewayProtocolVersion() {
|
||||||
|
return GATEWAY_PROTOCOL_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int workerProtocolVersion() {
|
||||||
|
return WORKER_PROTOCOL_VERSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package com.dohertylan.mxgateway.client;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import mxaccess_gateway.v1.MxAccessGatewayGrpc;
|
||||||
|
import mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest;
|
||||||
|
import mxaccess_worker.v1.MxaccessWorker.WorkerEnvelope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
final class GeneratedContractSmokeTests {
|
||||||
|
@Test
|
||||||
|
void generatedGatewayAndWorkerContractsCompile() {
|
||||||
|
OpenSessionRequest request = OpenSessionRequest.newBuilder()
|
||||||
|
.setClientSessionName("junit")
|
||||||
|
.build();
|
||||||
|
WorkerEnvelope envelope = WorkerEnvelope.newBuilder()
|
||||||
|
.setProtocolVersion(MxGatewayClientVersion.workerProtocolVersion())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertEquals("junit", request.getClientSessionName());
|
||||||
|
assertEquals("mxaccess_gateway.v1.MxAccessGateway", MxAccessGatewayGrpc.SERVICE_NAME);
|
||||||
|
assertEquals(1, envelope.getProtocolVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void javaTwentyOneToolchainRunsTests() {
|
||||||
|
assertEquals(21, Runtime.version().feature());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
gradlePluginPortal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id 'com.google.protobuf' version '0.9.5'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.name = 'mxaccessgw-java'
|
||||||
|
|
||||||
|
include 'mxgateway-client'
|
||||||
|
include 'mxgateway-cli'
|
||||||
+588
@@ -0,0 +1,588 @@
|
|||||||
|
package mxaccess_gateway.v1;
|
||||||
|
|
||||||
|
import static io.grpc.MethodDescriptor.generateFullMethodName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Public client API for MXAccess sessions hosted by the gateway.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
@io.grpc.stub.annotations.GrpcGenerated
|
||||||
|
public final class MxAccessGatewayGrpc {
|
||||||
|
|
||||||
|
private MxAccessGatewayGrpc() {}
|
||||||
|
|
||||||
|
public static final java.lang.String SERVICE_NAME = "mxaccess_gateway.v1.MxAccessGateway";
|
||||||
|
|
||||||
|
// Static method descriptors that strictly reflect the proto.
|
||||||
|
private static volatile io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply> getOpenSessionMethod;
|
||||||
|
|
||||||
|
@io.grpc.stub.annotations.RpcMethod(
|
||||||
|
fullMethodName = SERVICE_NAME + '/' + "OpenSession",
|
||||||
|
requestType = mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest.class,
|
||||||
|
responseType = mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply.class,
|
||||||
|
methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||||
|
public static io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply> getOpenSessionMethod() {
|
||||||
|
io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest, mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply> getOpenSessionMethod;
|
||||||
|
if ((getOpenSessionMethod = MxAccessGatewayGrpc.getOpenSessionMethod) == null) {
|
||||||
|
synchronized (MxAccessGatewayGrpc.class) {
|
||||||
|
if ((getOpenSessionMethod = MxAccessGatewayGrpc.getOpenSessionMethod) == null) {
|
||||||
|
MxAccessGatewayGrpc.getOpenSessionMethod = getOpenSessionMethod =
|
||||||
|
io.grpc.MethodDescriptor.<mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest, mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply>newBuilder()
|
||||||
|
.setType(io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||||
|
.setFullMethodName(generateFullMethodName(SERVICE_NAME, "OpenSession"))
|
||||||
|
.setSampledToLocalTracing(true)
|
||||||
|
.setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest.getDefaultInstance()))
|
||||||
|
.setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply.getDefaultInstance()))
|
||||||
|
.setSchemaDescriptor(new MxAccessGatewayMethodDescriptorSupplier("OpenSession"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getOpenSessionMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static volatile io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply> getCloseSessionMethod;
|
||||||
|
|
||||||
|
@io.grpc.stub.annotations.RpcMethod(
|
||||||
|
fullMethodName = SERVICE_NAME + '/' + "CloseSession",
|
||||||
|
requestType = mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest.class,
|
||||||
|
responseType = mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply.class,
|
||||||
|
methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||||
|
public static io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply> getCloseSessionMethod() {
|
||||||
|
io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest, mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply> getCloseSessionMethod;
|
||||||
|
if ((getCloseSessionMethod = MxAccessGatewayGrpc.getCloseSessionMethod) == null) {
|
||||||
|
synchronized (MxAccessGatewayGrpc.class) {
|
||||||
|
if ((getCloseSessionMethod = MxAccessGatewayGrpc.getCloseSessionMethod) == null) {
|
||||||
|
MxAccessGatewayGrpc.getCloseSessionMethod = getCloseSessionMethod =
|
||||||
|
io.grpc.MethodDescriptor.<mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest, mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply>newBuilder()
|
||||||
|
.setType(io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||||
|
.setFullMethodName(generateFullMethodName(SERVICE_NAME, "CloseSession"))
|
||||||
|
.setSampledToLocalTracing(true)
|
||||||
|
.setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest.getDefaultInstance()))
|
||||||
|
.setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply.getDefaultInstance()))
|
||||||
|
.setSchemaDescriptor(new MxAccessGatewayMethodDescriptorSupplier("CloseSession"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getCloseSessionMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static volatile io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxCommandReply> getInvokeMethod;
|
||||||
|
|
||||||
|
@io.grpc.stub.annotations.RpcMethod(
|
||||||
|
fullMethodName = SERVICE_NAME + '/' + "Invoke",
|
||||||
|
requestType = mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest.class,
|
||||||
|
responseType = mxaccess_gateway.v1.MxaccessGateway.MxCommandReply.class,
|
||||||
|
methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||||
|
public static io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxCommandReply> getInvokeMethod() {
|
||||||
|
io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest, mxaccess_gateway.v1.MxaccessGateway.MxCommandReply> getInvokeMethod;
|
||||||
|
if ((getInvokeMethod = MxAccessGatewayGrpc.getInvokeMethod) == null) {
|
||||||
|
synchronized (MxAccessGatewayGrpc.class) {
|
||||||
|
if ((getInvokeMethod = MxAccessGatewayGrpc.getInvokeMethod) == null) {
|
||||||
|
MxAccessGatewayGrpc.getInvokeMethod = getInvokeMethod =
|
||||||
|
io.grpc.MethodDescriptor.<mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest, mxaccess_gateway.v1.MxaccessGateway.MxCommandReply>newBuilder()
|
||||||
|
.setType(io.grpc.MethodDescriptor.MethodType.UNARY)
|
||||||
|
.setFullMethodName(generateFullMethodName(SERVICE_NAME, "Invoke"))
|
||||||
|
.setSampledToLocalTracing(true)
|
||||||
|
.setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest.getDefaultInstance()))
|
||||||
|
.setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxCommandReply.getDefaultInstance()))
|
||||||
|
.setSchemaDescriptor(new MxAccessGatewayMethodDescriptorSupplier("Invoke"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getInvokeMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static volatile io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxEvent> getStreamEventsMethod;
|
||||||
|
|
||||||
|
@io.grpc.stub.annotations.RpcMethod(
|
||||||
|
fullMethodName = SERVICE_NAME + '/' + "StreamEvents",
|
||||||
|
requestType = mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest.class,
|
||||||
|
responseType = mxaccess_gateway.v1.MxaccessGateway.MxEvent.class,
|
||||||
|
methodType = io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING)
|
||||||
|
public static io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxEvent> getStreamEventsMethod() {
|
||||||
|
io.grpc.MethodDescriptor<mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest, mxaccess_gateway.v1.MxaccessGateway.MxEvent> getStreamEventsMethod;
|
||||||
|
if ((getStreamEventsMethod = MxAccessGatewayGrpc.getStreamEventsMethod) == null) {
|
||||||
|
synchronized (MxAccessGatewayGrpc.class) {
|
||||||
|
if ((getStreamEventsMethod = MxAccessGatewayGrpc.getStreamEventsMethod) == null) {
|
||||||
|
MxAccessGatewayGrpc.getStreamEventsMethod = getStreamEventsMethod =
|
||||||
|
io.grpc.MethodDescriptor.<mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest, mxaccess_gateway.v1.MxaccessGateway.MxEvent>newBuilder()
|
||||||
|
.setType(io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING)
|
||||||
|
.setFullMethodName(generateFullMethodName(SERVICE_NAME, "StreamEvents"))
|
||||||
|
.setSampledToLocalTracing(true)
|
||||||
|
.setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest.getDefaultInstance()))
|
||||||
|
.setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxEvent.getDefaultInstance()))
|
||||||
|
.setSchemaDescriptor(new MxAccessGatewayMethodDescriptorSupplier("StreamEvents"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getStreamEventsMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new async stub that supports all call types for the service
|
||||||
|
*/
|
||||||
|
public static MxAccessGatewayStub newStub(io.grpc.Channel channel) {
|
||||||
|
io.grpc.stub.AbstractStub.StubFactory<MxAccessGatewayStub> factory =
|
||||||
|
new io.grpc.stub.AbstractStub.StubFactory<MxAccessGatewayStub>() {
|
||||||
|
@java.lang.Override
|
||||||
|
public MxAccessGatewayStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
return new MxAccessGatewayStub(channel, callOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return MxAccessGatewayStub.newStub(factory, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new blocking-style stub that supports all types of calls on the service
|
||||||
|
*/
|
||||||
|
public static MxAccessGatewayBlockingV2Stub newBlockingV2Stub(
|
||||||
|
io.grpc.Channel channel) {
|
||||||
|
io.grpc.stub.AbstractStub.StubFactory<MxAccessGatewayBlockingV2Stub> factory =
|
||||||
|
new io.grpc.stub.AbstractStub.StubFactory<MxAccessGatewayBlockingV2Stub>() {
|
||||||
|
@java.lang.Override
|
||||||
|
public MxAccessGatewayBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
return new MxAccessGatewayBlockingV2Stub(channel, callOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return MxAccessGatewayBlockingV2Stub.newStub(factory, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new blocking-style stub that supports unary and streaming output calls on the service
|
||||||
|
*/
|
||||||
|
public static MxAccessGatewayBlockingStub newBlockingStub(
|
||||||
|
io.grpc.Channel channel) {
|
||||||
|
io.grpc.stub.AbstractStub.StubFactory<MxAccessGatewayBlockingStub> factory =
|
||||||
|
new io.grpc.stub.AbstractStub.StubFactory<MxAccessGatewayBlockingStub>() {
|
||||||
|
@java.lang.Override
|
||||||
|
public MxAccessGatewayBlockingStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
return new MxAccessGatewayBlockingStub(channel, callOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return MxAccessGatewayBlockingStub.newStub(factory, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ListenableFuture-style stub that supports unary calls on the service
|
||||||
|
*/
|
||||||
|
public static MxAccessGatewayFutureStub newFutureStub(
|
||||||
|
io.grpc.Channel channel) {
|
||||||
|
io.grpc.stub.AbstractStub.StubFactory<MxAccessGatewayFutureStub> factory =
|
||||||
|
new io.grpc.stub.AbstractStub.StubFactory<MxAccessGatewayFutureStub>() {
|
||||||
|
@java.lang.Override
|
||||||
|
public MxAccessGatewayFutureStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
return new MxAccessGatewayFutureStub(channel, callOptions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return MxAccessGatewayFutureStub.newStub(factory, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* Public client API for MXAccess sessions hosted by the gateway.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public interface AsyncService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
default void openSession(mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest request,
|
||||||
|
io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply> responseObserver) {
|
||||||
|
io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getOpenSessionMethod(), responseObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
default void closeSession(mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest request,
|
||||||
|
io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply> responseObserver) {
|
||||||
|
io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getCloseSessionMethod(), responseObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
default void invoke(mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest request,
|
||||||
|
io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.MxCommandReply> responseObserver) {
|
||||||
|
io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getInvokeMethod(), responseObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
default void streamEvents(mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest request,
|
||||||
|
io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.MxEvent> responseObserver) {
|
||||||
|
io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getStreamEventsMethod(), responseObserver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for the server implementation of the service MxAccessGateway.
|
||||||
|
* <pre>
|
||||||
|
* Public client API for MXAccess sessions hosted by the gateway.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static abstract class MxAccessGatewayImplBase
|
||||||
|
implements io.grpc.BindableService, AsyncService {
|
||||||
|
|
||||||
|
@java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
|
||||||
|
return MxAccessGatewayGrpc.bindService(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stub to allow clients to do asynchronous rpc calls to service MxAccessGateway.
|
||||||
|
* <pre>
|
||||||
|
* Public client API for MXAccess sessions hosted by the gateway.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static final class MxAccessGatewayStub
|
||||||
|
extends io.grpc.stub.AbstractAsyncStub<MxAccessGatewayStub> {
|
||||||
|
private MxAccessGatewayStub(
|
||||||
|
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
super(channel, callOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
protected MxAccessGatewayStub build(
|
||||||
|
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
return new MxAccessGatewayStub(channel, callOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public void openSession(mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest request,
|
||||||
|
io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply> responseObserver) {
|
||||||
|
io.grpc.stub.ClientCalls.asyncUnaryCall(
|
||||||
|
getChannel().newCall(getOpenSessionMethod(), getCallOptions()), request, responseObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public void closeSession(mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest request,
|
||||||
|
io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply> responseObserver) {
|
||||||
|
io.grpc.stub.ClientCalls.asyncUnaryCall(
|
||||||
|
getChannel().newCall(getCloseSessionMethod(), getCallOptions()), request, responseObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public void invoke(mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest request,
|
||||||
|
io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.MxCommandReply> responseObserver) {
|
||||||
|
io.grpc.stub.ClientCalls.asyncUnaryCall(
|
||||||
|
getChannel().newCall(getInvokeMethod(), getCallOptions()), request, responseObserver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public void streamEvents(mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest request,
|
||||||
|
io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.MxEvent> responseObserver) {
|
||||||
|
io.grpc.stub.ClientCalls.asyncServerStreamingCall(
|
||||||
|
getChannel().newCall(getStreamEventsMethod(), getCallOptions()), request, responseObserver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stub to allow clients to do synchronous rpc calls to service MxAccessGateway.
|
||||||
|
* <pre>
|
||||||
|
* Public client API for MXAccess sessions hosted by the gateway.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static final class MxAccessGatewayBlockingV2Stub
|
||||||
|
extends io.grpc.stub.AbstractBlockingStub<MxAccessGatewayBlockingV2Stub> {
|
||||||
|
private MxAccessGatewayBlockingV2Stub(
|
||||||
|
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
super(channel, callOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
protected MxAccessGatewayBlockingV2Stub build(
|
||||||
|
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
return new MxAccessGatewayBlockingV2Stub(channel, callOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply openSession(mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest request) throws io.grpc.StatusException {
|
||||||
|
return io.grpc.stub.ClientCalls.blockingV2UnaryCall(
|
||||||
|
getChannel(), getOpenSessionMethod(), getCallOptions(), request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply closeSession(mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest request) throws io.grpc.StatusException {
|
||||||
|
return io.grpc.stub.ClientCalls.blockingV2UnaryCall(
|
||||||
|
getChannel(), getCloseSessionMethod(), getCallOptions(), request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public mxaccess_gateway.v1.MxaccessGateway.MxCommandReply invoke(mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest request) throws io.grpc.StatusException {
|
||||||
|
return io.grpc.stub.ClientCalls.blockingV2UnaryCall(
|
||||||
|
getChannel(), getInvokeMethod(), getCallOptions(), request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918")
|
||||||
|
public io.grpc.stub.BlockingClientCall<?, mxaccess_gateway.v1.MxaccessGateway.MxEvent>
|
||||||
|
streamEvents(mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest request) {
|
||||||
|
return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall(
|
||||||
|
getChannel(), getStreamEventsMethod(), getCallOptions(), request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stub to allow clients to do limited synchronous rpc calls to service MxAccessGateway.
|
||||||
|
* <pre>
|
||||||
|
* Public client API for MXAccess sessions hosted by the gateway.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static final class MxAccessGatewayBlockingStub
|
||||||
|
extends io.grpc.stub.AbstractBlockingStub<MxAccessGatewayBlockingStub> {
|
||||||
|
private MxAccessGatewayBlockingStub(
|
||||||
|
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
super(channel, callOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
protected MxAccessGatewayBlockingStub build(
|
||||||
|
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
return new MxAccessGatewayBlockingStub(channel, callOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply openSession(mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest request) {
|
||||||
|
return io.grpc.stub.ClientCalls.blockingUnaryCall(
|
||||||
|
getChannel(), getOpenSessionMethod(), getCallOptions(), request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply closeSession(mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest request) {
|
||||||
|
return io.grpc.stub.ClientCalls.blockingUnaryCall(
|
||||||
|
getChannel(), getCloseSessionMethod(), getCallOptions(), request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public mxaccess_gateway.v1.MxaccessGateway.MxCommandReply invoke(mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest request) {
|
||||||
|
return io.grpc.stub.ClientCalls.blockingUnaryCall(
|
||||||
|
getChannel(), getInvokeMethod(), getCallOptions(), request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public java.util.Iterator<mxaccess_gateway.v1.MxaccessGateway.MxEvent> streamEvents(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest request) {
|
||||||
|
return io.grpc.stub.ClientCalls.blockingServerStreamingCall(
|
||||||
|
getChannel(), getStreamEventsMethod(), getCallOptions(), request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stub to allow clients to do ListenableFuture-style rpc calls to service MxAccessGateway.
|
||||||
|
* <pre>
|
||||||
|
* Public client API for MXAccess sessions hosted by the gateway.
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static final class MxAccessGatewayFutureStub
|
||||||
|
extends io.grpc.stub.AbstractFutureStub<MxAccessGatewayFutureStub> {
|
||||||
|
private MxAccessGatewayFutureStub(
|
||||||
|
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
super(channel, callOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
protected MxAccessGatewayFutureStub build(
|
||||||
|
io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
|
||||||
|
return new MxAccessGatewayFutureStub(channel, callOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public com.google.common.util.concurrent.ListenableFuture<mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply> openSession(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest request) {
|
||||||
|
return io.grpc.stub.ClientCalls.futureUnaryCall(
|
||||||
|
getChannel().newCall(getOpenSessionMethod(), getCallOptions()), request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public com.google.common.util.concurrent.ListenableFuture<mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply> closeSession(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest request) {
|
||||||
|
return io.grpc.stub.ClientCalls.futureUnaryCall(
|
||||||
|
getChannel().newCall(getCloseSessionMethod(), getCallOptions()), request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public com.google.common.util.concurrent.ListenableFuture<mxaccess_gateway.v1.MxaccessGateway.MxCommandReply> invoke(
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest request) {
|
||||||
|
return io.grpc.stub.ClientCalls.futureUnaryCall(
|
||||||
|
getChannel().newCall(getInvokeMethod(), getCallOptions()), request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int METHODID_OPEN_SESSION = 0;
|
||||||
|
private static final int METHODID_CLOSE_SESSION = 1;
|
||||||
|
private static final int METHODID_INVOKE = 2;
|
||||||
|
private static final int METHODID_STREAM_EVENTS = 3;
|
||||||
|
|
||||||
|
private static final class MethodHandlers<Req, Resp> implements
|
||||||
|
io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
|
||||||
|
io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
|
||||||
|
io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
|
||||||
|
io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
|
||||||
|
private final AsyncService serviceImpl;
|
||||||
|
private final int methodId;
|
||||||
|
|
||||||
|
MethodHandlers(AsyncService serviceImpl, int methodId) {
|
||||||
|
this.serviceImpl = serviceImpl;
|
||||||
|
this.methodId = methodId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
@java.lang.SuppressWarnings("unchecked")
|
||||||
|
public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
|
||||||
|
switch (methodId) {
|
||||||
|
case METHODID_OPEN_SESSION:
|
||||||
|
serviceImpl.openSession((mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest) request,
|
||||||
|
(io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply>) responseObserver);
|
||||||
|
break;
|
||||||
|
case METHODID_CLOSE_SESSION:
|
||||||
|
serviceImpl.closeSession((mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest) request,
|
||||||
|
(io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply>) responseObserver);
|
||||||
|
break;
|
||||||
|
case METHODID_INVOKE:
|
||||||
|
serviceImpl.invoke((mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest) request,
|
||||||
|
(io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.MxCommandReply>) responseObserver);
|
||||||
|
break;
|
||||||
|
case METHODID_STREAM_EVENTS:
|
||||||
|
serviceImpl.streamEvents((mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest) request,
|
||||||
|
(io.grpc.stub.StreamObserver<mxaccess_gateway.v1.MxaccessGateway.MxEvent>) responseObserver);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
@java.lang.SuppressWarnings("unchecked")
|
||||||
|
public io.grpc.stub.StreamObserver<Req> invoke(
|
||||||
|
io.grpc.stub.StreamObserver<Resp> responseObserver) {
|
||||||
|
switch (methodId) {
|
||||||
|
default:
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) {
|
||||||
|
return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
|
||||||
|
.addMethod(
|
||||||
|
getOpenSessionMethod(),
|
||||||
|
io.grpc.stub.ServerCalls.asyncUnaryCall(
|
||||||
|
new MethodHandlers<
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply>(
|
||||||
|
service, METHODID_OPEN_SESSION)))
|
||||||
|
.addMethod(
|
||||||
|
getCloseSessionMethod(),
|
||||||
|
io.grpc.stub.ServerCalls.asyncUnaryCall(
|
||||||
|
new MethodHandlers<
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply>(
|
||||||
|
service, METHODID_CLOSE_SESSION)))
|
||||||
|
.addMethod(
|
||||||
|
getInvokeMethod(),
|
||||||
|
io.grpc.stub.ServerCalls.asyncUnaryCall(
|
||||||
|
new MethodHandlers<
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxCommandRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxCommandReply>(
|
||||||
|
service, METHODID_INVOKE)))
|
||||||
|
.addMethod(
|
||||||
|
getStreamEventsMethod(),
|
||||||
|
io.grpc.stub.ServerCalls.asyncServerStreamingCall(
|
||||||
|
new MethodHandlers<
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest,
|
||||||
|
mxaccess_gateway.v1.MxaccessGateway.MxEvent>(
|
||||||
|
service, METHODID_STREAM_EVENTS)))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static abstract class MxAccessGatewayBaseDescriptorSupplier
|
||||||
|
implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier {
|
||||||
|
MxAccessGatewayBaseDescriptorSupplier() {}
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {
|
||||||
|
return mxaccess_gateway.v1.MxaccessGateway.getDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {
|
||||||
|
return getFileDescriptor().findServiceByName("MxAccessGateway");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class MxAccessGatewayFileDescriptorSupplier
|
||||||
|
extends MxAccessGatewayBaseDescriptorSupplier {
|
||||||
|
MxAccessGatewayFileDescriptorSupplier() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class MxAccessGatewayMethodDescriptorSupplier
|
||||||
|
extends MxAccessGatewayBaseDescriptorSupplier
|
||||||
|
implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {
|
||||||
|
private final java.lang.String methodName;
|
||||||
|
|
||||||
|
MxAccessGatewayMethodDescriptorSupplier(java.lang.String methodName) {
|
||||||
|
this.methodName = methodName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@java.lang.Override
|
||||||
|
public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {
|
||||||
|
return getServiceDescriptor().findMethodByName(methodName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static volatile io.grpc.ServiceDescriptor serviceDescriptor;
|
||||||
|
|
||||||
|
public static io.grpc.ServiceDescriptor getServiceDescriptor() {
|
||||||
|
io.grpc.ServiceDescriptor result = serviceDescriptor;
|
||||||
|
if (result == null) {
|
||||||
|
synchronized (MxAccessGatewayGrpc.class) {
|
||||||
|
result = serviceDescriptor;
|
||||||
|
if (result == null) {
|
||||||
|
serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)
|
||||||
|
.setSchemaDescriptor(new MxAccessGatewayFileDescriptorSupplier())
|
||||||
|
.addMethod(getOpenSessionMethod())
|
||||||
|
.addMethod(getCloseSessionMethod())
|
||||||
|
.addMethod(getInvokeMethod())
|
||||||
|
.addMethod(getStreamEventsMethod())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,469 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"fixtureSet": "mxaccess-gateway-parity-fixture-matrix",
|
||||||
|
"contractName": "mxaccess-gateway",
|
||||||
|
"gatewayProtocolVersion": 1,
|
||||||
|
"workerProtocolVersion": 1,
|
||||||
|
"sourceCaptureRoot": "C:/Users/dohertj2/Desktop/mxaccess/captures",
|
||||||
|
"sourceDocs": [
|
||||||
|
"C:/Users/dohertj2/Desktop/mxaccess/docs/MXAccess-Public-API.md",
|
||||||
|
"C:/Users/dohertj2/Desktop/mxaccess/docs/Current-Sprint-State.md"
|
||||||
|
],
|
||||||
|
"comparisonFormat": {
|
||||||
|
"description": "Each parity run records the same command against direct MXAccess and the gateway-backed worker, then compares raw parity fields instead of client wrapper behavior.",
|
||||||
|
"directMxAccess": {
|
||||||
|
"requiredFields": [
|
||||||
|
"method",
|
||||||
|
"arguments",
|
||||||
|
"returnedValue",
|
||||||
|
"hresult",
|
||||||
|
"exceptionType",
|
||||||
|
"statuses",
|
||||||
|
"events"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gatewayResult": {
|
||||||
|
"requiredFields": [
|
||||||
|
"kind",
|
||||||
|
"protocolStatus",
|
||||||
|
"returnValue",
|
||||||
|
"hresult",
|
||||||
|
"statuses",
|
||||||
|
"diagnosticMessage",
|
||||||
|
"events"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"eventFields": [
|
||||||
|
"family",
|
||||||
|
"serverHandle",
|
||||||
|
"itemHandle",
|
||||||
|
"value",
|
||||||
|
"quality",
|
||||||
|
"sourceTimestamp",
|
||||||
|
"statuses",
|
||||||
|
"workerSequence",
|
||||||
|
"workerTimestamp",
|
||||||
|
"gatewayReceiveTimestamp",
|
||||||
|
"hresult",
|
||||||
|
"rawStatus"
|
||||||
|
],
|
||||||
|
"comparisonKeys": [
|
||||||
|
"hresult",
|
||||||
|
"exceptionType",
|
||||||
|
"returnedValue",
|
||||||
|
"statusArrayShape",
|
||||||
|
"statusRawFields",
|
||||||
|
"eventFamilyOrder",
|
||||||
|
"eventPayloadShape",
|
||||||
|
"valueProjection",
|
||||||
|
"rawFallbackMetadata"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"methodFixtures": [
|
||||||
|
{
|
||||||
|
"id": "method.register.basic",
|
||||||
|
"method": "Register",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_REGISTER",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/001-register/harness.log",
|
||||||
|
"captures/047-frida-com-proxy-register/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve returned server handle in returnValue and RegisterReply",
|
||||||
|
"preserve success HRESULT as 0",
|
||||||
|
"do not emit MXAccess events for register"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.unregister.basic",
|
||||||
|
"method": "Unregister",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_UNREGISTER",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/001-register/harness.log",
|
||||||
|
"captures/109-native-post-remove-errors/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve void return shape with explicit protocol success",
|
||||||
|
"preserve HRESULT or COM exception details for invalid server handle",
|
||||||
|
"close registered handle only after MXAccess succeeds"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.add-item.scalar",
|
||||||
|
"method": "AddItem",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_ADD_ITEM",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/002-add-remove-scalar/harness.log",
|
||||||
|
"captures/006-add-invalid/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve returned item handle in returnValue and AddItemReply",
|
||||||
|
"preserve invalid item reference HRESULT/status details",
|
||||||
|
"do not prevalidate item definition in the gateway"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.add-item2.context",
|
||||||
|
"method": "AddItem2",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_ADD_ITEM2",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/mxaccess-additem2-testint-context.log",
|
||||||
|
"captures/121-frida-buffered-history-testhistoryvalue-context/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"pass item_definition and item_context exactly as supplied",
|
||||||
|
"preserve returned item handle in returnValue and AddItem2Reply",
|
||||||
|
"compare context-bearing reference resolution against direct MXAccess"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.remove-item.basic",
|
||||||
|
"method": "RemoveItem",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_REMOVE_ITEM",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/002-add-remove-scalar/harness.log",
|
||||||
|
"captures/109-native-post-remove-errors/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve void return shape with explicit protocol success",
|
||||||
|
"preserve post-remove and invalid-handle HRESULT/status behavior",
|
||||||
|
"remove diagnostic handle state only after MXAccess succeeds"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.advise.supervisory-data-change",
|
||||||
|
"method": "Advise",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_ADVISE",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/003-subscribe-scalars/harness.log",
|
||||||
|
"captures/058-frida-subscribe-testint/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve successful command reply shape",
|
||||||
|
"forward OnDataChange with value, quality, timestamp, and status array",
|
||||||
|
"preserve per-worker event order"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.unadvise.basic",
|
||||||
|
"method": "UnAdvise",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_UN_ADVISE",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/058-frida-subscribe-testint/harness.log",
|
||||||
|
"captures/007-subscribe-invalid/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve void return shape with explicit protocol success",
|
||||||
|
"preserve invalid item handle HRESULT/status behavior",
|
||||||
|
"do not distinguish plain and supervisory cleanup beyond MXAccess behavior"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.advise-supervisory.basic",
|
||||||
|
"method": "AdviseSupervisory",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_ADVISE_SUPERVISORY",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/058-frida-subscribe-testint/harness.log",
|
||||||
|
"captures/105-frida-advise-shortdesc-prebound-fixed/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"keep AdviseSupervisory distinct from plain Advise in command kind",
|
||||||
|
"forward native OnDataChange only when MXAccess emits it",
|
||||||
|
"compare supervisory item status arrays without normalization"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.add-buffered-item.context",
|
||||||
|
"method": "AddBufferedItem",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_ADD_BUFFERED_ITEM",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/079-frida-add-buffered-advise-testint/harness.log",
|
||||||
|
"captures/120-frida-buffered-history-testhistoryvalue/harness.log",
|
||||||
|
"captures/121-frida-buffered-history-testhistoryvalue-context/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"pass item_definition and item_context exactly as supplied",
|
||||||
|
"preserve returned buffered item handle in returnValue and AddBufferedItemReply",
|
||||||
|
"keep buffered registration distinct from normal AddItem2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.set-buffered-update-interval.basic",
|
||||||
|
"method": "SetBufferedUpdateInterval",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_SET_BUFFERED_UPDATE_INTERVAL",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/mxaccess-set-buffered-interval-1000.log",
|
||||||
|
"captures/079-frida-add-buffered-advise-testint/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve requested update interval without clamping in the gateway",
|
||||||
|
"preserve void return shape with explicit protocol success",
|
||||||
|
"compare buffered event cadence only in opt-in live runs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.suspend.scan-state",
|
||||||
|
"method": "Suspend",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_SUSPEND",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/077-frida-suspend-advised-scanstate/harness.log",
|
||||||
|
"captures/118-frida-suspend-advised-scanstate-long/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve out MxStatus in SuspendReply and repeated statuses",
|
||||||
|
"preserve HRESULT separately from status detail",
|
||||||
|
"do not synthesize OperationComplete if native MXAccess does not raise it"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.activate.scan-state",
|
||||||
|
"method": "Activate",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_ACTIVATE",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/078-frida-activate-advised-scanstate/harness.log",
|
||||||
|
"captures/119-frida-activate-advised-scanstate-long/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve out MxStatus in ActivateReply and repeated statuses",
|
||||||
|
"preserve HRESULT separately from status detail",
|
||||||
|
"do not synthesize OperationComplete if native MXAccess does not raise it"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.write.value-status-matrix",
|
||||||
|
"method": "Write",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_WRITE",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/023-frida-write-test-int-sequence-109-111/harness.log",
|
||||||
|
"captures/024-frida-write-test-bool-sequence/harness.log",
|
||||||
|
"captures/089-frida-write-testint-wrong-type/harness.log",
|
||||||
|
"captures/090-frida-write-invalid-reference/harness.log",
|
||||||
|
"captures/107-native-write-testint-current/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve scalar and array value projections plus raw fallback metadata",
|
||||||
|
"preserve wrong-type and invalid-reference HRESULT/status arrays",
|
||||||
|
"forward OnWriteComplete only when native MXAccess emits it"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.write2.timestamped",
|
||||||
|
"method": "Write2",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_WRITE2",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/042-frida-write2-test-int-timestamp/harness.log",
|
||||||
|
"captures/066-frida-write2-test-bool-timestamp/harness.log",
|
||||||
|
"captures/075-frida-write2-test-datetime-array-timestamp/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve timestamp_value as an MXAccess VARIANT projection",
|
||||||
|
"preserve write value shape and HRESULT/status arrays",
|
||||||
|
"compare timestamped write completion events against direct MXAccess"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.write-secured.rejection-gap",
|
||||||
|
"method": "WriteSecured",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_WRITE_SECURED",
|
||||||
|
"status": "documented_gap",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/036-frida-write-secured-test-int/harness.log",
|
||||||
|
"captures/111-frida-write-secured-auth-protectedvalue/harness.log",
|
||||||
|
"captures/112-frida-write-secured-auth-verified-protectedvalue1/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve observed 0x80004021 rejection before a value-bearing NMX body",
|
||||||
|
"preserve current_user_id and verifier_user_id only as command inputs, not logs",
|
||||||
|
"upgrade this gap to planned_fixture when a successful direct WriteSecured path is observed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.write-secured2.authenticated",
|
||||||
|
"method": "WriteSecured2",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_WRITE_SECURED2",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/113-frida-write-secured2-auth-protectedvalue/harness.log",
|
||||||
|
"captures/116-frida-write-secured2-auth-verified-protectedvalue1/harness.log",
|
||||||
|
"captures/117-frida-write-secured2-auth-testint/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve authenticated timestamped secured write body shape",
|
||||||
|
"preserve HRESULT/status arrays without logging credential-bearing values",
|
||||||
|
"do not synthesize OnWriteComplete when direct MXAccess does not emit it"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.authenticate-user.basic",
|
||||||
|
"method": "AuthenticateUser",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_AUTHENTICATE_USER",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/087-frida-authenticate-administrator-empty/harness.log",
|
||||||
|
"captures/088-frida-authenticate-invalid-empty/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve returned user id in returnValue and AuthenticateUserReply",
|
||||||
|
"preserve invalid credential HRESULT/status behavior",
|
||||||
|
"redact verify_user_password from logs and diagnostics"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "method.archestra-user-to-id.basic",
|
||||||
|
"method": "ArchestrAUserToId",
|
||||||
|
"commandKind": "MX_COMMAND_KIND_ARCHESTRA_USER_TO_ID",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/mxaccess-user-map-administrator.log",
|
||||||
|
"captures/mxaccess-user-map-invalid.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve returned user id in returnValue and ArchestrAUserToIdReply",
|
||||||
|
"preserve invalid user GUID HRESULT/status behavior",
|
||||||
|
"compare raw mapping behavior without normalizing unknown users"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"eventFixtures": [
|
||||||
|
{
|
||||||
|
"id": "event.on-data-change.scalar",
|
||||||
|
"family": "MX_EVENT_FAMILY_ON_DATA_CHANGE",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/003-subscribe-scalars/harness.log",
|
||||||
|
"captures/106-native-subscribe-testint-current/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve value, quality, timestamp, status array, and worker sequence"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "event.on-write-complete.status",
|
||||||
|
"family": "MX_EVENT_FAMILY_ON_WRITE_COMPLETE",
|
||||||
|
"status": "planned_fixture",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/008-write-test-int-same-value/harness.log",
|
||||||
|
"captures/107-native-write-testint-current/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve write-complete status array and optional HRESULT"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "event.operation-complete.native-trigger-gap",
|
||||||
|
"family": "MX_EVENT_FAMILY_OPERATION_COMPLETE",
|
||||||
|
"status": "documented_gap",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/077-frida-suspend-advised-scanstate/harness.log",
|
||||||
|
"captures/118-frida-suspend-advised-scanstate-long/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"do not synthesize OperationComplete from Write or OnWriteComplete",
|
||||||
|
"upgrade this gap when a public MXAccess trigger emits event family 3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "event.on-buffered-data-change.batch-gap",
|
||||||
|
"family": "MX_EVENT_FAMILY_ON_BUFFERED_DATA_CHANGE",
|
||||||
|
"status": "documented_gap",
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/120-frida-buffered-history-testhistoryvalue/harness.log",
|
||||||
|
"captures/122-frida-buffered-history-testhistoryvalue-plainadvise/harness.log"
|
||||||
|
],
|
||||||
|
"assertions": [
|
||||||
|
"preserve raw buffered metadata until a public multi-sample event payload is observed",
|
||||||
|
"upgrade this gap when OnBufferedDataChange batches are captured from MXAccess"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scenarioGroups": [
|
||||||
|
{
|
||||||
|
"id": "invalid_handles",
|
||||||
|
"description": "Invalid server, item, post-remove, and invalid-reference cases keep MXAccess-owned HRESULT and status behavior.",
|
||||||
|
"fixtureIds": [
|
||||||
|
"method.add-item.scalar",
|
||||||
|
"method.remove-item.basic",
|
||||||
|
"method.unadvise.basic",
|
||||||
|
"method.write.value-status-matrix",
|
||||||
|
"method.unregister.basic"
|
||||||
|
],
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/006-add-invalid/harness.log",
|
||||||
|
"captures/007-subscribe-invalid/harness.log",
|
||||||
|
"captures/109-native-post-remove-errors/harness.log",
|
||||||
|
"captures/110-native-invalid-handle-errors/harness.log"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "write_statuses",
|
||||||
|
"description": "Write success, wrong type, invalid reference, scalar arrays, and completion-status cases compare HRESULT, status array, value projection, and event shape.",
|
||||||
|
"fixtureIds": [
|
||||||
|
"method.write.value-status-matrix",
|
||||||
|
"method.write2.timestamped",
|
||||||
|
"event.on-write-complete.status"
|
||||||
|
],
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/089-frida-write-testint-wrong-type/harness.log",
|
||||||
|
"captures/090-frida-write-invalid-reference/harness.log",
|
||||||
|
"captures/091-frida-write-testint-double-type/harness.log",
|
||||||
|
"captures/097-frida-write-bool-array-pattern/harness.log",
|
||||||
|
"captures/107-native-write-testint-current/harness.log"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "secured_writes",
|
||||||
|
"description": "Secured writes include observed WriteSecured rejection and authenticated WriteSecured2 success paths without logging credential-bearing values.",
|
||||||
|
"fixtureIds": [
|
||||||
|
"method.write-secured.rejection-gap",
|
||||||
|
"method.write-secured2.authenticated",
|
||||||
|
"method.authenticate-user.basic"
|
||||||
|
],
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/036-frida-write-secured-test-int/harness.log",
|
||||||
|
"captures/111-frida-write-secured-auth-protectedvalue/harness.log",
|
||||||
|
"captures/113-frida-write-secured2-auth-protectedvalue/harness.log",
|
||||||
|
"captures/117-frida-write-secured2-auth-testint/harness.log"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "add_item_context",
|
||||||
|
"description": "Context-bearing item registration compares AddItem2 and buffered AddBufferedItem argument preservation.",
|
||||||
|
"fixtureIds": [
|
||||||
|
"method.add-item2.context",
|
||||||
|
"method.add-buffered-item.context"
|
||||||
|
],
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/mxaccess-additem2-testint-context.log",
|
||||||
|
"captures/121-frida-buffered-history-testhistoryvalue-context/harness.log"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "buffered_registration",
|
||||||
|
"description": "Buffered registration and interval setup are tracked separately from normal advice until a public buffered data-change batch is captured.",
|
||||||
|
"fixtureIds": [
|
||||||
|
"method.add-buffered-item.context",
|
||||||
|
"method.set-buffered-update-interval.basic",
|
||||||
|
"event.on-buffered-data-change.batch-gap"
|
||||||
|
],
|
||||||
|
"captureReferences": [
|
||||||
|
"captures/079-frida-add-buffered-advise-testint/harness.log",
|
||||||
|
"captures/120-frida-buffered-history-testhistoryvalue/harness.log",
|
||||||
|
"captures/122-frida-buffered-history-testhistoryvalue-plainadvise/harness.log"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -76,6 +76,13 @@ stdout/stderr lines emitted during the run.
|
|||||||
|
|
||||||
## Focused Commands
|
## Focused Commands
|
||||||
|
|
||||||
|
Run the parity fixture matrix tests after changing the integration parity
|
||||||
|
scenario list:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test src/MxGateway.Tests/MxGateway.Tests.csproj --filter FullyQualifiedName~ParityFixtureMatrixTests
|
||||||
|
```
|
||||||
|
|
||||||
Run the fake worker tests after changing gateway worker IPC, session startup, or
|
Run the fake worker tests after changing gateway worker IPC, session startup, or
|
||||||
event streaming behavior:
|
event streaming behavior:
|
||||||
|
|
||||||
@@ -95,6 +102,7 @@ dotnet test src/MxGateway.Tests/MxGateway.Tests.csproj
|
|||||||
|
|
||||||
## Related Documentation
|
## Related Documentation
|
||||||
|
|
||||||
|
- [Parity Fixture Matrix](./ParityFixtureMatrix.md)
|
||||||
- [Gateway Process Design](./gateway-process-design.md)
|
- [Gateway Process Design](./gateway-process-design.md)
|
||||||
- [Worker Frame Protocol](./WorkerFrameProtocol.md)
|
- [Worker Frame Protocol](./WorkerFrameProtocol.md)
|
||||||
- [MXAccess Worker Instance Detailed Design](./mxaccess-worker-instance-design.md)
|
- [MXAccess Worker Instance Detailed Design](./mxaccess-worker-instance-design.md)
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
# Parity Fixture Matrix
|
||||||
|
|
||||||
|
The parity fixture matrix defines the live-test scenarios used to compare
|
||||||
|
direct MXAccess behavior with the gateway-backed worker. It is a planning and
|
||||||
|
validation fixture, not a source of synthetic MXAccess behavior.
|
||||||
|
|
||||||
|
The matrix lives in
|
||||||
|
`clients/proto/fixtures/parity/parity-fixture-matrix.json`. It references the
|
||||||
|
local MXAccess capture set under
|
||||||
|
`C:/Users/dohertj2/Desktop/mxaccess/captures` and keeps capture paths relative
|
||||||
|
to that root so the repository does not copy raw capture artifacts.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
The matrix covers every public `LMXProxyServerClass` method represented by the
|
||||||
|
gateway contract:
|
||||||
|
|
||||||
|
- `Register`
|
||||||
|
- `Unregister`
|
||||||
|
- `AddItem`
|
||||||
|
- `AddItem2`
|
||||||
|
- `RemoveItem`
|
||||||
|
- `Advise`
|
||||||
|
- `UnAdvise`
|
||||||
|
- `AdviseSupervisory`
|
||||||
|
- `AddBufferedItem`
|
||||||
|
- `SetBufferedUpdateInterval`
|
||||||
|
- `Suspend`
|
||||||
|
- `Activate`
|
||||||
|
- `Write`
|
||||||
|
- `Write2`
|
||||||
|
- `WriteSecured`
|
||||||
|
- `WriteSecured2`
|
||||||
|
- `AuthenticateUser`
|
||||||
|
- `ArchestrAUserToId`
|
||||||
|
|
||||||
|
Each entry is either a `planned_fixture` or a `documented_gap`.
|
||||||
|
`WriteSecured` remains a documented gap because the current captures show
|
||||||
|
`0x80004021` before MXAccess emits a value-bearing write body.
|
||||||
|
`OperationComplete` and public `OnBufferedDataChange` batches also remain
|
||||||
|
documented gaps because no capture in the current set proves those public event
|
||||||
|
payloads from native MXAccess.
|
||||||
|
|
||||||
|
## Required Scenario Groups
|
||||||
|
|
||||||
|
The matrix pins the high-risk parity scenarios from the integration milestone:
|
||||||
|
|
||||||
|
| Scenario | Purpose |
|
||||||
|
|----------|---------|
|
||||||
|
| `invalid_handles` | Preserves invalid server, item, post-remove, and invalid-reference HRESULT/status behavior. |
|
||||||
|
| `write_statuses` | Compares successful writes, wrong-type writes, invalid references, arrays, and write-complete status arrays. |
|
||||||
|
| `secured_writes` | Covers observed `WriteSecured` rejection and authenticated `WriteSecured2` paths without logging credential-bearing values. |
|
||||||
|
| `add_item_context` | Ensures `AddItem2` and buffered registration pass context strings exactly as supplied. |
|
||||||
|
| `buffered_registration` | Tracks buffered item registration and interval setup separately from normal advice. |
|
||||||
|
|
||||||
|
## Comparison Format
|
||||||
|
|
||||||
|
Each live parity fixture should record one direct MXAccess result and one
|
||||||
|
gateway result for the same operation.
|
||||||
|
|
||||||
|
Direct MXAccess records include:
|
||||||
|
|
||||||
|
- method name,
|
||||||
|
- arguments after redaction,
|
||||||
|
- returned value,
|
||||||
|
- HRESULT,
|
||||||
|
- exception type,
|
||||||
|
- `MXSTATUS_PROXY[]` values,
|
||||||
|
- native event records in observed order.
|
||||||
|
|
||||||
|
Gateway records include:
|
||||||
|
|
||||||
|
- `MxCommandKind`,
|
||||||
|
- `ProtocolStatus`,
|
||||||
|
- `MxCommandReply.ReturnValue`,
|
||||||
|
- `MxCommandReply.Hresult`,
|
||||||
|
- repeated `MxCommandReply.Statuses`,
|
||||||
|
- safe diagnostic message,
|
||||||
|
- streamed `MxEvent` records in worker-sequence order.
|
||||||
|
|
||||||
|
Compare HRESULT, exception type, returned value, status array shape, raw status
|
||||||
|
fields, event family order, event payload shape, value projection, and raw
|
||||||
|
fallback metadata. The gateway must not convert an MXAccess command failure
|
||||||
|
into a transport failure when the worker captured HRESULT or status details.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
Run the parity fixture matrix tests after changing the matrix:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test src/MxGateway.Tests/MxGateway.Tests.csproj --filter FullyQualifiedName~ParityFixtureMatrixTests
|
||||||
|
```
|
||||||
|
|
||||||
|
Live MXAccess execution remains opt-in. The matrix defines which scenarios to
|
||||||
|
run when the installed MXAccess COM component and provider state are available;
|
||||||
|
normal unit tests only validate the repository fixture shape.
|
||||||
|
|
||||||
|
## Related Documentation
|
||||||
|
|
||||||
|
- [Gateway Testing](./GatewayTesting.md)
|
||||||
|
- [MXAccess Worker Instance Detailed Design](./mxaccess-worker-instance-design.md)
|
||||||
|
- [Protobuf Contracts](./Contracts.md)
|
||||||
@@ -137,9 +137,17 @@ The Python scaffold provides a repo-local generation script:
|
|||||||
clients/python/generate-proto.ps1
|
clients/python/generate-proto.ps1
|
||||||
```
|
```
|
||||||
|
|
||||||
Java clients should use the Gradle protobuf plugin and write generated sources
|
Java clients use the Gradle protobuf plugin from `clients/java`. The
|
||||||
under `clients/java/src/main/generated`. The Java client scaffold owns the
|
`mxgateway-client` project reads the shared `.proto` files and writes generated
|
||||||
Gradle plugin versions and source-set wiring.
|
Java protobuf and gRPC sources under `clients/java/src/main/generated`, matching
|
||||||
|
the manifest output path. Handwritten client and CLI code stays in the
|
||||||
|
`mxgateway-client` and `mxgateway-cli` project source trees.
|
||||||
|
|
||||||
|
Run the Java workspace checks from `clients/java`:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
gradle test
|
||||||
|
```
|
||||||
|
|
||||||
## Golden Fixtures
|
## Golden Fixtures
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ Recommended Gradle multi-project layout:
|
|||||||
clients/java/
|
clients/java/
|
||||||
settings.gradle
|
settings.gradle
|
||||||
build.gradle
|
build.gradle
|
||||||
|
src/main/generated/
|
||||||
mxgateway-client/
|
mxgateway-client/
|
||||||
build.gradle
|
build.gradle
|
||||||
src/main/java/com/dohertylan/mxgateway/client/
|
src/main/java/com/dohertylan/mxgateway/client/
|
||||||
@@ -31,6 +32,7 @@ Alternative Maven layout is acceptable if the repo standardizes on Maven.
|
|||||||
Target Java:
|
Target Java:
|
||||||
|
|
||||||
- Java 21 recommended.
|
- Java 21 recommended.
|
||||||
|
- The Gradle scaffold uses the Java 21 toolchain for compilation and tests.
|
||||||
|
|
||||||
Expected dependencies:
|
Expected dependencies:
|
||||||
|
|
||||||
@@ -189,3 +191,16 @@ Publish library and CLI separately:
|
|||||||
|
|
||||||
Generated protobuf code should be produced during the build from shared proto
|
Generated protobuf code should be produced during the build from shared proto
|
||||||
files and should not be hand-edited.
|
files and should not be hand-edited.
|
||||||
|
|
||||||
|
## Current Build
|
||||||
|
|
||||||
|
Run the Java scaffold checks from `clients/java`:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
gradle test
|
||||||
|
```
|
||||||
|
|
||||||
|
The `mxgateway-client` project generates the gateway and worker protobuf/gRPC
|
||||||
|
bindings into `src/main/generated`, compiles the generated contracts, and runs
|
||||||
|
JUnit 5 tests. The `mxgateway-cli` project builds a Picocli-based `mxgw-java`
|
||||||
|
entry point for later command implementation.
|
||||||
|
|||||||
@@ -0,0 +1,293 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using MxGateway.Contracts;
|
||||||
|
|
||||||
|
namespace MxGateway.Tests.Contracts;
|
||||||
|
|
||||||
|
public sealed class ParityFixtureMatrixTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Matrix_DeclaresCurrentProtocolVersionsAndComparisonFields()
|
||||||
|
{
|
||||||
|
using JsonDocument matrix = LoadParityMatrix();
|
||||||
|
JsonElement root = matrix.RootElement;
|
||||||
|
|
||||||
|
Assert.Equal(1, root.GetProperty("schemaVersion").GetInt32());
|
||||||
|
Assert.Equal("mxaccess-gateway-parity-fixture-matrix", root.GetProperty("fixtureSet").GetString());
|
||||||
|
Assert.Equal(GatewayContractInfo.GatewayProtocolVersion, root.GetProperty("gatewayProtocolVersion").GetUInt32());
|
||||||
|
Assert.Equal(GatewayContractInfo.WorkerProtocolVersion, root.GetProperty("workerProtocolVersion").GetUInt32());
|
||||||
|
|
||||||
|
JsonElement comparisonFormat = root.GetProperty("comparisonFormat");
|
||||||
|
AssertRequiredFields(
|
||||||
|
comparisonFormat.GetProperty("directMxAccess").GetProperty("requiredFields"),
|
||||||
|
"method",
|
||||||
|
"arguments",
|
||||||
|
"returnedValue",
|
||||||
|
"hresult",
|
||||||
|
"statuses",
|
||||||
|
"events");
|
||||||
|
AssertRequiredFields(
|
||||||
|
comparisonFormat.GetProperty("gatewayResult").GetProperty("requiredFields"),
|
||||||
|
"kind",
|
||||||
|
"protocolStatus",
|
||||||
|
"returnValue",
|
||||||
|
"hresult",
|
||||||
|
"statuses",
|
||||||
|
"events");
|
||||||
|
AssertRequiredFields(
|
||||||
|
comparisonFormat.GetProperty("eventFields"),
|
||||||
|
"family",
|
||||||
|
"value",
|
||||||
|
"quality",
|
||||||
|
"sourceTimestamp",
|
||||||
|
"statuses",
|
||||||
|
"workerSequence");
|
||||||
|
AssertRequiredFields(
|
||||||
|
comparisonFormat.GetProperty("comparisonKeys"),
|
||||||
|
"hresult",
|
||||||
|
"statusArrayShape",
|
||||||
|
"statusRawFields",
|
||||||
|
"eventFamilyOrder",
|
||||||
|
"eventPayloadShape",
|
||||||
|
"valueProjection",
|
||||||
|
"rawFallbackMetadata");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Matrix_CoversEveryPublicMxAccessMethod()
|
||||||
|
{
|
||||||
|
using JsonDocument matrix = LoadParityMatrix();
|
||||||
|
JsonElement methodFixtures = matrix.RootElement.GetProperty("methodFixtures");
|
||||||
|
|
||||||
|
Dictionary<string, JsonElement> fixturesByMethod = [];
|
||||||
|
HashSet<string> ids = new(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
foreach (JsonElement fixture in methodFixtures.EnumerateArray())
|
||||||
|
{
|
||||||
|
string id = fixture.GetProperty("id").GetString()!;
|
||||||
|
string method = fixture.GetProperty("method").GetString()!;
|
||||||
|
string commandKind = fixture.GetProperty("commandKind").GetString()!;
|
||||||
|
string status = fixture.GetProperty("status").GetString()!;
|
||||||
|
|
||||||
|
Assert.True(ids.Add(id), $"Duplicate parity fixture id '{id}'.");
|
||||||
|
Assert.True(fixturesByMethod.TryAdd(method, fixture), $"Duplicate parity method '{method}'.");
|
||||||
|
Assert.StartsWith("MX_COMMAND_KIND_", commandKind, StringComparison.Ordinal);
|
||||||
|
Assert.Contains(status, KnownFixtureStatuses);
|
||||||
|
Assert.NotEmpty(fixture.GetProperty("assertions").EnumerateArray());
|
||||||
|
AssertCaptureReferencesAreRelative(fixture.GetProperty("captureReferences"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Equal(ExpectedPublicMethods.Order(StringComparer.Ordinal), fixturesByMethod.Keys.Order(StringComparer.Ordinal));
|
||||||
|
|
||||||
|
foreach (string method in ExpectedPublicMethods)
|
||||||
|
{
|
||||||
|
JsonElement fixture = fixturesByMethod[method];
|
||||||
|
string status = fixture.GetProperty("status").GetString()!;
|
||||||
|
|
||||||
|
Assert.True(
|
||||||
|
status == "planned_fixture" || status == "documented_gap",
|
||||||
|
$"Method '{method}' must have a planned parity fixture or documented gap.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Matrix_CoversRequiredParityScenarioGroups()
|
||||||
|
{
|
||||||
|
using JsonDocument matrix = LoadParityMatrix();
|
||||||
|
HashSet<string> knownFixtureIds = GetFixtureIds(matrix.RootElement);
|
||||||
|
Dictionary<string, JsonElement> groupsById = [];
|
||||||
|
|
||||||
|
foreach (JsonElement group in matrix.RootElement.GetProperty("scenarioGroups").EnumerateArray())
|
||||||
|
{
|
||||||
|
string id = group.GetProperty("id").GetString()!;
|
||||||
|
|
||||||
|
Assert.True(groupsById.TryAdd(id, group), $"Duplicate parity scenario group '{id}'.");
|
||||||
|
Assert.NotEmpty(group.GetProperty("description").GetString()!);
|
||||||
|
Assert.NotEmpty(group.GetProperty("fixtureIds").EnumerateArray());
|
||||||
|
AssertCaptureReferencesAreRelative(group.GetProperty("captureReferences"));
|
||||||
|
|
||||||
|
foreach (JsonElement fixtureIdElement in group.GetProperty("fixtureIds").EnumerateArray())
|
||||||
|
{
|
||||||
|
string fixtureId = fixtureIdElement.GetString()!;
|
||||||
|
Assert.Contains(fixtureId, knownFixtureIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string requiredGroup in RequiredScenarioGroups)
|
||||||
|
{
|
||||||
|
Assert.True(groupsById.ContainsKey(requiredGroup), $"Missing required parity scenario group '{requiredGroup}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertScenarioCovers(groupsById["invalid_handles"], "method.remove-item.basic", "method.write.value-status-matrix");
|
||||||
|
AssertScenarioCovers(groupsById["write_statuses"], "method.write.value-status-matrix", "event.on-write-complete.status");
|
||||||
|
AssertScenarioCovers(groupsById["secured_writes"], "method.write-secured.rejection-gap", "method.write-secured2.authenticated");
|
||||||
|
AssertScenarioCovers(groupsById["add_item_context"], "method.add-item2.context", "method.add-buffered-item.context");
|
||||||
|
AssertScenarioCovers(groupsById["buffered_registration"], "method.add-buffered-item.context", "event.on-buffered-data-change.batch-gap");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Matrix_CoversEveryPublicMxAccessEventFamily()
|
||||||
|
{
|
||||||
|
using JsonDocument matrix = LoadParityMatrix();
|
||||||
|
Dictionary<string, JsonElement> fixturesByFamily = [];
|
||||||
|
|
||||||
|
foreach (JsonElement fixture in matrix.RootElement.GetProperty("eventFixtures").EnumerateArray())
|
||||||
|
{
|
||||||
|
string family = fixture.GetProperty("family").GetString()!;
|
||||||
|
string status = fixture.GetProperty("status").GetString()!;
|
||||||
|
|
||||||
|
Assert.True(fixturesByFamily.TryAdd(family, fixture), $"Duplicate parity event family '{family}'.");
|
||||||
|
Assert.Contains(status, KnownFixtureStatuses);
|
||||||
|
Assert.NotEmpty(fixture.GetProperty("assertions").EnumerateArray());
|
||||||
|
AssertCaptureReferencesAreRelative(fixture.GetProperty("captureReferences"));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string eventFamily in ExpectedEventFamilies)
|
||||||
|
{
|
||||||
|
Assert.True(fixturesByFamily.ContainsKey(eventFamily), $"Missing parity fixture for event family '{eventFamily}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.Equal("documented_gap", fixturesByFamily["MX_EVENT_FAMILY_OPERATION_COMPLETE"].GetProperty("status").GetString());
|
||||||
|
Assert.Equal("documented_gap", fixturesByFamily["MX_EVENT_FAMILY_ON_BUFFERED_DATA_CHANGE"].GetProperty("status").GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly string[] ExpectedPublicMethods =
|
||||||
|
[
|
||||||
|
"Register",
|
||||||
|
"Unregister",
|
||||||
|
"AddItem",
|
||||||
|
"AddItem2",
|
||||||
|
"RemoveItem",
|
||||||
|
"Advise",
|
||||||
|
"UnAdvise",
|
||||||
|
"AdviseSupervisory",
|
||||||
|
"AddBufferedItem",
|
||||||
|
"SetBufferedUpdateInterval",
|
||||||
|
"Suspend",
|
||||||
|
"Activate",
|
||||||
|
"Write",
|
||||||
|
"Write2",
|
||||||
|
"WriteSecured",
|
||||||
|
"WriteSecured2",
|
||||||
|
"AuthenticateUser",
|
||||||
|
"ArchestrAUserToId",
|
||||||
|
];
|
||||||
|
|
||||||
|
private static readonly string[] ExpectedEventFamilies =
|
||||||
|
[
|
||||||
|
"MX_EVENT_FAMILY_ON_DATA_CHANGE",
|
||||||
|
"MX_EVENT_FAMILY_ON_WRITE_COMPLETE",
|
||||||
|
"MX_EVENT_FAMILY_OPERATION_COMPLETE",
|
||||||
|
"MX_EVENT_FAMILY_ON_BUFFERED_DATA_CHANGE",
|
||||||
|
];
|
||||||
|
|
||||||
|
private static readonly string[] RequiredScenarioGroups =
|
||||||
|
[
|
||||||
|
"invalid_handles",
|
||||||
|
"write_statuses",
|
||||||
|
"secured_writes",
|
||||||
|
"add_item_context",
|
||||||
|
"buffered_registration",
|
||||||
|
];
|
||||||
|
|
||||||
|
private static readonly string[] KnownFixtureStatuses =
|
||||||
|
[
|
||||||
|
"planned_fixture",
|
||||||
|
"documented_gap",
|
||||||
|
];
|
||||||
|
|
||||||
|
private static void AssertRequiredFields(
|
||||||
|
JsonElement fields,
|
||||||
|
params string[] expectedFields)
|
||||||
|
{
|
||||||
|
HashSet<string> declared = fields
|
||||||
|
.EnumerateArray()
|
||||||
|
.Select(field => field.GetString()!)
|
||||||
|
.ToHashSet(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
foreach (string expectedField in expectedFields)
|
||||||
|
{
|
||||||
|
Assert.Contains(expectedField, declared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AssertCaptureReferencesAreRelative(JsonElement captureReferences)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
foreach (JsonElement captureReference in captureReferences.EnumerateArray())
|
||||||
|
{
|
||||||
|
string path = captureReference.GetString()!;
|
||||||
|
|
||||||
|
Assert.StartsWith("captures/", path, StringComparison.Ordinal);
|
||||||
|
Assert.DoesNotContain("\\", path, StringComparison.Ordinal);
|
||||||
|
Assert.False(Path.IsPathRooted(path), $"Capture reference '{path}' must be relative.");
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.True(count > 0, "Each parity fixture must reference at least one MXAccess capture.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AssertScenarioCovers(
|
||||||
|
JsonElement group,
|
||||||
|
params string[] fixtureIds)
|
||||||
|
{
|
||||||
|
HashSet<string> declared = group
|
||||||
|
.GetProperty("fixtureIds")
|
||||||
|
.EnumerateArray()
|
||||||
|
.Select(fixtureId => fixtureId.GetString()!)
|
||||||
|
.ToHashSet(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
foreach (string fixtureId in fixtureIds)
|
||||||
|
{
|
||||||
|
Assert.Contains(fixtureId, declared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HashSet<string> GetFixtureIds(JsonElement root)
|
||||||
|
{
|
||||||
|
HashSet<string> ids = new(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
foreach (JsonElement fixture in root.GetProperty("methodFixtures").EnumerateArray())
|
||||||
|
{
|
||||||
|
ids.Add(fixture.GetProperty("id").GetString()!);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (JsonElement fixture in root.GetProperty("eventFixtures").EnumerateArray())
|
||||||
|
{
|
||||||
|
ids.Add(fixture.GetProperty("id").GetString()!);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JsonDocument LoadParityMatrix()
|
||||||
|
{
|
||||||
|
return JsonDocument.Parse(File.ReadAllText(Path.Combine(GetParityFixtureRoot().FullName, "parity-fixture-matrix.json")));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DirectoryInfo GetParityFixtureRoot()
|
||||||
|
{
|
||||||
|
DirectoryInfo repositoryRoot = FindRepositoryRoot();
|
||||||
|
|
||||||
|
return new DirectoryInfo(Path.Combine(repositoryRoot.FullName, "clients", "proto", "fixtures", "parity"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DirectoryInfo FindRepositoryRoot()
|
||||||
|
{
|
||||||
|
DirectoryInfo? current = new(AppContext.BaseDirectory);
|
||||||
|
|
||||||
|
while (current is not null)
|
||||||
|
{
|
||||||
|
if (File.Exists(Path.Combine(current.FullName, "AGENTS.md"))
|
||||||
|
&& Directory.Exists(Path.Combine(current.FullName, "src"))
|
||||||
|
&& Directory.Exists(Path.Combine(current.FullName, "clients")))
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new DirectoryNotFoundException("Could not locate the repository root from the test output directory.");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user