Dhanya Thattil ce7270e8a2
commands code generation (#871)
* commands code generation  (#803)

* commands code generation for only frames command

* fix cmake file and add Caller files

* working exptime, fully extended commands file and its variants

* start adding template commands

* add INT_CMD_VEC_ID template

* add list command, generate multiple bins, format code

* reach 208 commands using the cpp macros

* add tests for command parser

* start adding tests for commands parser

* fix typo to use commands.yaml

* add more tests for command_parser

* add all template functions (up to 218 commands)

* finish template functions and add more CmdProxy.cpp functions (250+)

* 257 commands

* 300 commands the rest are very special commands

* add special commands without generation

* separate special functions from generated c++ file

* implementing one command for put and get (buggy)

* add infer action in a separate file

* generate header for special commands from yaml

* allow only 0 or 1 for bool inputs

* group all commands in gen_commands.py

* add help to gen_commands.py

* add autocomplete bash script

* autocompletion: add support for module levels and help

* remove debugging line

* add autocompletion, help to commands, change int [0,1] to bool

* copy tests for Caller.cpp. Tests pass

* update with the new developer branch changes

* fix errors after merging (there is problems with tests)

* fixed port/stopport in yaml (intput typo), added '_caller' to the test dac and test on chip dac command in global test for cmdcaller

* undo previous test simulator debug change

* add documentation for the generated code

* reducing the comment to be replaced in length so formatting does not split into 2 lines

* removed formatting specific style of C++11 in gen_commands.py to keep with the top level clang format of the project
* regeneratign code for commands

* automation generated

* Redirect deprecated commands (#872)

* working implementation, need to fix dac

* fixed deprecation redirect for dac command

* Detector specific autocomplete (#873)

* working implementation, need to fix dac

* fixed deprecation redirect for dac command

* detector specific completion for dac

* added autocomplete using detector specific

* fixed error when autocompleting partial words

* Generate commands/fix commands (#875)

* fix vm_a, im_a etc have deg Celsius suffix, also help missing or changed in some places

* dac: require det id for all, arg0 to be printed at output, help for onchip dac and dac, onchipdac: spacing

* getscan detid and blocking trigger help

* udp_Dstlist det_id fixed, but rx_id invalid

* cmdApp in line with cmdLineApp (missing version, receiver_id, not creating det object in help action

* added set_command to differentiate between check_det_id and require_det_id (mixed up), args: -1 needs to check for at least one argument

* reordering

* reordering and checked till integer_command_hex

* fixed a lot more commands

* fix caller tests for eiger

* changes to tests after Bechir left

* changing .cmd to .cmdcall for the caller commands

* fixed tests for caller, still warning for setexptime about cast input

* autocomplete ran

* add moench test

* regenerating autocomplete and commands

* fixing other things from merge conflicts (renaming slsDetectorDefs to defs in commands.yaml)

* formatting

* added code injection to help (#876)

* updated 3 commands to have get output that can be put into put (#877)

* updated some commands to have get output that can be put into put

* fix tests for clkdiv

* adding help to free (#878)

* removing old commands and renaming them, (also making it work for parameters command as it was still calling cmdproxy) (#879)

* More helpful error messages for unsupported actions (#880)

* removing old commands and renaming them, (also making it work for parameters command as it was still calling cmdproxy)

* Added specific help for unsupported actions

* fixed a vetofile get special exception message. more specific warning for special exception message instead of no function warning

* added condition checking true in exceptions for special message

---------
Co-authored-by: Bechir Brahem <bachbrahem@gmail.com>
Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>
Co-authored-by: Dhanya Thattil <dhanya.thattil@psi.ch>
2023-12-13 14:43:38 +01:00

669 lines
25 KiB
C++

// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#include "Caller.h"
#include "catch.hpp"
#include "sls/Detector.h"
#include "sls/sls_detector_defs.h"
#include <array>
#include <sstream>
#include <thread>
#include "sls/versionAPI.h"
#include "test-Caller-global.h"
#include "tests/globals.h"
namespace sls {
using test::GET;
using test::PUT;
/** temperature */
TEST_CASE("CALLER::temp_fpgaext", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
REQUIRE_NOTHROW(caller.call("temp_fpgaext", {}, -1, GET));
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("temp_fpgaext", {}, 0, GET, oss));
std::string s = (oss.str()).erase(0, strlen("temp_fpgaext "));
REQUIRE(std::stoi(s) != -1);
} else {
REQUIRE_THROWS(caller.call("temp_fpgaext", {}, -1, GET));
}
}
TEST_CASE("CALLER::temp_10ge", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
REQUIRE_NOTHROW(caller.call("temp_10ge", {}, -1, GET));
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("temp_10ge", {}, 0, GET, oss));
std::string s = (oss.str()).erase(0, strlen("temp_10ge "));
REQUIRE(std::stoi(s) != -1);
} else {
REQUIRE_THROWS(caller.call("temp_10ge", {}, -1, GET));
}
}
TEST_CASE("CALLER::temp_dcdc", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
REQUIRE_NOTHROW(caller.call("temp_dcdc", {}, -1, GET));
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("temp_dcdc", {}, 0, GET, oss));
std::string s = (oss.str()).erase(0, strlen("temp_dcdc "));
REQUIRE(std::stoi(s) != -1);
} else {
REQUIRE_THROWS(caller.call("temp_dcdc", {}, -1, GET));
}
}
TEST_CASE("CALLER::temp_sodl", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
REQUIRE_NOTHROW(caller.call("temp_sodl", {}, -1, GET));
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("temp_sodl", {}, 0, GET, oss));
std::string s = (oss.str()).erase(0, strlen("temp_sodl "));
REQUIRE(std::stoi(s) != -1);
} else {
REQUIRE_THROWS(caller.call("temp_sodl", {}, -1, GET));
}
}
TEST_CASE("CALLER::temp_sodr", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
REQUIRE_NOTHROW(caller.call("temp_sodr", {}, -1, GET));
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("temp_sodr", {}, 0, GET, oss));
std::string s = (oss.str()).erase(0, strlen("temp_sodr "));
REQUIRE(std::stoi(s) != -1);
} else {
REQUIRE_THROWS(caller.call("temp_sodr", {}, -1, GET));
}
}
TEST_CASE("CALLER::temp_fpgafl", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
REQUIRE_NOTHROW(caller.call("temp_fpgafl", {}, -1, GET));
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("temp_fpgafl", {}, 0, GET, oss));
std::string s = (oss.str()).erase(0, strlen("temp_fpgafl "));
REQUIRE(std::stoi(s) != -1);
} else {
REQUIRE_THROWS(caller.call("temp_fpgafl", {}, -1, GET));
}
}
TEST_CASE("CALLER::temp_fpgafr", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
REQUIRE_NOTHROW(caller.call("temp_fpgafr", {}, -1, GET));
std::ostringstream oss;
REQUIRE_NOTHROW(caller.call("temp_fpgafr", {}, 0, GET, oss));
std::string s = (oss.str()).erase(0, strlen("temp_fpgafr "));
REQUIRE(std::stoi(s) != -1);
} else {
REQUIRE_THROWS(caller.call("temp_fpgafr", {}, -1, GET));
}
}
/* dacs */
TEST_CASE("CALLER::Setting and reading back EIGER dacs", "[.cmdcall][.dacs]") {
// vsvp, vtr, vrf, vrs, vsvn, vtgstv, vcmp_ll, vcmp_lr, vcal, vcmp_rl,
// rxb_rb, rxb_lb, vcmp_rr, vcp, vcn, vis, vthreshold
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
SECTION("vsvp") { test_dac_caller(defs::VSVP, "vsvp", 5); }
SECTION("vtrim") { test_dac_caller(defs::VTRIM, "vtrim", 1200); }
SECTION("vrpreamp") {
test_dac_caller(defs::VRPREAMP, "vrpreamp", 1500);
}
SECTION("vrshaper") {
test_dac_caller(defs::VRSHAPER, "vrshaper", 1510);
}
SECTION("vsvn") { test_dac_caller(defs::VSVN, "vsvn", 3800); }
SECTION("vtgstv") { test_dac_caller(defs::VTGSTV, "vtgstv", 2550); }
SECTION("vcmp_ll") { test_dac_caller(defs::VCMP_LL, "vcmp_ll", 1400); }
SECTION("vcmp_lr") { test_dac_caller(defs::VCMP_LR, "vcmp_lr", 1400); }
SECTION("vcal") { test_dac_caller(defs::VCAL, "vcal", 1400); }
SECTION("vcmp_rl") { test_dac_caller(defs::VCMP_RL, "vcmp_rl", 1400); }
SECTION("rxb_rb") { test_dac_caller(defs::RXB_RB, "rxb_rb", 1400); }
SECTION("rxb_lb") { test_dac_caller(defs::RXB_LB, "rxb_lb", 1400); }
SECTION("vcmp_rr") { test_dac_caller(defs::VCMP_RR, "vcmp_rr", 1400); }
SECTION("vcp") { test_dac_caller(defs::VCP, "vcp", 1400); }
SECTION("vcn") { test_dac_caller(defs::VCN, "vcn", 1400); }
SECTION("vishaper") {
test_dac_caller(defs::VISHAPER, "vishaper", 1400);
}
SECTION("iodelay") { test_dac_caller(defs::IO_DELAY, "iodelay", 1400); }
SECTION("vthreshold") {
// Read out individual vcmp to be able to reset after
// the test is done
auto vcmp_ll = det.getDAC(defs::VCMP_LL, false);
auto vcmp_lr = det.getDAC(defs::VCMP_LR, false);
auto vcmp_rl = det.getDAC(defs::VCMP_RL, false);
auto vcmp_rr = det.getDAC(defs::VCMP_RR, false);
auto vcp = det.getDAC(defs::VCP, false);
{
std::ostringstream oss;
caller.call("dac", {"vthreshold", "1234"}, -1, PUT, oss);
REQUIRE(oss.str() == "dac vthreshold 1234\n");
}
{
std::ostringstream oss;
caller.call("dac", {"vthreshold"}, -1, GET, oss);
REQUIRE(oss.str() == "dac vthreshold 1234\n");
}
// Reset dacs after test
for (int i = 0; i != det.size(); ++i) {
det.setDAC(defs::VCMP_LL, vcmp_ll[i], false, {i});
det.setDAC(defs::VCMP_LR, vcmp_lr[i], false, {i});
det.setDAC(defs::VCMP_RL, vcmp_rl[i], false, {i});
det.setDAC(defs::VCMP_RR, vcmp_rr[i], false, {i});
det.setDAC(defs::VCP, vcp[i], false, {i});
}
}
// gotthard
REQUIRE_THROWS(caller.call("vref_ds", {}, -1, GET));
REQUIRE_THROWS(caller.call("vcascn_pb", {}, -1, GET));
REQUIRE_THROWS(caller.call("vcascp_pb", {}, -1, GET));
REQUIRE_THROWS(caller.call("vout_cm", {}, -1, GET));
REQUIRE_THROWS(caller.call("vcasc_out", {}, -1, GET));
REQUIRE_THROWS(caller.call("vin_cm", {}, -1, GET));
REQUIRE_THROWS(caller.call("vref_comp", {}, -1, GET));
REQUIRE_THROWS(caller.call("ib_test_c", {}, -1, GET));
// mythen3
// REQUIRE_THROWS(caller.call("vrpreamp", {}, -1, GET));
// REQUIRE_THROWS(caller.call("vrshaper", {}, -1, GET));
REQUIRE_THROWS(caller.call("vrshaper_n", {}, -1, GET));
REQUIRE_THROWS(caller.call("vipre", {}, -1, GET));
// REQUIRE_THROWS(caller.call("vishaper", {}, -1, GET));
REQUIRE_THROWS(caller.call("vdcsh", {}, -1, GET));
REQUIRE_THROWS(caller.call("vth1", {}, -1, GET));
REQUIRE_THROWS(caller.call("vth2", {}, -1, GET));
REQUIRE_THROWS(caller.call("vth3", {}, -1, GET));
REQUIRE_THROWS(caller.call("vcal_n", {}, -1, GET));
REQUIRE_THROWS(caller.call("vcal_p", {}, -1, GET));
// REQUIRE_THROWS(caller.call("vtrim", {}, -1, GET));
REQUIRE_THROWS(caller.call("vcassh", {}, -1, GET));
REQUIRE_THROWS(caller.call("vcas", {}, -1, GET));
REQUIRE_THROWS(caller.call("vicin", {}, -1, GET));
REQUIRE_THROWS(caller.call("vipre_out", {}, -1, GET));
// gotthard2
REQUIRE_THROWS(caller.call("vref_h_adc", {}, -1, GET));
REQUIRE_THROWS(caller.call("vb_comp_fe", {}, -1, GET));
REQUIRE_THROWS(caller.call("vb_comp_adc", {}, -1, GET));
REQUIRE_THROWS(caller.call("vcom_cds", {}, -1, GET));
REQUIRE_THROWS(caller.call("vref_rstore", {}, -1, GET));
REQUIRE_THROWS(caller.call("vb_opa_1st", {}, -1, GET));
REQUIRE_THROWS(caller.call("vref_comp_fe", {}, -1, GET));
REQUIRE_THROWS(caller.call("vcom_adc1", {}, -1, GET));
REQUIRE_THROWS(caller.call("vref_l_adc", {}, -1, GET));
REQUIRE_THROWS(caller.call("vref_cds", {}, -1, GET));
REQUIRE_THROWS(caller.call("vb_cs", {}, -1, GET));
REQUIRE_THROWS(caller.call("vb_opa_fd", {}, -1, GET));
REQUIRE_THROWS(caller.call("vcom_adc2", {}, -1, GET));
// jungfrau
REQUIRE_THROWS(caller.call("vb_comp", {}, -1, GET));
REQUIRE_THROWS(caller.call("vdd_prot", {}, -1, GET));
REQUIRE_THROWS(caller.call("vin_com", {}, -1, GET));
REQUIRE_THROWS(caller.call("vref_prech", {}, -1, GET));
REQUIRE_THROWS(caller.call("vb_pixbuf", {}, -1, GET));
REQUIRE_THROWS(caller.call("vb_ds", {}, -1, GET));
REQUIRE_THROWS(caller.call("vref_ds", {}, -1, GET));
REQUIRE_THROWS(caller.call("vref_comp", {}, -1, GET));
}
}
/* acquisition */
/* Network Configuration (Detector<->Receiver) */
TEST_CASE("CALLER::txdelay_left", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_val = det.getTransmissionDelayLeft();
{
std::ostringstream oss1, oss2;
caller.call("txdelay_left", {"5000"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "txdelay_left 5000\n");
caller.call("txdelay_left", {}, -1, GET, oss2);
REQUIRE(oss2.str() == "txdelay_left 5000\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setTransmissionDelayLeft(prev_val[i]);
}
} else {
REQUIRE_THROWS(caller.call("txdelay_left", {}, -1, GET));
}
}
TEST_CASE("CALLER::txdelay_right", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_val = det.getTransmissionDelayRight();
{
std::ostringstream oss1, oss2;
caller.call("txdelay_right", {"5000"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "txdelay_right 5000\n");
caller.call("txdelay_right", {}, -1, GET, oss2);
REQUIRE(oss2.str() == "txdelay_right 5000\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setTransmissionDelayRight(prev_val[i]);
}
} else {
REQUIRE_THROWS(caller.call("txdelay_right", {}, -1, GET));
}
}
/* Eiger Specific */
TEST_CASE("CALLER::subexptime", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto time = det.getSubExptime();
std::ostringstream oss1, oss2;
caller.call("subexptime", {"2.5us"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "subexptime 2.5us\n");
caller.call("subexptime", {}, -1, GET, oss2);
REQUIRE(oss2.str() == "subexptime 2.5us\n");
for (int i = 0; i != det.size(); ++i) {
det.setSubExptime(time[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("subexptime", {}, -1, GET));
REQUIRE_THROWS(caller.call("subexptime", {"2.13"}, -1, PUT));
}
}
TEST_CASE("CALLER::subdeadtime", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto time = det.getSubDeadTime();
std::ostringstream oss1, oss2;
caller.call("subdeadtime", {"500us"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "subdeadtime 500us\n");
caller.call("subdeadtime", {}, -1, GET, oss2);
REQUIRE(oss2.str() == "subdeadtime 500us\n");
for (int i = 0; i != det.size(); ++i) {
det.setSubDeadTime(time[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("subdeadtime", {}, -1, GET));
REQUIRE_THROWS(caller.call("subdeadtime", {"2.13"}, -1, PUT));
}
}
TEST_CASE("CALLER::overflow", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto previous = det.getOverFlowMode();
std::ostringstream oss1, oss2, oss3;
caller.call("overflow", {"1"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "overflow 1\n");
caller.call("overflow", {}, -1, GET, oss2);
REQUIRE(oss2.str() == "overflow 1\n");
caller.call("overflow", {"0"}, -1, PUT, oss3);
REQUIRE(oss3.str() == "overflow 0\n");
for (int i = 0; i != det.size(); ++i) {
det.setOverFlowMode(previous[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("overflow", {}, -1, GET));
}
}
TEST_CASE("CALLER::ratecorr", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_dr = det.getDynamicRange().tsquash("inconsistent dr to test");
auto prev_tau = det.getRateCorrection();
det.setDynamicRange(16);
{
std::ostringstream oss;
caller.call("ratecorr", {"120"}, -1, PUT, oss);
REQUIRE(oss.str() == "ratecorr 120ns\n");
}
{
std::ostringstream oss;
caller.call("ratecorr", {}, -1, GET, oss);
REQUIRE(oss.str() == "ratecorr 120ns\n");
}
// may fail if default settings not loaded
// REQUIRE_NOTHROW(caller.call("ratecorr", {"-1"}, -1, PUT));
{
std::ostringstream oss;
caller.call("ratecorr", {"0"}, -1, PUT, oss);
REQUIRE(oss.str() == "ratecorr 0ns\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setRateCorrection(prev_tau[i], {i});
}
det.setDynamicRange(prev_dr);
} else {
REQUIRE_THROWS(caller.call("ratecorr", {}, -1, GET));
}
}
TEST_CASE("CALLER::interruptsubframe", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_val = det.getInterruptSubframe();
std::ostringstream oss1, oss2, oss3;
caller.call("interruptsubframe", {"1"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "interruptsubframe 1\n");
caller.call("interruptsubframe", {}, -1, GET, oss2);
REQUIRE(oss2.str() == "interruptsubframe 1\n");
caller.call("interruptsubframe", {"0"}, -1, PUT, oss3);
REQUIRE(oss3.str() == "interruptsubframe 0\n");
for (int i = 0; i != det.size(); ++i) {
det.setInterruptSubframe(prev_val[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("interruptsubframe", {}, -1, GET));
REQUIRE_THROWS(caller.call("interruptsubframe", {"1"}, -1, PUT));
}
}
TEST_CASE("CALLER::measuredperiod", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_frames = det.getNumberOfFrames().tsquash(
"inconsistent number of frames to test");
auto prev_timing =
det.getTimingMode().tsquash("inconsistent timing mode to test");
auto prev_period = det.getPeriod();
det.setNumberOfFrames(2);
det.setPeriod(std::chrono::seconds(1));
det.setTimingMode(defs::AUTO_TIMING);
det.startDetector();
std::this_thread::sleep_for(std::chrono::seconds(3));
std::ostringstream oss;
caller.call("measuredperiod", {}, -1, GET, oss);
std::string st = oss.str();
std::string s;
if (st.find('[') != std::string::npos) {
s = st.erase(0, strlen("measuredperiod ["));
} else {
s = st.erase(0, strlen("measuredperiod "));
}
double val = std::stod(s);
// REQUIRE(val >= 1.0);
REQUIRE(val < 2.0);
for (int i = 0; i != det.size(); ++i) {
det.setPeriod(prev_period[i], {i});
}
det.setNumberOfFrames(prev_frames);
det.setTimingMode(prev_timing);
} else {
REQUIRE_THROWS(caller.call("measuredperiod", {}, -1, GET));
}
}
TEST_CASE("CALLER::measuredsubperiod", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_frames = det.getNumberOfFrames().tsquash(
"inconsistent number of frames to test");
auto prev_timing =
det.getTimingMode().tsquash("inconsistent timing mode to test");
auto prev_period = det.getPeriod();
auto prev_dr = det.getDynamicRange().tsquash("inconsistent dr to test");
det.setNumberOfFrames(1);
det.setPeriod(std::chrono::seconds(1));
det.setTimingMode(defs::AUTO_TIMING);
det.setDynamicRange(32);
det.startDetector();
std::this_thread::sleep_for(std::chrono::seconds(3));
std::ostringstream oss;
caller.call("measuredsubperiod", {}, -1, GET, oss);
std::string st = oss.str();
std::string s;
if (st.find('[') != std::string::npos) {
s = st.erase(0, strlen("measuredsubperiod ["));
} else {
s = st.erase(0, strlen("measuredsubperiod "));
}
double val = std::stod(s);
REQUIRE(val >= 0);
REQUIRE(val < 1000);
for (int i = 0; i != det.size(); ++i) {
det.setPeriod(prev_period[i], {i});
}
det.setNumberOfFrames(prev_frames);
det.setTimingMode(prev_timing);
det.setDynamicRange(prev_dr);
} else {
REQUIRE_THROWS(caller.call("measuredsubperiod", {}, -1, GET));
}
}
TEST_CASE("CALLER::activate", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_val = det.getActive();
{
std::ostringstream oss;
caller.call("activate", {"1"}, -1, PUT, oss);
REQUIRE(oss.str() == "activate 1\n");
}
{
std::ostringstream oss;
caller.call("activate", {}, -1, GET, oss);
REQUIRE(oss.str() == "activate 1\n");
}
{
std::ostringstream oss;
caller.call("activate", {"0"}, -1, PUT, oss);
REQUIRE(oss.str() == "activate 0\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setActive(prev_val[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("activate", {}, -1, GET));
REQUIRE_THROWS(caller.call("activate", {"1"}, -1, PUT));
}
}
TEST_CASE("CALLER::partialreset", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_val = det.getPartialReset();
std::ostringstream oss1, oss2, oss3;
caller.call("partialreset", {"1"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "partialreset 1\n");
caller.call("partialreset", {}, -1, GET, oss2);
REQUIRE(oss2.str() == "partialreset 1\n");
caller.call("partialreset", {"0"}, -1, PUT, oss3);
REQUIRE(oss3.str() == "partialreset 0\n");
for (int i = 0; i != det.size(); ++i) {
det.setPartialReset(prev_val[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("partialreset", {}, -1, GET));
REQUIRE_THROWS(caller.call("partialreset", {"1"}, -1, PUT));
}
}
TEST_CASE("CALLER::pulse", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
REQUIRE_THROWS(caller.call("pulse", {}, -1, GET));
std::ostringstream oss;
caller.call("pulse", {"1", "1", "5"}, -1, PUT, oss);
REQUIRE(oss.str() == "pulse [1, 1, 5]\n");
} else {
REQUIRE_THROWS(caller.call("pulse", {}, -1, GET));
REQUIRE_THROWS(caller.call("pulse", {"1", "1", "5"}, -1, PUT));
}
}
TEST_CASE("CALLER::pulsenmove", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
REQUIRE_THROWS(caller.call("pulsenmove", {}, -1, GET));
std::ostringstream oss;
caller.call("pulsenmove", {"1", "1", "5"}, -1, PUT, oss);
REQUIRE(oss.str() == "pulsenmove [1, 1, 5]\n");
} else {
REQUIRE_THROWS(caller.call("pulsenmove", {}, -1, GET));
REQUIRE_THROWS(caller.call("pulsenmove", {"1", "1", "5"}, -1, PUT));
}
}
TEST_CASE("CALLER::pulsechip", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
REQUIRE_THROWS(caller.call("pulsechip", {}, -1, GET));
std::ostringstream oss;
caller.call("pulsechip", {"1"}, -1, PUT, oss);
REQUIRE(oss.str() == "pulsechip 1\n");
} else {
REQUIRE_THROWS(caller.call("pulsechip", {}, -1, GET));
REQUIRE_THROWS(caller.call("pulsechip", {"1"}, -1, PUT));
}
}
TEST_CASE("CALLER::quad", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_val = det.getQuad().tsquash("inconsistent quad to test");
// Quad only works with a single half module EIGER
std::ostringstream oss;
caller.call("quad", {}, -1, GET, oss);
REQUIRE(oss.str() == "quad 0\n");
det.setQuad(prev_val);
} else {
REQUIRE_THROWS(caller.call("quad", {}, -1, GET));
}
}
TEST_CASE("CALLER::datastream", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_val_left = det.getDataStream(defs::LEFT);
auto prev_val_right = det.getDataStream(defs::RIGHT);
// no "left" or "right"
REQUIRE_THROWS(caller.call("datastream", {"1"}, -1, PUT));
{
std::ostringstream oss;
caller.call("datastream", {"left", "0"}, -1, PUT, oss);
REQUIRE(oss.str() == "datastream [left, 0]\n");
}
{
std::ostringstream oss;
caller.call("datastream", {"right", "0"}, -1, PUT, oss);
REQUIRE(oss.str() == "datastream [right, 0]\n");
}
{
std::ostringstream oss;
caller.call("datastream", {"left", "1"}, -1, PUT, oss);
REQUIRE(oss.str() == "datastream [left, 1]\n");
}
{
std::ostringstream oss;
caller.call("datastream", {"right", "1"}, -1, PUT, oss);
REQUIRE(oss.str() == "datastream [right, 1]\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setDataStream(defs::LEFT, prev_val_left[i], {i});
det.setDataStream(defs::RIGHT, prev_val_right[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("datastream", {}, -1, GET));
REQUIRE_THROWS(caller.call("datastream", {"1"}, -1, PUT));
REQUIRE_THROWS(caller.call("datastream", {"left", "1"}, -1, PUT));
}
}
TEST_CASE("CALLER::top", "[.cmdcall]") {
Detector det;
Caller caller(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER) {
auto prev_val = det.getTop();
int numModulesTested = 1;
if (det.size() > 1) {
numModulesTested = 2;
}
for (int i = 0; i != numModulesTested; ++i) {
std::ostringstream oss1, oss2, oss3;
caller.call("top", {"1"}, i, PUT, oss1);
REQUIRE(oss1.str() == "top 1\n");
caller.call("top", {}, i, GET, oss2);
REQUIRE(oss2.str() == "top 1\n");
caller.call("top", {"0"}, i, PUT, oss3);
REQUIRE(oss3.str() == "top 0\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setTop(prev_val[i], {i});
}
} else {
REQUIRE_THROWS(caller.call("top", {}, -1, GET));
REQUIRE_THROWS(caller.call("top", {"1"}, -1, PUT));
}
}
} // namespace sls