mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-08 02:53:25 -08:00
- Install the distribution's gtest (libgtest-dev / gtest-devel) in the Debian, Ubuntu and Fedora images, so configuring the test suite no longer downloads googletest; Arch already had it. - Drop the toolchain meta packages. g++, Ninja and cmake are all that is used, and make is not: Ninja is the generator on every Linux leg. The DEB legs keep dpkg-dev, which CPack needs for dpkg-shlibdeps when CPACK_DEBIAN_PACKAGE_SHLIBDEPS is on. - Use the slim Debian bases and install Fedora packages with --nodocs. - Define the global rng in the tests that pull the server game classes out of server_remote, as the other server tests already do. Debian's libgtest.a leaves a std::string reference undefined, so the linker drags server_protocolhandler.cpp and the classes behind it into any test that links the library, and those need the symbol. git, ca-certificates, libcurl and OpenSSL stay: sentry-native is cloned over git at configure time on every packaging leg, and OpenSSL also backs CryptoUtil. mariadb-devel stays on Fedora for the same reason it is installed elsewhere: without it Servatrice configures successfully but silently loses its MySQL connector. Co-authored-by: Lukas Brübach <44814898+BruebachL@users.noreply.github.com>
157 lines
4 KiB
C++
157 lines
4 KiB
C++
#include <QList>
|
|
#include <QtGlobal>
|
|
#include <gtest/gtest.h>
|
|
#include <initializer_list>
|
|
#include <libcockatrice/network/client/abstract/latency_tracker.h>
|
|
#include <libcockatrice/rng/rng_abstract.h>
|
|
#include <string>
|
|
|
|
// Referenced by other translation units in the server_remote library.
|
|
RNG_Abstract *rng = nullptr;
|
|
|
|
TEST(LatencyTrackerTest, EmptyTrackerYieldsZeroedStats)
|
|
{
|
|
LatencyTracker tracker;
|
|
|
|
const auto stats = tracker.stats();
|
|
|
|
EXPECT_EQ(0, stats.sampleCount);
|
|
EXPECT_EQ(0, stats.lastMs);
|
|
EXPECT_EQ(0, stats.medianMs);
|
|
EXPECT_EQ(0, stats.p95Ms);
|
|
EXPECT_EQ(0, stats.maxMs);
|
|
}
|
|
|
|
TEST(LatencyTrackerTest, SingleSampleIsEveryStatistic)
|
|
{
|
|
LatencyTracker tracker;
|
|
tracker.addSample(42);
|
|
|
|
const auto stats = tracker.stats();
|
|
|
|
EXPECT_EQ(1, stats.sampleCount);
|
|
EXPECT_EQ(42, stats.lastMs);
|
|
EXPECT_EQ(42, stats.medianMs);
|
|
EXPECT_EQ(42, stats.p95Ms);
|
|
EXPECT_EQ(42, stats.maxMs);
|
|
}
|
|
|
|
TEST(LatencyTrackerTest, OddSizedWindowMedianAndP95)
|
|
{
|
|
LatencyTracker tracker;
|
|
for (qint64 ms : {qint64(50), qint64(10), qint64(30), qint64(20), qint64(40)}) {
|
|
tracker.addSample(ms);
|
|
}
|
|
|
|
const auto stats = tracker.stats();
|
|
|
|
EXPECT_EQ(5, stats.sampleCount);
|
|
EXPECT_EQ(40, stats.lastMs);
|
|
EXPECT_EQ(30, stats.medianMs);
|
|
// nearest-rank p95 of 5 samples: ceil(4.75) = 5th smallest
|
|
EXPECT_EQ(50, stats.p95Ms);
|
|
EXPECT_EQ(50, stats.maxMs);
|
|
}
|
|
|
|
TEST(LatencyTrackerTest, EvenSizedWindowMedianIsAverageOfMiddleTwo)
|
|
{
|
|
LatencyTracker tracker;
|
|
for (qint64 ms : {qint64(10), qint64(20), qint64(30), qint64(40)}) {
|
|
tracker.addSample(ms);
|
|
}
|
|
|
|
const auto stats = tracker.stats();
|
|
|
|
EXPECT_EQ(4, stats.sampleCount);
|
|
EXPECT_EQ(25, stats.medianMs);
|
|
// nearest-rank p95 of 4 samples: ceil(3.8) = 4th smallest
|
|
EXPECT_EQ(40, stats.p95Ms);
|
|
}
|
|
|
|
TEST(LatencyTrackerTest, WindowEvictsOldestSamples)
|
|
{
|
|
LatencyTracker tracker;
|
|
for (int i = 0; i <= 99; ++i) {
|
|
tracker.addSample(i);
|
|
}
|
|
|
|
const auto stats = tracker.stats();
|
|
|
|
EXPECT_EQ(LatencyTracker::WindowSize, stats.sampleCount);
|
|
EXPECT_EQ(99, stats.lastMs);
|
|
EXPECT_EQ(99, stats.maxMs);
|
|
// window now contains 36..99 (64 samples)
|
|
EXPECT_EQ(67, stats.medianMs); // (67 + 68) / 2 with integer division
|
|
EXPECT_EQ(96, stats.p95Ms); // ceil(0.95 * 64) - 1 = index 60 -> 36 + 60
|
|
}
|
|
|
|
TEST(LatencyTrackerTest, ClearResetsAllState)
|
|
{
|
|
LatencyTracker tracker;
|
|
for (int i = 0; i <= 99; ++i) {
|
|
tracker.addSample(i);
|
|
}
|
|
|
|
tracker.clear();
|
|
const auto cleared = tracker.stats();
|
|
EXPECT_EQ(0, cleared.sampleCount);
|
|
|
|
tracker.addSample(7);
|
|
const auto stats = tracker.stats();
|
|
EXPECT_EQ(1, stats.sampleCount);
|
|
EXPECT_EQ(7, stats.lastMs);
|
|
EXPECT_EQ(7, stats.medianMs);
|
|
}
|
|
|
|
TEST(LatencyTrackerTest, LastSampleSurvivesWraparound)
|
|
{
|
|
LatencyTracker tracker;
|
|
for (int i = 0; i < LatencyTracker::WindowSize; ++i) {
|
|
tracker.addSample(i);
|
|
}
|
|
tracker.addSample(1000);
|
|
|
|
EXPECT_EQ(1000, tracker.stats().lastMs);
|
|
}
|
|
|
|
TEST(LatencyTrackerTest, RecentSamplesAreChronologicalOldestFirst)
|
|
{
|
|
LatencyTracker tracker;
|
|
for (qint64 ms : {qint64(50), qint64(10), qint64(30)}) {
|
|
tracker.addSample(ms);
|
|
}
|
|
|
|
const QList<qint64> samples = tracker.recentSamples();
|
|
|
|
EXPECT_EQ((QList<qint64>{50, 10, 30}), samples);
|
|
}
|
|
|
|
TEST(LatencyTrackerTest, RecentSamplesFollowRingBufferWraparound)
|
|
{
|
|
LatencyTracker tracker;
|
|
for (int i = 0; i <= 99; ++i) {
|
|
tracker.addSample(i);
|
|
}
|
|
|
|
const QList<qint64> samples = tracker.recentSamples();
|
|
|
|
ASSERT_EQ(LatencyTracker::WindowSize, samples.size());
|
|
EXPECT_EQ(36, samples.first());
|
|
EXPECT_EQ(99, samples.last());
|
|
}
|
|
|
|
TEST(LatencyTrackerTest, RecentSamplesEmptyOnFreshAndClearedTracker)
|
|
{
|
|
LatencyTracker tracker;
|
|
EXPECT_TRUE(tracker.recentSamples().isEmpty());
|
|
|
|
tracker.addSample(5);
|
|
tracker.clear();
|
|
EXPECT_TRUE(tracker.recentSamples().isEmpty());
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|