mirror of
https://github.com/logos-co/logos-test-modules.git
synced 2026-08-27 10:11:12 +00:00
fix(basic-cpp): answer stringLength in characters, mirroring test_basic_module
test_basic_module_cpp is the pure-C++ mirror of test_basic_module, but after the
universal migration the two disagreed on non-ASCII: the Qt-derived one counted
CHARACTERS while this one still counted BYTES (s.size()), so
stringLength("héllo") was 5 there and 6 here, and validateInput's length field
likewise. Same for the code-point definition of "character": one emoji is 1.
The blind spot is the point: this module's group only ever asserted ASCII, where
bytes and characters coincide, so two modules that exist to mirror each other
could drift apart invisibly. Two non-ASCII assertions added — the same pair the
sibling carries, so a future divergence fails on both sides.
The helper is copied rather than shared: these fixtures are deliberately
standalone (this one's whole point is that it compiles with no Qt anywhere), and
a shared header between them would weaken that. The comment on each says so.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b14cf06ede
commit
d4054248d3
@@ -21,12 +21,35 @@ bool TestBasicModuleCppImpl::returnTrue() { return true; }
|
||||
bool TestBasicModuleCppImpl::returnFalse() { return false; }
|
||||
bool TestBasicModuleCppImpl::isPositive(int64_t value) { return value > 0; }
|
||||
|
||||
namespace {
|
||||
|
||||
// A character is a Unicode CODE POINT, so count the bytes that START one: in
|
||||
// UTF-8 every continuation byte matches 10xxxxxx. Identical to the helper in
|
||||
// test_basic_module — these two modules are deliberate mirrors and must agree
|
||||
// on non-ASCII, which they did not: this one answered in BYTES while its twin
|
||||
// answered in characters.
|
||||
inline bool isContinuationByte(char c)
|
||||
{
|
||||
return (static_cast<unsigned char>(c) & 0xC0) == 0x80;
|
||||
}
|
||||
|
||||
int64_t characterCount(const std::string& s)
|
||||
{
|
||||
int64_t n = 0;
|
||||
for (char c : s) {
|
||||
if (!isContinuationByte(c)) ++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ── int64_t ──────────────────────────────────────────────────────────────
|
||||
|
||||
int64_t TestBasicModuleCppImpl::returnInt() { return 42; }
|
||||
int64_t TestBasicModuleCppImpl::addInts(int64_t a, int64_t b) { return a + b; }
|
||||
int64_t TestBasicModuleCppImpl::stringLength(const std::string& s) {
|
||||
return static_cast<int64_t>(s.size());
|
||||
return characterCount(s);
|
||||
}
|
||||
|
||||
// ── uint64_t ─────────────────────────────────────────────────────────────
|
||||
@@ -81,7 +104,7 @@ StdLogosResult TestBasicModuleCppImpl::validateInput(const std::string& input) {
|
||||
}
|
||||
nlohmann::json data;
|
||||
data["input"] = input;
|
||||
data["length"] = static_cast<int64_t>(input.size());
|
||||
data["length"] = characterCount(input);
|
||||
return {true, data, ""};
|
||||
}
|
||||
|
||||
|
||||
@@ -508,6 +508,14 @@ test_basic_cpp "addInts(3, 4)" "Result: 7" "test_basic_module_cpp.addInts
|
||||
test_basic_cpp "addInts(0, 0)" "Result: 0" "test_basic_module_cpp.addInts(0, 0)"
|
||||
test_basic_cpp "addInts(-5, 10)" "Result: 5" "test_basic_module_cpp.addInts(-5, 10)"
|
||||
test_basic_cpp "stringLength(hello)" "Result: 5" "test_basic_module_cpp.stringLength(hello)"
|
||||
# The two modules are deliberate MIRRORS, so they must agree on non-ASCII. They
|
||||
# did not: this one answered in BYTES (6) while test_basic_module answered in
|
||||
# CHARACTERS (5). The blind spot was that this group only ever asserted ASCII,
|
||||
# where bytes and characters coincide — so the disagreement was invisible.
|
||||
test_basic_cpp "stringLength(héllo) [characters, mirrors test_basic_module]" "Result: 5" \
|
||||
"test_basic_module_cpp.stringLength(héllo)"
|
||||
test_basic_cpp "stringLength(😀) [non-BMP character counts 1]" "Result: 1" \
|
||||
"test_basic_module_cpp.stringLength(😀)"
|
||||
skip_test "stringLength()" "logoscore cannot call 1-arg method with 0 args"
|
||||
|
||||
# ── Return type: uint64_t (unique to the C++ surface) ───────────────────────
|
||||
|
||||
Reference in New Issue
Block a user