Reimplemented unit tests, ...

* Reimplemented unit tests and simplified addition of new tests
* Minimal support of Qt is now 5.15
This commit is contained in:
TrickyLeifa 2024-05-17 23:54:41 +02:00
parent 0500a54260
commit 657145035c
14 changed files with 93 additions and 252 deletions

View File

@ -11,8 +11,7 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
option(AO_BUILD_TESTS "Build test programs" OFF)
option(AO_ENABLE_BASS "Enable BASS audio library" ON)
option(AO_BUILD_TESTS "Build test programs" ON)
option(AO_ENABLE_DISCORD_RPC "Enable Discord Rich Presence" ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
@ -115,12 +114,7 @@ endif()
target_include_directories(Attorney_Online PRIVATE src lib)
target_link_directories(Attorney_Online PRIVATE lib)
target_link_libraries(Attorney_Online PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Concurrent Qt${QT_VERSION_MAJOR}::WebSockets Qt${QT_VERSION_MAJOR}::UiTools)
if(AO_ENABLE_BASS)
target_compile_definitions(Attorney_Online PRIVATE AO_ENABLE_BASS)
target_link_libraries(Attorney_Online PRIVATE bass bassmidi bassopus)
endif()
target_link_libraries(Attorney_Online PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Concurrent Qt${QT_VERSION_MAJOR}::WebSockets Qt${QT_VERSION_MAJOR}::UiTools bass bassopus bassmidi)
if(AO_ENABLE_DISCORD_RPC)
target_compile_definitions(Attorney_Online PRIVATE AO_ENABLE_DISCORD_RPC)
@ -128,5 +122,6 @@ if(AO_ENABLE_DISCORD_RPC)
endif()
if(AO_BUILD_TESTS)
add_subdirectory(test)
# add_subdirectory(test)
endif()
add_subdirectory(test)

View File

@ -9,9 +9,6 @@ Courtroom::Courtroom(AOApplication *p_ao_app)
this->setWindowFlags((this->windowFlags() | Qt::CustomizeWindowHint) & ~Qt::WindowMaximizeButtonHint);
ao_app->initBASS();
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) // Needed for pre-5.10 RNG stuff
qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
#endif
keepalive_timer = new QTimer(this);
keepalive_timer->start(45000);
@ -2947,13 +2944,8 @@ void Courtroom::do_screenshake()
for (int frame = 0; frame < maxframes; frame++)
{
double fraction = double(frame * frequency) / duration;
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
int rand_x = max_deviation * (2 * (qrand() / (float)RAND_MAX) - 1) + 1;
int rand_y = max_deviation * (2 * (qrand() / (float)RAND_MAX) - 1) + 1;
#else
int rand_x = QRandomGenerator::system()->bounded(-max_deviation, max_deviation);
int rand_y = QRandomGenerator::system()->bounded(-max_deviation, max_deviation);
#endif
screenshake_animation->setKeyValueAt(fraction, QPoint(pos_default.x() + rand_x, pos_default.y() + rand_y));
}
screenshake_animation->setEndValue(pos_default);
@ -3144,12 +3136,8 @@ void Courtroom::initialize_chatbox()
}
QFontMetrics fm(ui_vp_showname->font());
// Gotta support the slow paced ubuntu 18 STUCK IN 5.9.5!!
#if QT_VERSION > QT_VERSION_CHECK(5, 11, 0)
int fm_width = fm.horizontalAdvance(ui_vp_showname->text());
#else
int fm_width = fm.boundingRect((ui_vp_showname->text())).width();
#endif
if (extra_width > 0)
{
QString current_path = ui_vp_chatbox->image().left(ui_vp_chatbox->image().lastIndexOf('.'));
@ -4699,7 +4687,7 @@ void Courtroom::on_ooc_return_pressed()
if (ooc_message.startsWith("/load_case"))
{
QStringList command = ooc_message.split(" ", AOSplitBehaviorFlags::SkipEmptyParts);
QStringList command = ooc_message.split(" ", Qt::SkipEmptyParts);
QDir casefolder(get_base_path() + "/cases");
if (!casefolder.exists())
{
@ -4795,7 +4783,7 @@ void Courtroom::on_ooc_return_pressed()
}
else if (ooc_message.startsWith("/save_case"))
{
QStringList command = ooc_message.split(" ", AOSplitBehaviorFlags::SkipEmptyParts);
QStringList command = ooc_message.split(" ", Qt::SkipEmptyParts);
QDir casefolder(get_base_path() + "cases");
if (!casefolder.exists())
{
@ -5615,11 +5603,8 @@ void Courtroom::music_random()
{
return;
}
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
on_music_list_double_clicked(clist.at(qrand() % clist.length()), 1);
#else
on_music_list_double_clicked(clist.at(QRandomGenerator::global()->bounded(0, clist.length())), 1);
#endif
}
void Courtroom::music_list_expand_all()
@ -6028,11 +6013,7 @@ void Courtroom::on_text_color_changed(int p_color)
markdown_end = markdown_start;
}
int start = ui_ic_chat_message->selectionStart();
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
int end = ui_ic_chat_message->selectionEnd() + 1;
#else
int end = ui_ic_chat_message->selectedText().length() + 1;
#endif
ui_ic_chat_message->setCursorPosition(start);
ui_ic_chat_message->insert(markdown_start);

View File

@ -45,6 +45,7 @@
#include <QBrush>
#include <QDebug>
#include <QDesktopServices>
#include <QElapsedTimer>
#include <QFileDialog>
#include <QFont>
#include <QInputDialog>
@ -52,10 +53,7 @@
#include <QMessageBox>
#include <QParallelAnimationGroup>
#include <QPropertyAnimation>
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
#include <QRandomGenerator> //added in Qt 5.10
#endif
#include <QElapsedTimer>
#include <QRandomGenerator>
#include <QRegularExpression>
#include <QScrollBar>
#include <QTextBoundaryFinder>

View File

@ -3,12 +3,6 @@
#include <QMap>
#include <QString>
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
using AOSplitBehaviorFlags = QString::SplitBehaviorFlags;
#else
using AOSplitBehaviorFlags = Qt::SplitBehaviorFlags;
#endif
enum ServerConnectionType
{
TcpServerConnection,

View File

@ -95,7 +95,7 @@ void DemoServer::recv_data()
{
QString in_data = QString::fromUtf8(client_sock->readAll());
const QStringList packet_list = in_data.split("%", AOSplitBehaviorFlags::SkipEmptyParts);
const QStringList packet_list = in_data.split("%", Qt::SkipEmptyParts);
for (const QString &packet : packet_list)
{
QStringList f_contents;

View File

@ -6,11 +6,8 @@ bool AOLineEditFilter::eventFilter(QObject *obj, QEvent *event)
if (event->type() == QEvent::FocusOut && lineEdit != nullptr && preserve_selection)
{ // lost focus
int start = lineEdit->selectionStart();
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
int len = lineEdit->selectionLength();
#else
int len = lineEdit->selectedText().length();
#endif
if (start != -1 && len != -1)
{
lineEdit->setSelection(start, len);

View File

@ -174,19 +174,12 @@ void Lobby::loadUI()
if (!l_changelog.open(QFile::ReadOnly))
{
qDebug() << "Unable to locate changelog file. Does it even exist?";
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
ui_game_changelog_text->setMarkdown(l_changelog_text);
#else
ui_game_changelog_text->setPlainText(l_changelog_text); // imperfect solution, but implementing Markdown
// ourselves for this edge case is out of scope
#endif
return;
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
ui_game_changelog_text->setMarkdown(l_changelog.readAll());
#else
ui_game_changelog_text->setPlainText((l_changelog.readAll()));
#endif
l_changelog.close();
QTabWidget *l_tabbar = findChild<QTabWidget *>("motd_changelog_tab");

View File

@ -78,7 +78,7 @@ void NetTcpConnection::onReadyRead()
return;
}
QStringList raw_packet_list = m_cached_data.split('%', AOSplitBehaviorFlags::SkipEmptyParts);
QStringList raw_packet_list = m_cached_data.split('%', Qt::SkipEmptyParts);
m_cached_data.clear();
for (QString raw_packet : raw_packet_list)
{

View File

@ -42,12 +42,8 @@ void ScrollText::setSeparator(QString separator)
void ScrollText::updateText()
{
timer.stop();
#if QT_VERSION > QT_VERSION_CHECK(5, 11, 0)
singleTextWidth = fontMetrics().horizontalAdvance(m_text);
#else
singleTextWidth = fontMetrics().boundingRect(_text).width();
#endif
singleTextWidth = fontMetrics().horizontalAdvance(m_text);
scrollEnabled = (singleTextWidth > width() - leftMargin * 2);
if (scrollEnabled)
@ -62,11 +58,7 @@ void ScrollText::updateText()
}
staticText.prepare(QTransform(), font());
#if QT_VERSION > QT_VERSION_CHECK(5, 11, 0)
wholeTextSize = QSize(fontMetrics().horizontalAdvance(staticText.text()), fontMetrics().height());
#else
wholeTextSize = QSize(fontMetrics().boundingRect(staticText.text()).width(), fontMetrics().height());
#endif
}
void ScrollText::paintEvent(QPaintEvent *)

View File

@ -1,20 +1,21 @@
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Widgets REQUIRED)
find_package(Catch2 REQUIRED)
project(tests LANGUAGES CXX C)
target_include_directories(test PRIVATE ../src)
target_link_directories(test PRIVATE ../lib)
target_link_libraries(test PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Widgets Catch2::Catch2)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Test REQUIRED)
add_executable(test
test_aopacket.cpp
test_caseloading.cpp
test_apng.cpp
../src/aopacket.h
../src/aopacket.cpp
)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(AO_ENABLE_BASS)
target_compile_definitions(Attorney_Online PRIVATE AO_ENABLE_BASS)
target_link_libraries(Attorney_Online PRIVATE bass bassmidi bassopus)
target_sources(test PRIVATE test_bass.cpp)
endif()
enable_testing(true)
set(SKIP_AUTOMOC ON)
function(ao_declare_test test_id)
message(STATUS "FOOBAR Adding test: ${test_id}")
message(STATUS "FOOBAR Source files: ${ARGN}")
add_executable(${test_id} ${ARGN})
target_include_directories(${test_id} PRIVATE ../src src)
target_link_directories(${test_id} PRIVATE ../lib)
target_link_libraries(${test_id} PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Test)
add_test(NAME ${test_id} COMMAND ${test_id})
endfunction()
ao_declare_test(test_aopacket test_aopacket.cpp ../src/aopacket.cpp)

View File

@ -1,51 +1,70 @@
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include "aopacket.h"
TEST_CASE("AOPacket construct", "[aopacket]")
#include <QString>
#include <QtTest/QTest>
class test_AOPacket : public QObject
{
// Parameters
QString packet_string = "CT#MY_OOC_NAME#/doc https://docs.google.com/document/d/123/edit##%";
Q_OBJECT
SECTION("Packet string")
private:
const QMap<QString, QString> SYMBOL_MAP{
{"#", "<num>"},
{"%", "<percent>"},
{"$", "<dollar>"},
{"&", "<and>"},
};
private Q_SLOTS:
void constructPacket_data()
{
AOPacket p(packet_string);
REQUIRE(p.to_string() == packet_string);
}
SECTION("Header and contents")
{
QStringList contents = {"MY_OOC_NAME", "/doc https://docs.google.com/document/d/123/edit#"};
AOPacket p("CT", contents);
REQUIRE(p.to_string() == packet_string);
}
}
QTest::addColumn<QString>("header");
QTest::addColumn<QStringList>("content");
QTest::addColumn<QString>("result");
TEST_CASE("AOPacket encode/decode", "[aopacket]")
{
// Parameters
QString packet_string = "CT#MY_OOC_NAME#/doc https://docs.google.com/document/d/%$&/edit##%";
QString good_encode = "CT#MY_OOC_NAME#/doc https://docs.google.com/document/d/<percent><dollar><and>/edit<num>#%";
SECTION("Bad encode/decode because packet string constructor splits the '#' after 'edit'")
{
AOPacket p(packet_string);
p.net_encode();
REQUIRE(p.to_string() != good_encode);
p.net_decode();
REQUIRE(p.to_string() == packet_string);
QTest::newRow("Basic Packet") << "CT" << QStringList{"MY_OOC_NAME", "/doc https://docs.google.com/document/d/123/edit"} << "CT#MY_OOC_NAME#/doc https://docs.google.com/document/d/123/edit#%";
}
SECTION("Good encode/decode with header and contents constructor")
void constructPacket()
{
QStringList contents = {"MY_OOC_NAME", "/doc https://docs.google.com/document/d/%$&/edit#"};
AOPacket p("CT", contents);
QFETCH(QString, header);
QFETCH(QStringList, content);
QFETCH(QString, result);
p.net_encode();
REQUIRE(p.to_string() == good_encode);
p.net_decode();
REQUIRE(p.to_string() == packet_string);
AOPacket packet(header, content);
QVERIFY(packet.toString(true) == result);
}
}
void encodeDecodeData_data()
{
QTest::addColumn<QString>("what");
QTest::addColumn<QString>("result");
QTest::addColumn<bool>("encode");
for (auto it = SYMBOL_MAP.begin(); it != SYMBOL_MAP.end(); ++it)
{
QTest::newRow(QString("Encode %1").arg(it.key()).toUtf8()) << it.key() << it.value() << true;
QTest::newRow(QString("Decode %1").arg(it.value()).toUtf8()) << it.value() << it.key() << false;
}
}
void encodeDecodeData()
{
QFETCH(QString, what);
QFETCH(QString, result);
QFETCH(bool, encode);
if (encode)
{
QVERIFY(AOPacket::encode(what) == result);
}
else
{
QVERIFY(AOPacket::decode(what) == result);
}
}
};
#include "test/test_aopacket.moc"
QTEST_MAIN(test_AOPacket)

View File

@ -1,67 +0,0 @@
#include <catch2/catch.hpp>
#include <QCoreApplication>
#include <QGuiApplication>
#include <QImageReader>
#include <QPixmap>
#include <QPluginLoader>
TEST_CASE("Support APNG Plugin", "[apng]")
{
// Check paths for libs
QCoreApplication::addLibraryPath(".");
QCoreApplication::addLibraryPath("lib");
// Either it's loaded from system or we load local
QPluginLoader apngPlugin("qapng");
apngPlugin.load();
INFO(QImageReader::supportedImageFormats().join(' ').toStdString());
REQUIRE(QImageReader::supportedImageFormats().contains("apng"));
}
TEST_CASE("Detect png animation", "[apng]")
{
// Required for QPixmap methods
int argc = 1;
char bin[] = "test";
char *argv[] = {bin};
QGuiApplication app(argc, argv);
// Instantiate reader
QImageReader reader;
SECTION("Decide format from content fails on apng")
{
reader.setFileName("snackoo.png");
reader.setDecideFormatFromContent(true);
REQUIRE(!reader.supportsAnimation());
REQUIRE(!QPixmap::fromImage(reader.read()).isNull());
}
SECTION("Auto detect fails on apng")
{
reader.setFileName("snackoo.png");
reader.setAutoDetectImageFormat(true);
REQUIRE(!reader.supportsAnimation());
REQUIRE(!QPixmap::fromImage(reader.read()).isNull());
}
SECTION("Detect apng supports animation")
{
reader.setFileName("snackoo.png");
reader.setFormat("apng");
REQUIRE(reader.supportsAnimation());
REQUIRE(!QPixmap::fromImage(reader.read()).isNull());
}
SECTION("Detect png frame has no animation")
{
reader.setFileName("missle.png");
reader.setFormat("apng");
REQUIRE(!reader.supportsAnimation());
reader.setFormat("png");
REQUIRE(!reader.supportsAnimation());
REQUIRE(!QPixmap::fromImage(reader.read()).isNull());
}
}

View File

@ -1,46 +0,0 @@
#include <cstring>
#include <iostream>
#include <QString>
#include <catch2/catch.hpp>
#include "bass.h"
#include "bassmidi.h"
#include "bassopus.h"
TEST_CASE("BASS URL streaming", "[bass][noci]")
{
// Sample
QString url = "https://raw.githubusercontent.com/skyedeving/aocharedit/master/Attorney%20Online%20Character%20Editor/Resources/about.mp3";
// initialize
BASS_Init(-1, 44100, 0, 0, nullptr);
// create stream from url
HSTREAM stream;
unsigned int flags = BASS_STREAM_AUTOFREE | BASS_STREAM_STATUS;
if (url.endsWith(".opus"))
{
stream = BASS_OPUS_StreamCreateURL(url.toStdString().c_str(), 0, flags, nullptr, 0);
}
else
{
stream = BASS_StreamCreateURL(url.toStdString().c_str(), 0, flags, nullptr, 0);
}
// Log http status
const char *tags = BASS_ChannelGetTags(stream, BASS_TAG_HTTP);
if (tags)
{
while (*tags)
{
UNSCOPED_INFO(tags);
tags += strlen(tags) + 1;
}
}
// Test
REQUIRE(stream != 0);
REQUIRE(BASS_ChannelPlay(stream, TRUE) == TRUE);
// while (BASS_ChannelIsActive(stream) != BASS_ACTIVE_STOPPED); // block test to listen
}

View File

@ -1,16 +0,0 @@
#include <catch2/catch.hpp>
#include <QStringList>
TEST_CASE("Sort case evidence numerically", "[case]")
{
// Parameters
QStringList case_evidence = {"1", "10", "11", "2", "3", "4", "5", "6", "7", "8", "9"};
QStringList case_evidence_sorted = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"};
// Sort
std::sort(case_evidence.begin(), case_evidence.end(), [](const QString &a, const QString &b) { return a.toInt() < b.toInt(); });
// Test
REQUIRE(case_evidence == case_evidence_sorted);
}