feat(daemon): FireEvent + event name resolution + in-process gRPC tests
- name_index: add resolve_event(name) -> CEID (unit-tested). - equipment_service.hpp: extract the gRPC service + value/state conversion into a shared header; add FireEvent (optional per-fire variable values, then trigger the collection event by name). secs_gemd slims to main(). - test_daemon_service: real in-process gRPC integration test (client stub -> service -> EquipmentRuntime) proving SetVariables lands in the model, GetControlState reports the state, FireEvent and unknown-name paths behave. Separate secs_gemd_tests target (links grpc++/proto), gated on the daemon. Core suite 459/459 (2799 assertions); daemon gRPC tests 15/15. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||
#include <doctest/doctest.h>
|
||||
|
||||
#include <grpcpp/grpcpp.h>
|
||||
|
||||
#include "equipment_service.hpp"
|
||||
|
||||
using namespace secsgem;
|
||||
namespace gem = secsgem::gem;
|
||||
namespace s2 = secsgem::secs2;
|
||||
namespace pb = secsgem::v1;
|
||||
namespace dmn = secsgem::daemon;
|
||||
|
||||
#ifndef SECSGEM_DATA_DIR
|
||||
#error "SECSGEM_DATA_DIR not defined; see CMakeLists.txt"
|
||||
#endif
|
||||
|
||||
static gem::EquipmentRuntime::Config test_config() {
|
||||
gem::EquipmentRuntime::Config c;
|
||||
c.equipment_yaml = SECSGEM_DATA_DIR "/equipment.yaml";
|
||||
c.control_state_yaml = SECSGEM_DATA_DIR "/control_state.yaml";
|
||||
c.process_job_yaml = SECSGEM_DATA_DIR "/process_job_state.yaml";
|
||||
c.control_job_yaml = SECSGEM_DATA_DIR "/control_job_state.yaml";
|
||||
c.port = 0; // ephemeral; the engine isn't run() here, only poll()ed
|
||||
return c;
|
||||
}
|
||||
|
||||
// Exercises the real gRPC service over an in-process channel: client stub ->
|
||||
// service -> EquipmentRuntime, proving the RPCs move data, not just compile.
|
||||
TEST_CASE("Equipment gRPC service over an in-process channel") {
|
||||
gem::EquipmentRuntime rt(test_config());
|
||||
dmn::EquipmentService svc(rt);
|
||||
|
||||
grpc::ServerBuilder builder;
|
||||
builder.RegisterService(&svc);
|
||||
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
|
||||
REQUIRE(server);
|
||||
auto stub = pb::Equipment::NewStub(server->InProcessChannel(grpc::ChannelArguments{}));
|
||||
|
||||
SUBCASE("GetControlState returns the initial control state") {
|
||||
grpc::ClientContext ctx;
|
||||
pb::Empty req;
|
||||
pb::ControlState resp;
|
||||
auto st = stub->GetControlState(&ctx, req, &resp);
|
||||
CHECK(st.ok());
|
||||
CHECK(resp.state() == pb::ControlState::HOST_OFFLINE);
|
||||
}
|
||||
|
||||
SUBCASE("SetVariables accepts a known name and updates the model") {
|
||||
grpc::ClientContext ctx;
|
||||
pb::VariableUpdate req;
|
||||
pb::Ack resp;
|
||||
(*req.mutable_values())["ChamberPressure"].set_real(2.5);
|
||||
auto st = stub->SetVariables(&ctx, req, &resp);
|
||||
CHECK(st.ok());
|
||||
CHECK(resp.code() == pb::Ack::ACCEPT);
|
||||
rt.poll(); // drain the posted set_variable onto this thread
|
||||
CHECK(rt.model().dvids.value(101) == s2::Item::f8(2.5));
|
||||
}
|
||||
|
||||
SUBCASE("SetVariables rejects an unknown variable name") {
|
||||
grpc::ClientContext ctx;
|
||||
pb::VariableUpdate req;
|
||||
pb::Ack resp;
|
||||
(*req.mutable_values())["definitely_not_a_var"].set_real(1.0);
|
||||
auto st = stub->SetVariables(&ctx, req, &resp);
|
||||
CHECK(st.ok());
|
||||
CHECK(resp.code() == pb::Ack::PARAMETER_INVALID);
|
||||
}
|
||||
|
||||
SUBCASE("FireEvent accepts a known event and rejects an unknown one") {
|
||||
{
|
||||
grpc::ClientContext ctx;
|
||||
pb::Event req;
|
||||
pb::Ack resp;
|
||||
req.set_name("ProcessStarted");
|
||||
CHECK(stub->FireEvent(&ctx, req, &resp).ok());
|
||||
CHECK(resp.code() == pb::Ack::ACCEPT);
|
||||
}
|
||||
{
|
||||
grpc::ClientContext ctx;
|
||||
pb::Event req;
|
||||
pb::Ack resp;
|
||||
req.set_name("NoSuchEvent");
|
||||
CHECK(stub->FireEvent(&ctx, req, &resp).ok());
|
||||
CHECK(resp.code() == pb::Ack::PARAMETER_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
server->Shutdown();
|
||||
}
|
||||
Reference in New Issue
Block a user