← source index

test/SlidingWindowTest.cpp

270 lines  ·  9.6 K  ·  cpp
#include <iostream>
#include <fstream>

#include <catch_amalgamated.hpp>
#include <boost/algorithm/string.hpp>

#include "../src/Helper.h"
#include "../src/SlidingWindow.h"

void slidingWindowFill(SlidingWindow& slidingWindow, std::vector<TickEntry>& lookup,
                       size_t maxSplitSize, TickEntry& tail, TickEntry& head,
                       TickEntry& tick, SlidingWindowData& data, const std::string& line,
                       std::string& ts, std::string& tradeId, std::string& price,
                       std::string& ns, std::string& parsedPx, std::string& flag)
{
    std::vector<std::string> strs;
    boost::split(strs, line, boost::is_any_of(" "));
    size_t splitSize = 0;
    ts = strs[splitSize];
    if(splitSize < maxSplitSize - 1) splitSize++;
    tradeId = strs[splitSize];
    if(splitSize < maxSplitSize - 1) splitSize++;
    price = strs[splitSize];
    if(splitSize < maxSplitSize - 1) splitSize++;
    ns = strs[splitSize];
    if(splitSize < maxSplitSize - 1) splitSize++;
    parsedPx = strs[splitSize];
    if(splitSize < maxSplitSize - 1) splitSize++;
    flag = strs[splitSize];

    TickEntry rawTick;
    rawTick.mTsNano = Helper::parseTsNs(ts);
    rawTick.mTradeId = std::stoll(tradeId);
    rawTick.mPrice = Helper::parseToPx(price);

    if(flag[0] == 'H') head = rawTick;
    if(flag[0] == 'T') tail = rawTick;

    auto [status, d] = slidingWindow.push(rawTick);
    data = d;
    tick = rawTick;
    REQUIRE(status == true);
    if(status && (flag[0] == 'H' || flag[0] == 'T' || flag[0] == 'Y'))
        lookup.emplace_back(rawTick);
}

void slidingWindowFileTest(const char* path, size_t medianBufCapacity, size_t tickSize)
{
    std::string line;
    std::ifstream file(path);

    REQUIRE(file.good() == true);

    getline (file, line);
    std::vector<std::string> s;
    boost::split(s, line, boost::is_any_of(" "));

    uint64_t windowSize = std::stoull(s[0]);
    uint64_t cap = std::stoull(s[1]);
    uint64_t size = std::stoull(s[2]);
    uint64_t maxCap = std::stoull(s[3]);
    //uint64_t entryCount = std::stoull(s[4]);

    SlidingWindow slidingWindow(windowSize, cap, maxCap, medianBufCapacity, tickSize);
    TickEntry head;
    TickEntry tail;
    TickEntry tick;
    SlidingWindowData data;

    std::string ts;
    std::string tradeId;
    std::string price;
    std::string ns;
    std::string parsedPx;
    std::string flag;

    std::vector<TickEntry> lookup;
    lookup.reserve(size);

    while (getline (file, line))
    {
        slidingWindowFill(slidingWindow, lookup, 6, tail, head, tick, data, line,
                          ts, tradeId, price, ns, parsedPx, flag);
    }

    REQUIRE(lookup.size() == size);
    REQUIRE(slidingWindow.getSize() == size);
    auto [tailTick, tailData] = slidingWindow.getTail();
    REQUIRE(tailTick == tail);
    auto [headTick, headData] = slidingWindow.getHead();
    REQUIRE(headTick == head);

    auto window = slidingWindow.getWindow();
    REQUIRE(window.size() == size);
    for(size_t i = 0; i < window.size(); i++)
    {
        CHECK(lookup[i] == window[i]);
    }

    file.close();
}

