LDMX Software
ConfigurePythonTest.cxx
1
2#include <catch2/catch_approx.hpp>
3#include <catch2/catch_test_macros.hpp>
4#include <catch2/matchers/catch_matchers_string.hpp>
5#include <fstream> // ifstream, ofstream
6
7#include "Framework/Configure/Python.h"
9#include "Framework/Process.h"
10
11using Catch::Approx;
12using Catch::Matchers::ContainsSubstring;
13
14namespace framework {
15namespace test {
16
23 public:
32 TestConfig(const std::string& name, framework::Process& process)
33 : framework::Producer(name, process) {
34 CHECK(name == "test_instance");
35 }
36
49 void configure(framework::config::Parameters& parameters) final override {
50 // Check parameters
51 CHECK(parameters.get<int>("test_int") == 9);
52 CHECK(parameters.get<double>("test_double") == Approx(7.7));
53 CHECK(parameters.get<std::string>("test_string") == "Yay!");
54
55 // Check dictionary
56 auto test_dict{parameters.get<framework::config::Parameters>("test_dict")};
57 CHECK(test_dict.get<int>("one") == 1);
58 CHECK(test_dict.get<double>("two") == 2.0);
59
60 // Check int vector
61 std::vector<int> int_vect{1, 2, 3};
62 auto test_int_vec{parameters.get<std::vector<int>>("test_int_vec")};
63 REQUIRE(test_int_vec.size() == int_vect.size());
64 for (std::size_t i{0}; i < test_int_vec.size(); i++)
65 CHECK(test_int_vec.at(i) == int_vect.at(i));
66
67 // Check double vec
68 std::vector<double> double_vec{0.1, 0.2, 0.3};
69 auto test_double_vec{
70 parameters.get<std::vector<double>>("test_double_vec")};
71 REQUIRE(test_double_vec.size() == double_vec.size());
72 for (std::size_t i{0}; i < test_double_vec.size(); i++)
73 CHECK(test_double_vec.at(i) == double_vec.at(i));
74
75 // Check string vector
76 std::vector<std::string> string_vec{"first", "second", "third"};
77 auto test_string_vec{
78 parameters.get<std::vector<std::string>>("test_string_vec")};
79 REQUIRE(test_string_vec.size() == string_vec.size());
80 for (std::size_t i{0}; i < test_string_vec.size(); i++)
81 CHECK(test_string_vec.at(i) == string_vec.at(i));
82
83 // check 2d vector
84 std::vector<std::vector<int>> twod_vec{
85 {11, 12, 13}, {21, 22}, {31, 32, 33, 34}};
86 auto test_2d_vec{
87 parameters.get<std::vector<std::vector<int>>>("test_2dlist")};
88 REQUIRE(test_2d_vec.size() == twod_vec.size());
89 for (std::size_t i{0}; i < twod_vec.size(); i++) {
90 REQUIRE(test_2d_vec.at(i).size() == twod_vec.at(i).size());
91 for (std::size_t j{0}; j < twod_vec.at(i).size(); j++) {
92 CHECK(test_2d_vec.at(i).at(j) == twod_vec.at(i).at(j));
93 }
94 }
95 }
96
97 // I don't do anything.
98 virtual void produce(framework::Event&) override {}
99};
100} // namespace test
101} // namespace framework
102
104
105
115TEST_CASE("Configure Python Test", "[Framework][functionality]") {
116 const std::string config_file_name{"config_python_test_config.py"};
117
118 // Arguments to pass to ConfigurePython constructor
119 char* args[1];
120
121 // Process handle
123
124 // Run a check of the python configuration class without arguments.
125 SECTION("No arguments to python script") {
127 "ldmxcfg.Process.last_process", config_file_name, args, 0)};
128 p = std::make_unique<framework::Process>(config);
129
130 CHECK(p->getPassName() == "test");
131 }
132
133 // Update the python config so we can pass the log frequency as a parameter.
134 std::ifstream in_file;
135 std::ofstream out_file;
136
137 in_file.open(config_file_name.c_str(), std::ios::in | std::ios::binary);
138
139 const std::string config_file_name_arg{
140 "/tmp/config_python_test_config_arg.py"};
141 out_file.open(config_file_name_arg, std::ios::out | std::ios::binary);
142 out_file << in_file.rdbuf();
143 out_file << "import sys" << std::endl;
144 out_file << "p.log_frequency = int(sys.argv[1])" << std::endl;
145
146 in_file.close();
147 out_file.close();
148
149 // Pass the log frequency as a parameter to the process and check that it
150 // was set correctly.
151 auto correct_log_freq{9000};
152 SECTION("Single argument to python script") {
153 args[0] = (char*)"9000";
154 auto config{framework::config::run("ldmxcfg.Process.last_process",
155 config_file_name_arg, args, 1)};
156 p = std::make_unique<framework::Process>(config);
157 CHECK(p->getLogFrequency() == correct_log_freq);
158 }
159}
Base classes for all user event processing components to extend.
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Class which represents the process under execution.
Implements an event buffer system for storing event data.
Definition Event.h:40
Class which represents the process under execution.
Definition Process.h:34
Base class for a module which produces a data product.
virtual void process(Event &event) final
Processing an event for a Producer is calling produce.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:26
Defines a test Producer to test the passing of configuration variables.
virtual void produce(framework::Event &) override
Process the event and put new data products into it.
TestConfig(const std::string &name, framework::Process &process)
Constructor.
void configure(framework::config::Parameters &parameters) final override
Configure function.
Parameters run(const std::string &root_object, const std::string &pythonScript, char *args[], int nargs)
run the python script and extract the parameters
Definition Python.cxx:300
All classes in the ldmx-sw project use this namespace.
std::unique_ptr< Process > ProcessHandle
A handle to the current process Used to pass a process from ConfigurePython to fire....
Definition Process.h:243