diff --git a/Source/Global/global.h b/Source/Global/global.h index e5cf839a..e35b31ac 100644 --- a/Source/Global/global.h +++ b/Source/Global/global.h @@ -78,6 +78,7 @@ typedef struct http_singleton // Mock state std::recursive_mutex m_mocksLock; http_internal_vector m_mocks; + http_internal_map m_mockCycleIndex; std::recursive_mutex m_sharedPtrsLock; http_internal_unordered_map> m_sharedPtrs; diff --git a/Source/Mock/lhc_mock.cpp b/Source/Mock/lhc_mock.cpp index 73c276ec..7a73f820 100644 --- a/Source/Mock/lhc_mock.cpp +++ b/Source/Mock/lhc_mock.cpp @@ -60,16 +60,37 @@ bool Mock_Internal_HCHttpCallPerformAsync( auto& mocks{ httpSingleton->m_mocks }; HC_MOCK_CALL* mock{ nullptr }; - // Use the most recently added mock that matches (similar to a stack). - for (auto iter = mocks.rbegin(); iter != mocks.rend(); ++iter) + // Collect all matching mocks in insertion order + http_internal_vector matchingMocks; + for (auto& m : mocks) { - if (DoesMockCallMatch(*iter, originalCall)) + if (DoesMockCallMatch(m, originalCall)) { - mock = *iter; - break; + matchingMocks.push_back(m); } } + if (matchingMocks.empty()) + { + return false; + } + + if (matchingMocks.size() == 1) + { + mock = matchingMocks[0]; + } + else + { + // Build a key from method+url to track cycling position + http_internal_string key{ originalCall->method }; + key += "|"; + key += originalCall->url; + + auto& idx = httpSingleton->m_mockCycleIndex[key]; + mock = matchingMocks[idx % matchingMocks.size()]; + ++idx; + } + if (!mock) { return false; diff --git a/Source/Mock/mock_publics.cpp b/Source/Mock/mock_publics.cpp index fdd7c6c9..e5795f32 100644 --- a/Source/Mock/mock_publics.cpp +++ b/Source/Mock/mock_publics.cpp @@ -115,6 +115,7 @@ try { mocks.erase(iter); HCHttpCallCloseHandle(call); + httpSingleton->m_mockCycleIndex.clear(); return S_OK; } } @@ -139,6 +140,7 @@ try } httpSingleton->m_mocks.clear(); + httpSingleton->m_mockCycleIndex.clear(); return S_OK; } CATCH_RETURN()