You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
MockRedisAdapter has drifted from the adapter API and is never compiled in CI #124
main at ff2d5b8. mock/MockRedisAdapter.hpp is byte-identical through the #108 → #109 → #111 stack.
Redis version and deployment mode
Not applicable (compile-time).
Observed behavior
With MOCK_REDIS_ADAPTER defined, RedisAdapter.hpp includes only mock/MockRedisAdapter.hpp and aliases RedisAdapter to the mock. The mock redefines RA_Time, but:
It declares neither RA_NOT_CONNECTED (pre-existing) nor RA_REJECTED (added by Separate rejected stream writes from transport failures #109). Code that follows docs/api.md, for example t.err() == RA_REJECTED.err(), compiles against the real adapter and fails with the mock: error: 'RA_REJECTED' was not declared in this scope (same for RA_NOT_CONNECTED). The mock also cannot simulate a rejection.
It lacks RA_Options and all of the stack's new API: subscribeStream, ReaderHandle and status(), ReaderStatus, getStreamSnapshot. It also lacks the new pure helpers and types (decodeScalar, decodeArray, compareStreamIds, StreamEntry/StreamBatch), which need no connection and could be shared at no cost.
Over-allocation in MockRedisAdapter list functions using size_bytes() instead of size() #81 is worse than filed. Under the project's C++17, no instantiation of either addSingleList overload compiles: std::vector, std::array and the spanCpp14.hpp span have no size_bytes(). Only a C++20 std::span compiles, and it allocates sizeof(T) times too much (48 bytes for 12).
RedisCache.hpp can't even be included in a mock build. _ra->addListsReader/getSingleList are resolved at template-definition time and the mock has neither. Under C++17 the header also fails earlier, at std::atomic<bool>, because it relies on <atomic> (and <thread>, <mutex>, <algorithm>) arriving transitively from the real adapter header. So consumers that use RedisCache can't unit-test with the mock at all.
The mock declares, but never defines, RA_Time(const std::string&), id() and id_or_now(), so a mock-only test that formats an ID fails to link.
Nothing in CMake or CI builds a translation unit with -DMOCK_REDIS_ADAPTER, which is how this drifted. #106/#107 show that the mock has users.
Related, affecting the real header too: t == RA_REJECTED does not compile (ambiguous operator==, because RA_Time has two implicit integer conversions). Both conversions map every error to 0, so int64_t(t) == int64_t(RA_REJECTED) is also true for a transport failure. Callers are left with the magic number err() == 2.
Reproduction
#defineMOCK_REDIS_ADAPTER
#include"RedisAdapter.hpp"boolrejected(const RA_Time& t) { return t.err() == RA_REJECTED.err(); } // error: 'RA_REJECTED' was not declared
g++ -std=c++17 -fsyntax-only against main or the stack head, with the adapter's include directories, fails as shown. The same happens with RA_NOT_CONNECTED, and with any instantiation of MockRedisAdapter::addSingleList.
Build and runtime environment
g++ 13.3 and clang++ 18.1, C++17 and C++20.
Suggested fix
Move RA_Time, the sentinels, the stream types and the pure helpers into a small header that both RedisAdapter.hpp and the mock include.
Add friend bool operator==/!=(const RA_Time&, const RA_Time&) comparing value, or named predicates. Validated with gcc and clang; ctest 17/17.
Let mock writes return a configurable result, so consumers can unit-test their rejection handling.
Give the mock recording/replay versions of addListsReader/addValuesReader/getSingleList, or ship a MockRedisCache. Make RedisCache.hpp include what it uses and drop the unused <semaphore>. Define the mock's RA_Time helpers inline.
Add a CI step that compiles a small consumer translation unit with -DMOCK_REDIS_ADAPTER, including RedisAdapter.hpp and RedisCache.hpp.
Decide whether the mock should mirror the owned-subscription API. It needs at least a subscribeStream that stores the callback plus a hook to inject batches. Otherwise, document that it is absent.
RedisAdapter version or revision
mainatff2d5b8.mock/MockRedisAdapter.hppis byte-identical through the #108 → #109 → #111 stack.Redis version and deployment mode
Not applicable (compile-time).
Observed behavior
With
MOCK_REDIS_ADAPTERdefined,RedisAdapter.hppincludes onlymock/MockRedisAdapter.hppand aliasesRedisAdapterto the mock. The mock redefinesRA_Time, but:RA_NOT_CONNECTED(pre-existing) norRA_REJECTED(added by Separate rejected stream writes from transport failures #109). Code that follows docs/api.md, for examplet.err() == RA_REJECTED.err(), compiles against the real adapter and fails with the mock:error: 'RA_REJECTED' was not declared in this scope(same forRA_NOT_CONNECTED). The mock also cannot simulate a rejection.RA_Optionsand all of the stack's new API:subscribeStream,ReaderHandleandstatus(),ReaderStatus,getStreamSnapshot. It also lacks the new pure helpers and types (decodeScalar,decodeArray,compareStreamIds,StreamEntry/StreamBatch), which need no connection and could be shared at no cost.addSingleListoverload compiles:std::vector,std::arrayand thespanCpp14.hppspan have nosize_bytes(). Only a C++20std::spancompiles, and it allocatessizeof(T)times too much (48 bytes for 12).RedisCache.hppcan't even be included in a mock build._ra->addListsReader/getSingleListare resolved at template-definition time and the mock has neither. Under C++17 the header also fails earlier, atstd::atomic<bool>, because it relies on<atomic>(and<thread>,<mutex>,<algorithm>) arriving transitively from the real adapter header. So consumers that use RedisCache can't unit-test with the mock at all.RA_Time(const std::string&),id()andid_or_now(), so a mock-only test that formats an ID fails to link.Nothing in CMake or CI builds a translation unit with
-DMOCK_REDIS_ADAPTER, which is how this drifted. #106/#107 show that the mock has users.Related, affecting the real header too:
t == RA_REJECTEDdoes not compile (ambiguousoperator==, becauseRA_Timehas two implicit integer conversions). Both conversions map every error to 0, soint64_t(t) == int64_t(RA_REJECTED)is also true for a transport failure. Callers are left with the magic numbererr() == 2.Reproduction
g++ -std=c++17 -fsyntax-onlyagainstmainor the stack head, with the adapter's include directories, fails as shown. The same happens withRA_NOT_CONNECTED, and with any instantiation ofMockRedisAdapter::addSingleList.Build and runtime environment
g++ 13.3 and clang++ 18.1, C++17 and C++20.
Suggested fix
RA_Time, the sentinels, the stream types and the pure helpers into a small header that bothRedisAdapter.hppand the mock include.friend bool operator==/!=(const RA_Time&, const RA_Time&)comparingvalue, or named predicates. Validated with gcc and clang; ctest 17/17.const size_t count = data.size(); int dataSize = count * sizeof(T); new T[count]. Validated: all six vector/array/span × C++17/C++20 combinations compile and run clean under ASan+UBSan.addListsReader/addValuesReader/getSingleList, or ship aMockRedisCache. MakeRedisCache.hppinclude what it uses and drop the unused<semaphore>. Define the mock'sRA_Timehelpers inline.-DMOCK_REDIS_ADAPTER, includingRedisAdapter.hppandRedisCache.hpp.subscribeStreamthat stores the callback plus a hook to inject batches. Otherwise, document that it is absent.Related: #80 (fixed by #107), #81, #106, #109.