#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);
}