diff options
author | Marc Mutz <marc.mutz@qt.io> | 2022-01-21 15:02:08 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2022-01-23 01:06:57 +0000 |
commit | 3d3558dc8f0a1885f416b4650037364f4ef11bd4 (patch) | |
tree | 33c0a28a52ec17c86057ba4632e68f92bb2266a0 /tests | |
parent | 3ec587666f89c996cc0a403775c352954d8b804f (diff) |
QStaticByteArrayMatcher: fix searching in 2+GiB haystacks
Add a test (same techniques as for the 4+GiB check in
tst_qcryptographichash).
Takes ~1s to build the 4GiB test data here, and skips
when RAM is too low:
$ qtbase/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher haystacksWithMoreThan4GiBWork
[...]
QDEBUG : tst_QByteArrayMatcher::haystacksWithMoreThan4GiBWork() created dataset in 891 ms
[...]
$ (ulimit -v 2000000; qtbase/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher haystacksWithMoreThan4GiBWork)
********* Start testing of tst_QByteArrayMatcher *********
[...]
SKIP : tst_QByteArrayMatcher::haystacksWithMoreThan4GiBWork() Could not allocate 4GiB plus a couple hundred bytes of RAM.
Loc: [/home/marc/Qt/qt5/qtbase/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp(242)]
[...]
Found during 6.3 API review.
[ChangeLog][QtCore][QStaticByteArrayMatcher] Fixed searching in
strings with size > 2GiB (on 64-bit platforms).
Fixes: QTBUG-100118
Pick-to: 6.3
Change-Id: I1df420965673b5555fef2b75e785954cc50b654f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp b/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp index 42b978acc8..aa2b928e95 100644 --- a/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp +++ b/tests/auto/corelib/text/qbytearraymatcher/tst_qbytearraymatcher.cpp @@ -31,6 +31,13 @@ #include <qbytearraymatcher.h> +#include <numeric> +#include <string> + +#if QT_CONFIG(cxx11_future) +# include <thread> +#endif + // COM interface #if defined(Q_OS_WIN) && defined(interface) # undef interface @@ -44,6 +51,7 @@ private slots: void interface(); void indexIn(); void staticByteArrayMatcher(); + void haystacksWithMoreThan4GiBWork(); }; void tst_QByteArrayMatcher::interface() @@ -208,6 +216,72 @@ void tst_QByteArrayMatcher::staticByteArrayMatcher() } +void tst_QByteArrayMatcher::haystacksWithMoreThan4GiBWork() +{ +#if QT_POINTER_SIZE > 4 + // use a large needle to trigger long skips in the Boyer-Moore algorithm + // (to speed up the test) + constexpr std::string_view needle = LONG_STRING_256; + + // + // GIVEN: a haystack with more than 4 GiB of data + // + + // don't use QByteArray because freeSpaceAtEnd() may break reserve() + // semantics and a realloc is the last thing we need here + std::string large; + QElapsedTimer timer; + timer.start(); + constexpr size_t GiB = 1024 * 1024 * 1024; + constexpr size_t BaseSize = 4 * GiB + 1; + try { + large.reserve(BaseSize + needle.size()); + large.resize(BaseSize, '\0'); + large.append(needle); + } catch (const std::bad_alloc &) { + QSKIP("Could not allocate 4GiB plus a couple hundred bytes of RAM."); + } + QCOMPARE(large.size(), BaseSize + needle.size()); + qDebug("created dataset in %lld ms", timer.elapsed()); + +# if QT_CONFIG(cxx11_future) + using MaybeThread = std::thread; +# else + struct MaybeThread { + std::function<void()> func; + void join() { func(); } + }; +# endif + + // + // WHEN: trying to match an occurrence past the 4GiB mark + // + + qsizetype dynamicResult, staticResult; + + auto t = MaybeThread{[&]{ + QByteArrayMatcher m(needle); + dynamicResult = m.indexIn(large); + }}; + { + static_assert(needle == LONG_STRING_256); // need a string literal in the following line: + QStaticByteArrayMatcher m(LONG_STRING_256); + staticResult = m.indexIn(large.data(), large.size()); + } + t.join(); + + // + // THEN: the result index is not trucated + // + + QCOMPARE(staticResult, qsizetype(BaseSize)); + QCOMPARE(dynamicResult, qsizetype(BaseSize)); +#else + QSKIP("This test is 64-bit only."); +#endif + +} + #undef LONG_STRING_256 #undef LONG_STRING_128 #undef LONG_STRING__64 |