test(java-cli): cover galaxy-discover/galaxy-watch over in-process harness
This commit is contained in:
+125
-2
@@ -5,8 +5,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.zb.mom.ww.mxgateway.client.MxGatewayAlarmFeedSubscription;
|
||||
import com.zb.mom.ww.mxgateway.client.MxGatewayClient;
|
||||
import com.zb.mom.ww.mxgateway.client.MxGatewayClientOptions;
|
||||
import galaxy_repository.v1.GalaxyRepositoryOuterClass.DeployEvent;
|
||||
import galaxy_repository.v1.GalaxyRepositoryOuterClass.GalaxyObject;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -749,6 +749,89 @@ final class MxGatewayCliTests {
|
||||
}
|
||||
}
|
||||
|
||||
// ---- galaxy-discover / galaxy-watch over the in-process harness (Task 6) ----
|
||||
|
||||
@Test
|
||||
void galaxyDiscoverPrintsPagedHierarchyJson() {
|
||||
// Drive the REAL GalaxyRepositoryClient.discoverHierarchy path over the
|
||||
// in-process harness (Task 6), so the production galaxy-discover command
|
||||
// exercises the real client paging loop against scripted objects instead
|
||||
// of a hand-written seam. The harness's fake discoverHierarchy returns a
|
||||
// single page carrying the scripted objects.
|
||||
GalaxyObject area = GalaxyObject.newBuilder()
|
||||
.setGobjectId(101)
|
||||
.setTagName("Area001")
|
||||
.setContainedName("Area001")
|
||||
.setBrowseName("Area001")
|
||||
.setIsArea(true)
|
||||
.build();
|
||||
GalaxyObject pump = GalaxyObject.newBuilder()
|
||||
.setGobjectId(202)
|
||||
.setTagName("Pump001")
|
||||
.setContainedName("Pump001")
|
||||
.setBrowseName("Pump001")
|
||||
.setParentGobjectId(101)
|
||||
.build();
|
||||
|
||||
try (InProcessGatewayHarness harness = new InProcessGatewayHarness()) {
|
||||
harness.setScriptedObjects(List.of(area, pump));
|
||||
CliRun run = executeGalaxy(new HarnessGalaxyClientFactory(harness), "galaxy-discover", "--json");
|
||||
|
||||
assertEquals(0, run.exitCode(), "errors:\n" + run.errors());
|
||||
String out = run.output();
|
||||
// galaxy-discover --json renders {"command":..,"options":..,"objects":[{galaxyObjectMap}]}.
|
||||
assertTrue(out.contains("\"command\":\"galaxy-discover\""), out);
|
||||
// Both scripted objects render with the flattened object fields.
|
||||
assertTrue(out.contains("\"tagName\":\"Area001\""), out);
|
||||
assertTrue(out.contains("\"tagName\":\"Pump001\""), out);
|
||||
assertTrue(out.contains("\"gobjectId\":101"), out);
|
||||
assertTrue(out.contains("\"gobjectId\":202"), out);
|
||||
assertTrue(out.contains("\"parentGobjectId\":101"), out);
|
||||
assertTrue(out.contains("\"isArea\":true"), out);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void galaxyWatchRendersScriptedDeployEvents() {
|
||||
// Drive the REAL GalaxyRepositoryClient.watchDeployEvents / DeployEventStream
|
||||
// path over the in-process harness. The harness's fake watchDeployEvents
|
||||
// streams the scripted deploy events then completes; the CLI's --limit
|
||||
// option caps how many it prints before closing the stream.
|
||||
DeployEvent first = DeployEvent.newBuilder()
|
||||
.setSequence(7L)
|
||||
.setObjectCount(12)
|
||||
.setAttributeCount(34)
|
||||
.build();
|
||||
DeployEvent second = DeployEvent.newBuilder()
|
||||
.setSequence(8L)
|
||||
.setObjectCount(13)
|
||||
.setAttributeCount(35)
|
||||
.build();
|
||||
DeployEvent third = DeployEvent.newBuilder()
|
||||
.setSequence(9L)
|
||||
.setObjectCount(14)
|
||||
.setAttributeCount(36)
|
||||
.build();
|
||||
|
||||
try (InProcessGatewayHarness harness = new InProcessGatewayHarness()) {
|
||||
harness.setScriptedDeployEvents(List.of(first, second, third));
|
||||
// --limit 2 caps the feed at the first two scripted events.
|
||||
CliRun run = executeGalaxy(
|
||||
new HarnessGalaxyClientFactory(harness), "galaxy-watch", "--limit", "2", "--json");
|
||||
|
||||
assertEquals(0, run.exitCode(), "errors:\n" + run.errors());
|
||||
String out = run.output();
|
||||
// galaxy-watch --json prints one proto-JSON object per event; proto3
|
||||
// JSON renders uint64 sequence as a decimal string.
|
||||
assertTrue(out.contains("\"sequence\":\"7\""), out);
|
||||
assertTrue(out.contains("\"objectCount\":12"), out);
|
||||
assertTrue(out.contains("\"attributeCount\":34"), out);
|
||||
assertTrue(out.contains("\"sequence\":\"8\""), out);
|
||||
// --limit 2 must stop before printing the third scripted event.
|
||||
assertFalse(out.contains("\"sequence\":\"9\""), out);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void batchCommandExecutesVersionAndEmitsEorMarker() {
|
||||
CliRun run = executeBatch(new FakeClientFactory(), "version --json\n");
|
||||
@@ -863,6 +946,24 @@ final class MxGatewayCliTests {
|
||||
return new CliRun(exitCode, output.toString(), errors.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a galaxy subcommand against the supplied {@link
|
||||
* MxGatewayCli.GalaxyClientFactory}, wiring it through the production
|
||||
* {@code commandLine(gatewayFactory, galaxyFactory)} two-arg overload (Task 3
|
||||
* seam). The gateway factory slot is unused by galaxy commands, so a plain
|
||||
* {@link FakeClientFactory} fills it. Mirrors {@link #execute} for the
|
||||
* gateway commands.
|
||||
*/
|
||||
private static CliRun executeGalaxy(MxGatewayCli.GalaxyClientFactory galaxyFactory, String... args) {
|
||||
StringWriter output = new StringWriter();
|
||||
StringWriter errors = new StringWriter();
|
||||
picocli.CommandLine commandLine = MxGatewayCli.commandLine(new FakeClientFactory(), galaxyFactory);
|
||||
commandLine.setOut(new PrintWriter(output, true));
|
||||
commandLine.setErr(new PrintWriter(errors, true));
|
||||
int exitCode = commandLine.execute(args);
|
||||
return new CliRun(exitCode, output.toString(), errors.toString());
|
||||
}
|
||||
|
||||
private record CliRun(int exitCode, String output, String errors) {
|
||||
}
|
||||
|
||||
@@ -907,7 +1008,8 @@ final class MxGatewayCliTests {
|
||||
|
||||
/**
|
||||
* Factory that wires the production {@link MxGatewayCli.GrpcMxGatewayCliClient}
|
||||
* adapter around the harness's REAL {@link MxGatewayClient}, so the
|
||||
* adapter around the harness's REAL
|
||||
* {@link com.zb.mom.ww.mxgateway.client.MxGatewayClient}, so the
|
||||
* stream-events command runs against the in-process scripted gateway over
|
||||
* a real channel (exercising the real {@code MxEventStream}). Mirrors the
|
||||
* production {@code GrpcMxGatewayCliClientFactory}, swapping only the
|
||||
@@ -927,6 +1029,27 @@ final class MxGatewayCliTests {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Galaxy factory that returns the harness's REAL {@link
|
||||
* com.zb.mom.ww.mxgateway.client.GalaxyRepositoryClient} over the in-process
|
||||
* scripted {@code GalaxyRepository} service, so galaxy-discover / galaxy-watch
|
||||
* exercise the real client (paging loop, deploy-event stream wrapper) against
|
||||
* scripted payloads. Mirrors the production {@code GrpcGalaxyClientFactory},
|
||||
* swapping only client construction for the harness-backed client.
|
||||
*/
|
||||
private static final class HarnessGalaxyClientFactory implements MxGatewayCli.GalaxyClientFactory {
|
||||
private final InProcessGatewayHarness harness;
|
||||
|
||||
private HarnessGalaxyClientFactory(InProcessGatewayHarness harness) {
|
||||
this.harness = harness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.zb.mom.ww.mxgateway.client.GalaxyRepositoryClient connect(MxGatewayClientOptions options) {
|
||||
return harness.galaxyClient();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class OverflowingFakeClient implements MxGatewayCli.MxGatewayCliClient {
|
||||
private final PrintWriter out;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user