76 lines
4.4 KiB
C++
76 lines
4.4 KiB
C++
/* Проверяем настоящую очередь: конкуренция, переполнение, целостность и повторный запуск. */
|
|
#include "../transport/audio_diagnostics.cpp"
|
|
#include <cassert>
|
|
#include <cstdio>
|
|
#include <vector>
|
|
|
|
int main() {
|
|
debug_config_init(); debug_enable_console(0);
|
|
constexpr int producers = 4, perProducer = 20000;
|
|
std::vector<bool> seen(producers * perProducer);
|
|
std::atomic<int> done{0};
|
|
for (uint64_t i = 0; i < kCapacity; ++i) queue[i].sequence.store(i);
|
|
running = true;
|
|
// Сначала полное кольцо: producer обязан вернуть управление, потеря учтена.
|
|
for (uint64_t i = 0; i < kCapacity + 1; ++i) audio_diag_event(nullptr, AUDIO_DIAG_HOLE, AUDIO_DIAG_READ, i, 7);
|
|
assert(lost.load() == 1);
|
|
Event e;
|
|
for (uint64_t i = 0; i < kCapacity; ++i) {
|
|
assert(take(e)); assert(e.value == int64_t(i) && e.detail == 7);
|
|
}
|
|
assert(!take(e)); lost = 0;
|
|
// Граница секундного отчёта не обрывает карту времени; hole отделён от скачка оценки latency.
|
|
std::map<uintptr_t, Device> devices;
|
|
audio_capture_timing timing{1000000, 100000, 0, 480, 48000, 1, 0};
|
|
audio_diag_capture_clock(nullptr, &timing);
|
|
timing.first_us = 1014000; timing.latency_us = 96000;
|
|
audio_diag_capture_clock(nullptr, &timing);
|
|
timing.first_us = 1024000; timing.missing = 1;
|
|
audio_diag_capture_clock(nullptr, &timing);
|
|
while (take(e)) consume(e, devices);
|
|
auto& capture = devices[0];
|
|
assert(capture.captureSequence == 1440 && capture.captureFrames == 1440 && capture.captureBlocks == 3);
|
|
assert(capture.captureJumps == 1 && capture.captureMaxDelta == 4000 && capture.captureMinDelta == 0);
|
|
assert(capture.captureMissing == 480 && capture.captureEstimated == 0);
|
|
assert(capture.captureMinLatency == 96000 && capture.captureMaxLatency == 100000);
|
|
report(devices, now(CLOCK_MONOTONIC), 1.0);
|
|
timing.first_us = 1034000; timing.missing = 0; timing.measured = 0;
|
|
audio_diag_capture_clock(nullptr, &timing);
|
|
assert(take(e)); consume(e, devices);
|
|
assert(capture.captureJumps == 0 && capture.captureMissing == 0 && capture.captureEstimated == 1);
|
|
assert(capture.captureSequence == 1920 && capture.captureBlocks == 1 && capture.captureFrames == 480);
|
|
// Отсутствующий timestamp не превращается в измеренную нулевую задержку.
|
|
audio_playback_timing output{30000, 1000, 1200, 48000, 1};
|
|
audio_diag_playback_clock(nullptr, &output);
|
|
output.latency_us = -1000; output.frames = 960;
|
|
audio_diag_playback_clock(nullptr, &output);
|
|
output.latency_us = 999999; output.measured = 0;
|
|
audio_diag_playback_clock(nullptr, &output);
|
|
while (take(e)) consume(e, devices);
|
|
assert(capture.playbackBlocks == 3 && capture.playbackFrames == 3120 && capture.playbackMeasured == 2);
|
|
assert(capture.playbackMinLatency == -1000 && capture.playbackMaxLatency == 30000);
|
|
assert(capture.playbackMaxBlock == 25000 && capture.playbackMaxConverter == 1000);
|
|
report(devices, now(CLOCK_MONOTONIC), 1.0);
|
|
assert(capture.playbackBlocks == 0 && capture.playbackMeasured == 0 && capture.playbackMaxBlock == 0);
|
|
std::vector<std::thread> workers;
|
|
for (int p = 0; p < producers; ++p) workers.emplace_back([p, &done]() {
|
|
for (int i = 0; i < perProducer; ++i)
|
|
audio_diag_event(nullptr, AUDIO_DIAG_HOLE, AUDIO_DIAG_READ, p * perProducer + i, p);
|
|
++done;
|
|
});
|
|
uint64_t received = 0;
|
|
while (done.load() != producers || readPosition != writePosition.load()) {
|
|
if (!take(e)) { std::this_thread::yield(); continue; }
|
|
assert(e.value >= 0 && e.value < producers * perProducer);
|
|
assert(e.kind == AUDIO_DIAG_HOLE && e.stage == AUDIO_DIAG_READ && e.value / perProducer == e.detail);
|
|
assert(e.wall && e.cpu && e.tid && !seen[e.value]);
|
|
seen[e.value] = true; ++received;
|
|
}
|
|
for (auto& worker : workers) worker.join();
|
|
assert(received + lost.load() == producers * perProducer);
|
|
running = false;
|
|
// Lifecycle не оставляет joinable-поток и очищает очередь между сеансами.
|
|
for (int i = 0; i < 2; ++i) { audio_diag_start(); audio_diag_event(nullptr, AUDIO_DIAG_OPEN, -1, 1, 48000); audio_diag_stop(); }
|
|
puts("test_audio_diagnostics: bounded MPSC, concurrent integrity and restart PASS");
|
|
}
|