Rename kamil_adc to rph_radar and fix its data path
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
#include "capture_file_writer.h"
|
||||
#include "channel_bundle_support.hpp"
|
||||
#include "data_preprocessor.hpp"
|
||||
#include "locator/tcp_server.hpp"
|
||||
@@ -7,6 +6,8 @@
|
||||
#include "runtime_wait.hpp"
|
||||
#include "shm_ring.hpp"
|
||||
#include "tty_protocol_writer.h"
|
||||
#include "switch_sequencer.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -307,40 +308,6 @@ void test_cosine_notch_taper() {
|
||||
}
|
||||
}
|
||||
|
||||
void test_csv_failures(const Workspace& workspace) {
|
||||
const auto csv = workspace.path / "capture.csv";
|
||||
const auto spool = workspace.path / "capture.capture_spool.bin";
|
||||
CaptureFileWriter writer(csv.string(), (workspace.path / "capture.svg").string(), "", "");
|
||||
writer.initialize_csv(2, false);
|
||||
CapturePacket packet{.ch1 = {1, 2}, .ch2 = {3, 4}, .di1 = {}};
|
||||
auto invalid_packet = packet;
|
||||
invalid_packet.ch2.pop_back();
|
||||
expect_error([&] { writer.append_csv_packet(invalid_packet); });
|
||||
require(std::filesystem::file_size(spool) == 16, "invalid packet partially changed the spool");
|
||||
writer.append_csv_packet(packet);
|
||||
std::filesystem::remove(csv);
|
||||
std::filesystem::create_symlink("/dev/full", csv);
|
||||
expect_error([&] { writer.write({packet}, 1000, 10); });
|
||||
require(std::filesystem::file_size(spool) > 16, "failed CSV write deleted the recovery spool");
|
||||
std::filesystem::remove(csv);
|
||||
writer.write({packet}, 1000, 10);
|
||||
require(!std::filesystem::exists(spool), "successful CSV export retained the spool");
|
||||
std::ifstream csv_input(csv);
|
||||
const std::string csv_text((std::istreambuf_iterator<char>(csv_input)), {});
|
||||
require(csv_text.find("1.000000000,3.000000000") != std::string::npos,
|
||||
"CSV retry lost channel samples");
|
||||
writer.initialize_csv(2, false);
|
||||
std::ofstream(spool, std::ios::binary | std::ios::app).put('x');
|
||||
expect_error([&] { writer.write({}, 1000, 10); });
|
||||
require(std::filesystem::exists(spool), "truncated packet header deleted the spool");
|
||||
writer.initialize_csv(2, false);
|
||||
const std::array<std::uint64_t, 4> corrupt_packet{0, 2, 0xffffffffffffffffULL, 0};
|
||||
std::ofstream(spool, std::ios::binary | std::ios::app).write(
|
||||
reinterpret_cast<const char*>(corrupt_packet.data()), sizeof(corrupt_packet));
|
||||
expect_error([&] { writer.write({}, 1000, 10); });
|
||||
require(std::filesystem::exists(spool), "oversized packet count deleted the spool");
|
||||
}
|
||||
|
||||
void test_asset_reload_preserves_data(const Workspace& workspace) {
|
||||
const auto save = [&](const char* name, float sample) {
|
||||
return save_bundle(workspace, name, {.traces = {
|
||||
@@ -497,10 +464,77 @@ void test_locator_packet_errors() {
|
||||
for (unsigned iteration = 0; iteration < 30; ++iteration) { server.start(); server.stop(); }
|
||||
}
|
||||
|
||||
void test_tty_sweep_overflow(const Workspace& workspace) {
|
||||
TtyProtocolWriter writer((workspace.path / "overflow_tty").string(), 32'096);
|
||||
const int fd = ::open(writer.path().c_str(), O_RDONLY | O_NONBLOCK);
|
||||
require(fd >= 0, "Cannot open test PTY");
|
||||
std::vector<std::uint16_t> words(8'000, 42);
|
||||
for (std::uint64_t id = 1; id <= 100; ++id) {
|
||||
writer.enqueue_sweep(words, {id, id, id * 100, id * 100 + 50, 1, 2, false});
|
||||
}
|
||||
require(writer.stats().ring_overflows > 0, "test did not overflow the queue");
|
||||
std::vector<std::uint8_t> received;
|
||||
std::uint64_t last_id = 0;
|
||||
const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2);
|
||||
while (last_id < 100 && std::chrono::steady_clock::now() < deadline) {
|
||||
std::array<std::uint8_t, 8192> chunk{};
|
||||
const auto n = ::read(fd, chunk.data(), chunk.size());
|
||||
if (n > 0) { received.insert(received.end(), chunk.begin(), chunk.begin() + n); }
|
||||
while (received.size() >= 16'048) {
|
||||
require(std::memcmp(received.data(), "RPH1", 4) == 0, "overflow truncated a sweep header");
|
||||
const auto value = [&](std::size_t at, unsigned size) {
|
||||
std::uint64_t result = 0;
|
||||
for (unsigned i = 0; i < size; ++i) { result |= std::uint64_t{received[at + i]} << (8U * i); }
|
||||
return result;
|
||||
};
|
||||
require(value(4, 4) == 16'000 && value(8, 8) > last_id, "lost framing or source order");
|
||||
last_id = value(8, 8);
|
||||
require(value(16, 8) == last_id && value(24, 8) == last_id * 100 &&
|
||||
value(32, 8) == last_id * 100 + 50 && value(40, 2) == 1 && value(42, 2) == 2,
|
||||
"sweep lost source identity, timing, or combo");
|
||||
require(received[48] == 42 && received[16'047] == 0, "corrupt point payload");
|
||||
received.erase(received.begin(), received.begin() + 16'048);
|
||||
}
|
||||
if (n <= 0) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); }
|
||||
}
|
||||
::close(fd);
|
||||
require(last_id == 100 && received.empty(), "latest complete sweep did not arrive");
|
||||
}
|
||||
|
||||
void test_switch_backlog() {
|
||||
drivers::H7992MinimalDriverSettings settings{.mode = config::DriverMode::Mock};
|
||||
rph::SwitchSequencer sequencer({.combos = {{0, 0}, {0, 1}}},
|
||||
std::make_unique<drivers::H7992MinimalDriver>(settings),
|
||||
std::make_unique<drivers::H7992MinimalDriver>(settings));
|
||||
sequencer.open();
|
||||
sequencer.session_started();
|
||||
require(!sequencer.on_sweep_end(false), "duration limit requested a new session");
|
||||
require(sequencer.current_combo().output_pos == 0 && sequencer.cycle_id() == 1,
|
||||
"duration limit switched hardware before the physical sweep ended");
|
||||
require(sequencer.on_sweep_end(), "GPIO change must request a new source session");
|
||||
for (unsigned i = 0; i < 10; ++i) {
|
||||
require(sequencer.current_dirty(), "queued pre-switch sweep incorrectly clean");
|
||||
require(!sequencer.on_sweep_end(), "dirty backlog requested another session");
|
||||
require(sequencer.current_combo().output_pos == 1 && sequencer.cycle_id() == 1,
|
||||
"dirty backlog advanced the combo or cycle");
|
||||
}
|
||||
sequencer.session_started();
|
||||
require(!sequencer.current_dirty(), "new source session must permit a complete sweep");
|
||||
sequencer.on_sweep_end();
|
||||
require(sequencer.current_combo().output_pos == 0 && sequencer.cycle_id() == 2,
|
||||
"clean cycle did not advance");
|
||||
rph::SwitchSequencer single({.combos = {{0, 0}}},
|
||||
std::make_unique<drivers::H7992MinimalDriver>(settings),
|
||||
std::make_unique<drivers::H7992MinimalDriver>(settings));
|
||||
single.open(); single.session_started();
|
||||
require(!single.on_sweep_end() && single.cycle_id() == 2 && !single.current_dirty(),
|
||||
"unchanged combination restarted its source or stopped advancing cycles");
|
||||
}
|
||||
|
||||
void test_unread_tty_shutdown(const Workspace& workspace) {
|
||||
TtyProtocolWriter writer((workspace.path / "tty").string(), 160'000);
|
||||
TtyProtocolWriter writer((workspace.path / "tty").string(), 160'048);
|
||||
const std::vector<std::uint16_t> words(80'000, 42);
|
||||
writer.enqueue_encoded_frames(words.data(), words.size() / 4U);
|
||||
writer.enqueue_sweep(words, {1, 1, 100, 200});
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
writer.shutdown();
|
||||
@@ -524,9 +558,10 @@ int main(int argc, char** argv) {
|
||||
test_acquisition_identity();
|
||||
test_interruptible_wait();
|
||||
test_cosine_notch_taper();
|
||||
test_csv_failures(workspace);
|
||||
test_locator_packet_errors();
|
||||
test_tty_sweep_overflow(workspace);
|
||||
test_switch_backlog();
|
||||
test_unread_tty_shutdown(workspace);
|
||||
test_locator_packet_errors();
|
||||
std::cout << "native regressions passed (10,000 decoder mutations; 20,000 concurrent ring frames)\n";
|
||||
} catch (const std::exception& error) {
|
||||
std::cerr << "native regression failed: " << error.what() << '\n';
|
||||
|
||||
Reference in New Issue
Block a user