File indexing completed on 2026-10-20 08:45:51
0001 #include <cassert>
0002 #include <cstdlib>
0003 #include <filesystem>
0004 #include <fstream>
0005 #include <stdexcept>
0006 #include <string>
0007 #include <unistd.h>
0008
0009 #include "EventTiming.hh"
0010 #include "SEventConfig.hh"
0011 #include "config.h"
0012
0013 namespace
0014 {
0015 namespace fs = std::filesystem;
0016
0017 void WriteText(const fs::path& path, const std::string& text)
0018 {
0019 std::ofstream output(path, std::ios::binary | std::ios::trunc);
0020 assert(output);
0021 output << text;
0022 output.close();
0023 assert(output);
0024 }
0025
0026 void Require(bool condition, const char* message)
0027 {
0028 if (!condition)
0029 throw std::runtime_error(message);
0030 }
0031 }
0032
0033 int main()
0034 {
0035 const fs::path directory = fs::temp_directory_path() /
0036 ("ConfigTest-" + std::to_string(static_cast<long long>(::getpid())));
0037 const fs::path output_dir = directory / "output";
0038 fs::remove_all(directory);
0039 fs::create_directories(directory);
0040
0041 WriteText(
0042 directory / "timing.json",
0043 "{\n"
0044 " \"event\": {\"output_dir\": \"" +
0045 output_dir.string() + "\"},\n"
0046 " \"event_timing\": {\n"
0047 " \"output\": \"events.csv\",\n"
0048 " \"profile\": {\n"
0049 " \"enabled\": true,\n"
0050 " \"output\": \"event_timing_profile_%03d.csv\",\n"
0051 " \"path_index\": 7\n"
0052 " }\n"
0053 " }\n"
0054 "}\n");
0055
0056 setenv("SIMPHONY_CONFIG_DIR", directory.c_str(), 1);
0057 EventTimingProfile::Clear();
0058 const simphony::Config config("timing");
0059
0060 assert(config.event_timing_output == output_dir / "events.csv");
0061 assert(config.event_timing_profile_enabled);
0062 assert(config.event_timing_profile_output == output_dir / "event_timing_profile_%03d.csv");
0063 assert(config.event_timing_profile_path_index == 7);
0064 assert(EventTimingProfile::Enabled());
0065 assert(EventTimingProfile::Path() == output_dir / "event_timing_profile_007.csv");
0066 assert(EventTimingRecorder(config.event_timing_output).enabled());
0067 const std::vector<EventTimingProfileRecord> records = EventTimingProfile::Records();
0068 assert(records.size() == 1u);
0069 assert(records.front().name == "EventTimingProfile__Configure");
0070 assert(records.front().sample.has(EventTimingCapture::Monotonic));
0071
0072 WriteText(directory / "omitted.json", "{}\n");
0073 const simphony::Config omitted("omitted");
0074 assert(omitted.event_timing_output.empty());
0075 assert(!EventTimingRecorder(omitted.event_timing_output).enabled());
0076 assert(!EventTimingProfile::Enabled());
0077
0078 WriteText(
0079 directory / "empty.json",
0080 "{\"event_timing\": {\"output\": \"\", \"profile\": {\"enabled\": false}}}\n");
0081 const simphony::Config empty("empty");
0082 assert(empty.event_timing_output.empty());
0083 assert(!EventTimingRecorder(empty.event_timing_output).enabled());
0084 assert(!EventTimingProfile::Enabled());
0085
0086 WriteText(
0087 directory / "bad-timing.json",
0088 "{\"event_timing\": {\"profile\": {\"path_index\": \"seven\"}}}\n");
0089 bool rejected_bad_index = false;
0090 try
0091 {
0092 (void)simphony::Config("bad-timing");
0093 }
0094 catch (const std::runtime_error&)
0095 {
0096 rejected_bad_index = true;
0097 }
0098 assert(rejected_bad_index);
0099
0100 WriteText(directory / "ser-none.json", "{\"ser\": {\"interval\": 8, \"hint\": \"none\"}}\n");
0101 const simphony::Config ser_none("ser-none");
0102 Require(ser_none.ser_hint == simphony::SerHint::None, "ser.hint none was not parsed");
0103 Require(SEventConfig::_SerHint == 0, "ser.hint none was not applied");
0104
0105 WriteText(directory / "ser-bounce.json", "{\"ser\": {\"interval\": 8, \"hint\": \"bounce\"}}\n");
0106 const simphony::Config ser_bounce("ser-bounce");
0107 Require(ser_bounce.ser_hint == simphony::SerHint::Bounce, "ser.hint bounce was not parsed");
0108 Require(SEventConfig::_SerHint == 1, "ser.hint bounce was not applied");
0109
0110 for (const auto& [name, value] : std::vector<std::pair<std::string, std::string>>{
0111 {"bad-ser-number", "2"},
0112 {"bad-ser-name", "\"boundary-wavelength\""},
0113 })
0114 {
0115 WriteText(directory / (name + ".json"), "{\"ser\": {\"hint\": " + value + "}}\n");
0116 bool rejected_bad_hint = false;
0117 try
0118 {
0119 (void)simphony::Config(name);
0120 }
0121 catch (const std::runtime_error&)
0122 {
0123 rejected_bad_hint = true;
0124 }
0125 Require(rejected_bad_hint, "invalid ser.hint was accepted");
0126 }
0127
0128 EventTimingProfile::Configure(false);
0129 unsetenv("SIMPHONY_CONFIG_DIR");
0130 fs::remove_all(directory);
0131 return 0;
0132 }