Browse Source

Test Qt voice file validation and decoder cancellation

master
evgeny 2 days ago
parent
commit
05476fb102
  1. 5
      tools/chatgui/CMakeLists.txt
  2. 45
      tools/chatgui/tests/test_voice_file.cpp

5
tools/chatgui/CMakeLists.txt

@ -262,6 +262,11 @@ add_executable(test_ptt_key_chord tests/test_ptt_key_chord.cpp)
target_link_libraries(test_ptt_key_chord PRIVATE ${QT_CORE}) target_link_libraries(test_ptt_key_chord PRIVATE ${QT_CORE})
add_test(NAME test_ptt_key_chord COMMAND test_ptt_key_chord) add_test(NAME test_ptt_key_chord COMMAND test_ptt_key_chord)
add_executable(test_voice_file tests/test_voice_file.cpp src/voiceplayback.cpp src/sound_manager.cpp transport/miniaudio_impl.c)
target_include_directories(test_voice_file PRIVATE ${UTUN_INCLUDE_DIRS})
target_link_libraries(test_voice_file PRIVATE ${QT_LIBS} utun pthread ${CMAKE_DL_LIBS})
add_test(NAME test_voice_file COMMAND test_voice_file)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux") if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
add_executable(test_ptt_portal tests/test_ptt_portal.cpp src/ptt_portal.cpp) add_executable(test_ptt_portal tests/test_ptt_portal.cpp src/ptt_portal.cpp)
target_link_libraries(test_ptt_portal PRIVATE ${QT_DBUS} ${QT_TEST_LIB} utun pthread) target_link_libraries(test_ptt_portal PRIVATE ${QT_DBUS} ${QT_TEST_LIB} utun pthread)

45
tools/chatgui/tests/test_voice_file.cpp

@ -0,0 +1,45 @@
/* Реальное воспроизведение: строгий формат и отмена асинхронного декодирования. */
#include "../src/voiceplayback.h"
#include <QCoreApplication>
#include <QTemporaryDir>
#include <QFile>
#include <QElapsedTimer>
#include <QThread>
extern "C" {
#include "../../../lib/debug_config.h"
#include "../../../src/media_async/voice_file.h"
}
#define REQUIRE(value) do { if (!(value)) { qFatal("voice file check line=%d", __LINE__); } } while (0)
int main(int argc, char** argv) {
QCoreApplication app(argc, argv);
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR);
QTemporaryDir dir; REQUIRE(dir.isValid());
QString path = dir.filePath("voice.opus");
std::vector<int16_t> source(48000), decoded;
attachment_info info = {}; int rate = 0, channels = 0; float duration = 0;
REQUIRE(!voice_file_encode(source.data(), source.size(), 48000, 1, 1, qPrintable(path), &info));
REQUIRE(VoicePlayer::decodeOpusFile(path, decoded, rate, channels, duration) == 50);
REQUIRE(decoded.size() == 48000 && rate == 48000 && channels == 1 && duration == 1);
QFile file(path); REQUIRE(file.open(QIODevice::ReadOnly));
const auto valid = file.readAll(); file.close();
auto reject = [&](const QByteArray& data) {
REQUIRE(file.open(QIODevice::WriteOnly | QIODevice::Truncate)); REQUIRE(file.write(data) == data.size()); file.close();
REQUIRE(VoicePlayer::decodeOpusFile(path, decoded, rate, channels, duration) < 0 && duration == 0);
};
reject(valid.left(10)); // Обрезанный заголовок.
auto bad = valid; bad[8] = 3; reject(bad); // Число каналов.
bad = valid; bad[10] = 0; bad[11] = 0; reject(bad); // Размер кадра.
reject(valid.left(valid.size() - 2)); // Нет end marker.
reject(valid + "x"); // Посторонние байты после marker.
reject(valid.left(14)); // Обрезанный пакет.
REQUIRE(file.open(QIODevice::WriteOnly | QIODevice::Truncate)); REQUIRE(file.write(valid) == valid.size()); file.close();
bool called = false;
VoicePlayer::playOpusFile(path, &app, [&](float) { called = true; });
REQUIRE(VoicePlayer::isPreparing()); VoicePlayer::cancelPending();
QElapsedTimer deadline; deadline.start();
while (VoicePlayer::isPreparing() && deadline.elapsed() < 5000) { app.processEvents(); QThread::msleep(1); }
REQUIRE(!VoicePlayer::isPreparing() && !called);
qInfo("test_voice_file: Opus round-trip, malformed files and asynchronous cancellation PASS");
return 0;
}
Loading…
Cancel
Save