void testSlidingWindowData(uint64_t windowSize, uint64_t windowCap, uint64_t windowMaxCap, 
                           uint64_t medianBufCap, uint64_t tickSize, const std::vector<std::string>& tests,
                           const std::vector<std::string>& expected)
{
    SlidingWindow slidingWindow(windowSize, windowCap, windowMaxCap, medianBufCap, tickSize);
    TickEntry head;
    TickEntry tail;
    TickEntry tick;
    SlidingWindowData data;

    std::string ts;
    std::string tradeId;
    std::string price;
    std::string ns;
    std::string parsedPx;
    std::string flag;

    std::vector<TickEntry> lookup;
    lookup.reserve(tests.size());

    for(size_t i = 0; i < tests.size(); i++)
    {
        std::string line = tests[i];
        std::string exp = expected[i];
        slidingWindowFill(slidingWindow, lookup, 3, tail, head, tick, data, line,
                          ts, tradeId, price, ns, parsedPx, flag);

        char meanBuf[32];
        char medianBuf[32];
        char lowBuf[32];
        char highBuf[32];

        Helper::parseFromPx(data.mMean, meanBuf);
        Helper::parseFromPx(data.mMedian, medianBuf);
        Helper::parseFromPx(data.mLow, lowBuf);
        Helper::parseFromPx(data.mHigh, highBuf);

        CHECK(data.mLow <= data.mMedian);
        CHECK(data.mMedian <= data.mHigh);
        CHECK(data.mLow <= data.mMean);
        CHECK(data.mMean <= data.mHigh);

        std::vector<std::string> expBuf;
        boost::split(expBuf, exp, boost::is_any_of(" "));

        CHECK(meanBuf == expBuf[0]);
        CHECK(medianBuf == expBuf[1]);
        CHECK(lowBuf == expBuf[2]);
        CHECK(highBuf == expBuf[3]);
    }
}

TEST_CASE("SlidingWindow.h -> short sliding functionality")
{
    slidingWindowFileTest("test_data/SlidingWindow-short.testdata", 2000000, 1);
}

TEST_CASE("SlidingWindow.h -> long sliding functionality")
{
    slidingWindowFileTest("test_data/SlidingWindow-long.testdata", 2000000, 100);
}

TEST_CASE("SlidingWindow.h -> mean/median/low/high 1")
{
    std::vector<std::string> tests =
    {
        "2026-10-25T10:43:11.492712Z 1767956358 84985.67",
        "2026-10-25T10:43:11.493199Z 8194575072 84965.53",
        "2026-10-25T10:43:11.493474Z 4531995809 84930.31",
        "2026-10-25T10:43:11.493717Z 0081494246 84925.84",
        "2026-10-25T10:43:11.494184Z 4294755161 84895.75",
        "2026-10-25T10:43:11.494385Z 6403900565 84880.50",
        "2026-10-25T10:43:11.494736Z 4663098181 84905.77",
        "2026-10-25T10:43:11.495232Z 3922168192 84885.12",
        "2026-10-25T10:43:11.495564Z 9112650686 84925.09",
        "2026-10-25T10:43:11.496024Z 8383355168 84910.07",
        "2026-10-25T10:43:11.496478Z 2647479102 84865.09",
        "2026-10-25T10:43:11.496959Z 6204094662 84870.97",
        "2026-10-25T10:43:11.497359Z 7942728477 84855.63",
        "2026-10-25T10:43:11.497836Z 8870179891 84825.63",
        "2026-10-25T10:43:11.498171Z 3943911144 84860.86",
        "2026-10-25T10:43:11.498660Z 4814842962 84895.03",
        "2026-10-25T10:43:11.499041Z 9726971122 84915.06",
        "2026-10-25T10:43:11.499524Z 1156093549 84940.37",
        "2026-10-25T10:43:11.500000Z 3265867191 84910.97",
        "2026-10-25T10:43:11.500246Z 1490064901 84890.10"
    };

    std::vector<std::string> expected =
    {
        "84985.67 84985.67 84985.67 84985.67",
        "84975.6 84985.67 84965.53 84985.67",
        "84960.5 84965.53 84930.31 84985.67",
        "84951.83 84965.53 84925.84 84985.67",
        "84940.62 84930.31 84895.75 84985.67",
        "84930.6 84930.31 84880.5 84985.67",
        "84927.05 84925.84 84880.5 84985.67",
        "84921.81 84925.84 84880.5 84985.67",
        "84922.17 84925.09 84880.5 84985.67",
        "84920.96 84925.09 84880.5 84985.67",
        "84915.88 84910.07 84865.09 84985.67",
        "84912.14 84910.07 84865.09 84985.67",
        "84907.79 84905.77 84855.63 84985.67",
        "84901.92 84905.77 84825.63 84985.67",
        "84899.18 84895.75 84825.63 84985.67",
        "84898.92 84895.75 84825.63 84985.67",
        "84899.87 84895.75 84825.63 84985.67",
        "84902.12 84905.77 84825.63 84985.67",
        "84902.59 84905.77 84825.63 84985.67",
        "84901.96 84905.77 84825.63 84985.67"
    };

    testSlidingWindowData(300000000000LL, 1024, 4096, 2000000, 1, tests, expected);
}

