LCOV - code coverage report
Current view: top level - daphnemodules/test/apps - DaphneMezzModule_test.cxx (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 107 0
Test Date: 2026-10-11 15:05:20 Functions: 0.0 % 4 0

            Line data    Source code
       1              : /**
       2              :  * @file DaphneMezzModule_test.cxx
       3              :  *
       4              :  * Testing configurations sender for the daphne v3
       5              :  *
       6              :  * This is part of the DUNE DAQ Software Suite, copyright 2020.
       7              :  * Licensing/copyright details are in the COPYING file that you should have
       8              :  * received with this code.
       9              :  *
      10              :  */
      11              : 
      12              : #include "DaphneV3Interface.hpp"
      13              : 
      14              : #include "daphnemodules/daphne_control_high.pb.h"
      15              : #include <zmq.hpp>
      16              : 
      17              : #include <chrono>
      18              : #include <cstdlib>
      19              : #include <cstring>
      20              : #include <iostream>
      21              : #include <random>
      22              : #include <stdexcept>
      23              : #include <string>
      24              : #include <vector>
      25              : 
      26              : using namespace daphne;
      27              : using namespace dunedaq::daphnemodules;
      28              : 
      29              : // ------------- small helpers -------------
      30              : static std::vector<zmq::message_t>
      31              : recv_multipart(zmq::socket_t& s)
      32              : {
      33              :   std::vector<zmq::message_t> frames;
      34              :   while (true) {
      35              :     zmq::message_t part;
      36              :     auto ok = s.recv(part, zmq::recv_flags::none);
      37              :     if (!ok || *ok <= 0)
      38              :       throw std::runtime_error("No response from slow controller");
      39              :     frames.emplace_back(std::move(part));
      40              :     if (!s.get(zmq::sockopt::rcvmore))
      41              :       break;
      42              :   }
      43              :   return frames;
      44              : }
      45              : 
      46              : static inline uint64_t
      47            0 : now_ns()
      48              : {
      49            0 :   using namespace std::chrono;
      50            0 :   return duration_cast<nanoseconds>(steady_clock::now().time_since_epoch()).count();
      51              : }
      52              : 
      53              : static inline std::pair<uint64_t, uint64_t>
      54            0 : next_ids()
      55              : {
      56            0 :   static std::mt19937_64 rng{ std::random_device{}() };
      57            0 :   static uint64_t seq = 1;
      58            0 :   uint64_t t = now_ns();
      59            0 :   uint64_t task = (t << 16) ^ (rng() & 0xFFFF);
      60            0 :   uint64_t msg = (t << 1) ^ (++seq);
      61            0 :   task &= ((1ull << 63) - 1);
      62            0 :   msg &= ((1ull << 63) - 1);
      63            0 :   return { task, msg };
      64              : }
      65              : 
      66              : static void
      67            0 : usage(const char* prog)
      68              : {
      69            0 :   std::cerr << "Usage: " << prog << " [--ip <addr>] [--port <num>] [--route <name>]\n"
      70              :             << "       " << prog << " [ip] [port]\n"
      71              :             << "Env:   DAPHNE_IP, DAPHNE_PORT\n"
      72            0 :             << "Default: 10.73.137.161:9000, route=mezz/0\n";
      73            0 : }
      74              : 
      75              : int
      76            0 : main(int argc, char** argv)
      77              : {
      78              :   // ---- Defaults
      79            0 :   std::string ip = "10.73.137.161";
      80            0 :   int port = 9000;
      81            0 :   std::string route = "mezz/0";
      82              : 
      83              :   // ---- Env
      84            0 :   if (const char* eip = std::getenv("DAPHNE_IP"); eip && *eip)
      85            0 :     ip = eip;
      86            0 :   if (const char* ep = std::getenv("DAPHNE_PORT"); ep && *ep) {
      87            0 :     try {
      88            0 :       port = std::stoi(ep);
      89            0 :     } catch (...) {
      90            0 :     }
      91              :   }
      92              : 
      93              :   // ---- CLI flags (priority over env)
      94            0 :   for (int i = 1; i < argc; ++i) {
      95            0 :     if (!std::strcmp(argv[i], "--help") || !std::strcmp(argv[i], "-h")) {
      96            0 :       usage(argv[0]);
      97              :       return 0;
      98              :     }
      99            0 :     if (!std::strcmp(argv[i], "--ip") && i + 1 < argc) {
     100            0 :       ip = argv[++i];
     101            0 :       continue;
     102              :     }
     103            0 :     if (!std::strcmp(argv[i], "--port") && i + 1 < argc) {
     104            0 :       try {
     105            0 :         port = std::stoi(argv[++i]);
     106            0 :       } catch (...) {
     107            0 :       }
     108            0 :       continue;
     109              :     }
     110            0 :     if (!std::strcmp(argv[i], "--route") && i + 1 < argc) {
     111            0 :       route = argv[++i];
     112            0 :       continue;
     113              :     }
     114              :   }
     115              :   // ---- Positional args (fallback if flags not used)
     116            0 :   if (argc >= 2 && argv[1][0] != '-')
     117            0 :     ip = argv[1];
     118            0 :   if (argc >= 3 && argv[2][0] != '-') {
     119            0 :     try {
     120            0 :       port = std::stoi(argv[2]);
     121            0 :     } catch (...) {
     122            0 :     }
     123              :   }
     124              : 
     125            0 :   const std::string address = ip + ":" + std::to_string(port);
     126            0 :   const std::string endpoint = "tcp://" + address;
     127            0 :   std::cerr << "[SMOKE-V2] connecting to " << endpoint << " route=" << route << "\n";
     128              : 
     129            0 :   DaphneV3Interface iface(address, route);
     130              : 
     131            0 :   GOOGLE_PROTOBUF_VERIFY_VERSION;
     132              : 
     133              :   // ---- Build ConfigureRequest (same payload you used before)
     134            0 :   ConfigureRequest cfg;
     135            0 :   cfg.set_daphne_address(ip);
     136            0 :   cfg.set_slot(0);
     137            0 :   cfg.set_timeout_ms(500);
     138            0 :   cfg.set_biasctrl(1300);
     139            0 :   cfg.set_self_trigger_threshold(0x1F40);
     140            0 :   cfg.set_self_trigger_xcorr(0x68);
     141            0 :   cfg.set_tp_conf(0x0010DB35);
     142            0 :   cfg.set_compensator(0xFFFFFFFFFFull);
     143            0 :   cfg.set_inverters(0xFF00000000ull);
     144              : 
     145            0 :   for (uint32_t ch = 0; ch < 40; ++ch) {
     146            0 :     auto* c = cfg.add_channels();
     147            0 :     c->set_id(ch);
     148            0 :     c->set_trim(0);
     149            0 :     c->set_offset(2275);
     150            0 :     c->set_gain(1);
     151              :   }
     152            0 :   for (uint32_t afe = 0; afe < 5; ++afe) {
     153            0 :     auto* a = cfg.add_afes();
     154            0 :     a->set_id(afe);
     155            0 :     a->set_attenuators(1600);
     156            0 :     a->set_v_bias(0);
     157            0 :     a->mutable_adc()->set_resolution(true);
     158            0 :     a->mutable_adc()->set_output_format(true);
     159            0 :     a->mutable_adc()->set_sb_first(false);
     160            0 :     a->mutable_pga()->set_lpf_cut_frequency(4);
     161            0 :     a->mutable_pga()->set_integrator_disable(true);
     162            0 :     a->mutable_pga()->set_gain(0);
     163            0 :     a->mutable_lna()->set_clamp(0);
     164            0 :     a->mutable_lna()->set_gain(2);
     165            0 :     a->mutable_lna()->set_integrator_disable(true);
     166              :   }
     167              : 
     168              :   // ---- Wrap in V2 envelope
     169            0 :   ControlEnvelopeV2 req;
     170            0 :   req.set_version(2);
     171            0 :   req.set_dir(DIR_REQUEST);
     172            0 :   req.set_type(MT2_CONFIGURE_FE_REQ);
     173            0 :   req.set_payload(cfg.SerializeAsString());
     174            0 :   {
     175            0 :     auto [task_id, msg_id] = next_ids();
     176            0 :     req.set_task_id(task_id);
     177            0 :     req.set_msg_id(msg_id);
     178            0 :     req.set_timestamp_ns(now_ns());
     179            0 :     if (!route.empty())
     180            0 :       req.set_route(route);
     181              :   }
     182              : 
     183            0 :   try {
     184              :     // zmq::context_t ctx(1);
     185              :     // zmq::socket_t  sock(ctx, zmq::socket_type::dealer);
     186              :     // sock.set(zmq::sockopt::routing_id, "zmq-config-smoke-v2");
     187              :     // sock.set(zmq::sockopt::rcvtimeo, 4000);
     188              :     // sock.set(zmq::sockopt::sndtimeo, 4000);
     189              :     // sock.connect(endpoint);
     190              : 
     191              :     // send
     192              :     // {
     193              :     //   std::string bytes = req.SerializeAsString();
     194              :     //   zmq::message_t msg(bytes.size());
     195              :     //   std::memcpy(msg.data(), bytes.data(), bytes.size());
     196              :     //   if (!sock.send(msg, zmq::send_flags::none)) {
     197              :     //     std::cerr << "send() timed out\n"; return 2;
     198              :     //   }
     199              :     // }
     200              : 
     201              :     // // recv
     202              :     // auto frames = recv_multipart(sock);
     203              :     // const zmq::message_t& payload = frames.back();
     204              : 
     205              :     // ControlEnvelopeV2 rep;
     206              :     // if (!rep.ParseFromArray(payload.data(), static_cast<int>(payload.size()))) {
     207              :     //   std::cerr << "Failed to parse ControlEnvelopeV2 reply\n"; return 3;
     208              :     // }
     209              : 
     210              :     // // validate V2 transport
     211              :     // bool ok_dir  = (rep.dir()  == DIR_RESPONSE);
     212              :     // bool ok_type = (rep.type() == MT2_CONFIGURE_FE_RESP);
     213              :     // bool ok_tid  = (rep.task_id()   == req.task_id());
     214              :     // bool ok_corr = (rep.correl_id() == req.msg_id());
     215              :     // if (!ok_dir || !ok_type || !ok_tid || !ok_corr) {
     216              :     //   std::cerr << "Correlation/type mismatch:"
     217              :     //             << "\n  dir:  got " << rep.dir()  << " expect " << DIR_RESPONSE
     218              :     //             << "\n  type: got " << rep.type() << " expect " << MT2_CONFIGURE_FE_RESP
     219              :     //             << "\n  task: got " << rep.task_id()  << " expect " << req.task_id()
     220              :     //             << "\n  corr: got " << rep.correl_id()<< " expect " << req.msg_id()
     221              :     //             << "\n";
     222              :     //   return 4;
     223              :     // }
     224              : 
     225              :     // // decode payload
     226              :     // ConfigureResponse resp;
     227              :     // if (!resp.ParseFromString(rep.payload())) {
     228              :     //   std::cerr << "Failed to parse ConfigureResponse\n"; return 5;
     229              :     // }
     230              : 
     231            0 :     auto resp = iface.send<ConfigureResponse>(cfg.SerializeAsString(), MT2_CONFIGURE_FE_REQ, MT2_CONFIGURE_FE_RESP);
     232              : 
     233              :     // std::cout << "[V2 meta]\n";
     234              :     // std::cout << "  task_id      : " << rep.task_id() << "\n";
     235              :     // std::cout << "  msg_id       : " << rep.msg_id() << "\n";
     236              :     // std::cout << "  correl_id    : " << rep.correl_id() << "\n";
     237              :     // std::cout << "  timestamp_ns : " << rep.timestamp_ns() << "\n";
     238              :     // if (!rep.route().empty())
     239              :     //   std::cout << "  route        : " << rep.route() << "\n";
     240              :     // std::cout << "\n";
     241            0 :     std::cout << "Success: " << std::boolalpha << resp.success() << "\n";
     242            0 :     std::cout << "Message:\n" << resp.message() << "\n";
     243              : 
     244            0 :     google::protobuf::ShutdownProtobufLibrary();
     245            0 :     return resp.success() ? 0 : 6;
     246              : 
     247            0 :   } catch (const std::exception& e) {
     248            0 :     std::cerr << "Exception: " << e.what() << "\n";
     249            0 :     return 7;
     250            0 :   }
     251            0 : }
        

Generated by: LCOV version 2.0-1