Skip to content

Commit c1bc42c

Browse files
committed
Refactor CI integration tests to run as a single executable and increase timeout; enhance WebSocket integration test synchronization
1 parent 285bbfe commit c1bc42c

3 files changed

Lines changed: 39 additions & 11 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,10 @@ jobs:
6767
run: ctest --test-dir build -C Release -L unit --output-on-failure
6868

6969
- name: Integration tests
70-
run: ctest --test-dir build -C Release -L integration --output-on-failure
71-
timeout-minutes: 5
70+
run: |
71+
if [[ "$RUNNER_OS" == "Windows" ]]; then
72+
build/tests/Release/hyperliquid_integration_tests.exe --gtest_color=yes
73+
else
74+
build/tests/hyperliquid_integration_tests --gtest_color=yes
75+
fi
76+
timeout-minutes: 10

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
### Changed
1313
- Normalize line ending to LF
14-
- Move test CMake setup into `tests/CMakeLists.txt`, register GoogleTest cases with `gtest_discover_tests()`, and update CI to run unit/integration test groups by CTest label.
14+
- Move test CMake setup into `tests/CMakeLists.txt`, register GoogleTest cases with `gtest_discover_tests()`, and keep CI integration tests running as a single executable to avoid repeated testnet setup per discovered test case.
15+
- Stabilize the WebSocket partial-unsubscribe integration test by waiting for the next `allMids` event instead of assuming one arrives within a fixed one-second sleep.
1516

1617
## [0.1.2] - 2026-06-09
1718

tests/test_websocket_integration.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,28 @@ struct Waiter {
3535
}
3636
};
3737

38+
struct CounterWaiter {
39+
std::atomic_int count = 0;
40+
41+
void increment() {
42+
count.fetch_add(1, std::memory_order_acq_rel);
43+
}
44+
45+
int value() {
46+
return count.load(std::memory_order_relaxed);
47+
}
48+
49+
bool wait_greater_than(int baseline, std::chrono::seconds timeout = kMsgTimeout) {
50+
const auto deadline = std::chrono::steady_clock::now() + timeout;
51+
while (value() <= baseline) {
52+
if (std::chrono::steady_clock::now() >= deadline)
53+
return false;
54+
std::this_thread::sleep_for(std::chrono::milliseconds(10));
55+
}
56+
return true;
57+
}
58+
};
59+
3860
// ── Fixture ───────────────────────────────────────────────────────────────────
3961
// One shared Info (and therefore one WebSocket connection) for the whole suite.
4062
// All sync objects are heap-allocated via shared_ptr so there are no dangling
@@ -355,24 +377,24 @@ TEST_F(WsIntegration, CallbackCanRemoveLaterCallbackFromSameDispatch) {
355377

356378
TEST_F(WsIntegration, UnsubscribeOneCallbackLeavesOther) {
357379
auto w1 = std::make_shared<Waiter>();
358-
auto counter2 = std::make_shared<std::atomic<int>>(0);
380+
auto counter2 = std::make_shared<CounterWaiter>();
359381
const json kSub{{"type", "allMids"}};
360382

361383
int sid1 = info_->subscribe(kSub, [w1](const json& m) { w1->set(m); });
362-
int sid2 = info_->subscribe(kSub, [counter2](const json&) { ++(*counter2); });
384+
int sid2 = info_->subscribe(kSub, [counter2](const json&) { counter2->increment(); });
363385

364386
// Wait until both have received at least one message
365387
ASSERT_TRUE(w1->wait()) << "Timed out before partial unsubscribe";
366-
// Give sid2's callback time to fire too
367-
std::this_thread::sleep_for(std::chrono::milliseconds(200));
388+
ASSERT_TRUE(counter2->wait_greater_than(0)) << "sid2 did not receive before partial unsubscribe";
368389

369390
// Remove only sid1
370391
info_->unsubscribe(kSub, sid1);
371-
int snap = counter2->load();
392+
int snap = counter2->value();
372393

373-
// sid2 must continue to receive messages for another second
374-
std::this_thread::sleep_for(std::chrono::seconds(1));
375-
EXPECT_GT(counter2->load(), snap) << "sid2 stopped receiving after sid1 was removed";
394+
// sid2 must continue receiving after sid1 is removed. allMids can be quiet
395+
// for short periods on testnet, so wait for the next event instead of
396+
// assuming one arrives within a fixed sleep.
397+
EXPECT_TRUE(counter2->wait_greater_than(snap)) << "sid2 stopped receiving after sid1 was removed";
376398

377399
info_->unsubscribe(kSub, sid2);
378400
}

0 commit comments

Comments
 (0)