TEST_CASE("SlidingWindow.h -> mean/median/low/high 2")
{
    std::vector<std::string> tests =
    {
        "2026-10-25T10:43:11.000000Z 1767956358 84985.67",
        "2026-10-25T10:43:11.120000Z 8194575072 84965.53",
        "2026-10-25T10:43:11.260000Z 4531995809 84930.31",
        "2026-10-25T10:43:11.455000Z 1081494246 84925.84",
        "2026-10-25T10:43:11.700000Z 4294755161 84880.50",
        "2026-10-25T10:43:11.905000Z 6403900565 84905.77",
        "2026-10-25T10:43:12.150000Z 4663098181 84855.12",
        "2026-10-25T10:43:12.400000Z 3922168192 84925.09",
        "2026-10-25T10:43:12.700000Z 9112650686 84910.07",
        "2026-10-25T10:43:12.700000Z 8383355168 84865.09",
        "2026-10-25T10:43:12.955000Z 2647479102 84870.97",
        "2026-10-25T10:43:13.100000Z 6204094662 84855.63",
        "2026-10-25T10:43:13.450000Z 7942728477 84825.63",
        "2026-10-25T10:43:13.450000Z 8870179891 84860.86",
        "2026-10-25T10:43:13.800000Z 3943911144 84895.03",
        "2026-10-25T10:43:13.905000Z 4814842962 84915.06",
        "2026-10-25T10:43:14.050000Z 9726971122 84940.37",
        "2026-10-25T10:43:14.300000Z 1156093549 84910.97",
        "2026-10-25T10:43:14.600000Z 3265867191 84890.10",
        "2026-10-25T10:43:14.900000Z 1490064901 84880.00"
    };

    std::vector<std::string> expected =
    {
        "84985.67 84985.67 84985.67 84985.67",
        "84975.6 84985.67 84965.53 84985.67",
        "84960.5 84965.53 84930.31 84985.67",
        "84951.83 84965.53 84925.84 84985.67",
        "84937.57 84930.31 84880.5 84985.67",
        "84932.27 84930.31 84880.5 84985.67",
        "84899.5 84905.77 84855.12 84930.31",
        "84898.46 84905.77 84855.12 84925.84",
        "84895.31 84905.77 84855.12 84925.09",
        "84890.27 84905.77 84855.12 84925.09",
        "84885.26 84870.97 84855.12 84925.09",
        "84880.32 84870.97 84855.12 84925.09",
        "84865.47 84865.09 84825.63 84910.07",
        "84864.7 84865.09 84825.63 84910.07",
        "84861.62 84860.86 84825.63 84895.03",
        "84870.53 84870.97 84825.63 84915.06",
        "84882.09 84895.03 84825.63 84940.37",
        "84891.32 84910.97 84825.63 84940.37",
        "84910.3 84910.97 84890.1 84940.37",
        "84907.3 84910.97 84880 84940.37"
    };

    testSlidingWindowData(1000000000LL, 1024, 4096, 2000000, 1, tests, expected);
}