File indexing completed on 2024-05-19 04:39:27

0001 /*
0002     SPDX-FileCopyrightText: 2012-2013 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "test_indexedstring.h"
0008 
0009 #include <serialization/indexedstring.h>
0010 #include <serialization/referencecounting.h>
0011 
0012 #include <QTest>
0013 
0014 #include <cstddef>
0015 #include <utility>
0016 
0017 QTEST_GUILESS_MAIN(TestIndexedString)
0018 
0019 using namespace KDevelop;
0020 
0021 void TestIndexedString::testUrl_data()
0022 {
0023     QTest::addColumn<QUrl>("url");
0024     QTest::addColumn<QString>("string");
0025     QTest::newRow("empty") << QUrl() << QString();
0026     QTest::newRow("/") << QUrl::fromLocalFile(QStringLiteral("/")) << QStringLiteral("/");
0027     QTest::newRow("/foo/bar") << QUrl::fromLocalFile(QStringLiteral("/foo/bar")) << QStringLiteral("/foo/bar");
0028     QTest::newRow("http://foo.com/") << QUrl(QStringLiteral("http://foo.com/")) << QStringLiteral("http://foo.com/");
0029     QTest::newRow("http://foo.com/bar/asdf") << QUrl(QStringLiteral("http://foo.com/bar/asdf")) << QStringLiteral(
0030         "http://foo.com/bar/asdf");
0031     QTest::newRow("file:///bar/asdf") << QUrl(QStringLiteral("file:///bar/asdf")) << QStringLiteral("/bar/asdf");
0032 
0033 #ifdef Q_OS_WIN
0034     // Make sure we're not running into https://bugreports.qt.io/browse/QTBUG-41729
0035     QTest::newRow("file:///C:/bar/asdf") << QUrl("file:///C:/bar/asdf") << QStringLiteral("C:/bar/asdf");
0036 #endif
0037 }
0038 
0039 void TestIndexedString::testUrl()
0040 {
0041     QFETCH(QUrl, url);
0042     IndexedString indexed(url);
0043     QCOMPARE(indexed.toUrl(), url);
0044     QTEST(indexed.str(), "string");
0045 }
0046 
0047 void TestIndexedString::test()
0048 {
0049     QFETCH(QString, data);
0050 
0051     IndexedString indexed(data);
0052     QCOMPARE(indexed.str(), data);
0053     QCOMPARE(indexed.index(), IndexedString::indexForString(data));
0054     const auto byteArrayData = data.toUtf8();
0055     QEXPECT_FAIL("char-utf8", "UTF-8 gets decoded and the char data is stored internally", Continue);
0056     QEXPECT_FAIL("string-utf8", "UTF-8 gets decoded and the char data is stored internally", Continue);
0057     QCOMPARE(indexed.length(), data.length());
0058     // fallback until we rely on internal utf8 encoding
0059     QCOMPARE(indexed.length(), byteArrayData.length());
0060 
0061     QCOMPARE(indexed.byteArray(), byteArrayData);
0062     QVERIFY(!strncmp(indexed.c_str(), byteArrayData.data(), byteArrayData.length()));
0063     QCOMPARE(indexed.index(), IndexedString::indexForString(byteArrayData.data(), byteArrayData.length()));
0064 
0065     IndexedString moved = std::move(indexed);
0066     QCOMPARE(moved.str(), data);
0067 }
0068 
0069 void TestIndexedString::test_data()
0070 {
0071     QTest::addColumn<QString>("data");
0072 
0073     QTest::newRow("empty") << QString();
0074     QTest::newRow("char-ascii") << QStringLiteral("a");
0075     QTest::newRow("char-utf8") << QStringLiteral("ä");
0076     QTest::newRow("string-ascii") << QStringLiteral("asdf()?=");
0077     QTest::newRow("string-utf8") << QStringLiteral("æſðđäöü");
0078 }
0079 
0080 void TestIndexedString::testMoveAssignment()
0081 {
0082     // Deliberately make no assumptions about the value of the moved-from object.
0083 
0084     const QString text = QStringLiteral("random text");
0085     IndexedString movedFrom(text);
0086     QCOMPARE(movedFrom.str(), text);
0087 
0088     IndexedString notRefCounted;
0089     notRefCounted = std::move(movedFrom);
0090     QCOMPARE(notRefCounted.str(), text);
0091 
0092     movedFrom = std::move(notRefCounted);
0093     QCOMPARE(movedFrom.str(), text);
0094 
0095     const QString toBeDerefed = QStringLiteral("to-be-derefed");
0096 
0097     // Enable reference counting throughout refCounted's lifetime.
0098     std::byte indexedStringData[sizeof(IndexedString)];
0099     const DUChainReferenceCountingEnabler rcEnabler(indexedStringData, sizeof(IndexedString));
0100     IndexedString* const refCounted = new (indexedStringData) IndexedString(toBeDerefed);
0101     QCOMPARE(refCounted->str(), toBeDerefed);
0102 
0103     *refCounted = std::move(movedFrom);
0104     QCOMPARE(refCounted->str(), text);
0105     refCounted->~IndexedString();
0106 }
0107 
0108 void TestIndexedString::testSwap()
0109 {
0110     QFETCH(bool, lhsRcEnabled);
0111     QFETCH(bool, rhsRcEnabled);
0112 
0113     class OptionallyRcString
0114     {
0115     public:
0116         explicit OptionallyRcString(bool rcEnabled, const QString& initText)
0117             : m_rcEnabled{rcEnabled}
0118             , m_initText{initText}
0119             , m_notRefCounted{m_initText}
0120             , m_refCountedData{}
0121             , m_rcEnabler{m_refCountedData, sizeof(IndexedString)}
0122             , m_string{m_rcEnabled ? new (m_refCountedData) IndexedString(m_initText) : &m_notRefCounted}
0123         {
0124             QCOMPARE(m_string->str(), m_initText);
0125         }
0126 
0127         ~OptionallyRcString()
0128         {
0129             if (m_rcEnabled) {
0130                 m_string->~IndexedString();
0131             }
0132         }
0133 
0134         const QString& initText() const { return m_initText; }
0135         IndexedString& string() { return *m_string; }
0136 
0137     private:
0138         const bool m_rcEnabled;
0139         const QString m_initText;
0140 
0141         IndexedString m_notRefCounted;
0142         std::byte m_refCountedData[sizeof(IndexedString)];
0143         const DUChainReferenceCountingEnabler m_rcEnabler;
0144 
0145         IndexedString* const m_string = nullptr;
0146     };
0147 
0148     OptionallyRcString lhs(lhsRcEnabled, QStringLiteral("1st text"));
0149     OptionallyRcString rhs(rhsRcEnabled, QStringLiteral("another string"));
0150 
0151     using std::swap;
0152 
0153     swap(lhs.string(), rhs.string());
0154     QCOMPARE(lhs.string().str(), rhs.initText());
0155     QCOMPARE(rhs.string().str(), lhs.initText());
0156 
0157     swap(lhs.string(), rhs.string());
0158     QCOMPARE(lhs.string().str(), lhs.initText());
0159     QCOMPARE(rhs.string().str(), rhs.initText());
0160 }
0161 
0162 void TestIndexedString::testSwap_data()
0163 {
0164     QTest::addColumn<bool>("lhsRcEnabled");
0165     QTest::addColumn<bool>("rhsRcEnabled");
0166 
0167     QTest::newRow("no reference counting") << false << false;
0168     QTest::newRow("lhs reference-counted") << true << false;
0169     QTest::newRow("rhs reference-counted") << false << true;
0170     QTest::newRow("both reference-counted") << true << true;
0171 }
0172 
0173 void TestIndexedString::testCString()
0174 {
0175     IndexedString str(nullptr);
0176     QCOMPARE(str.index(), 0u);
0177     QVERIFY(str.isEmpty());
0178 }
0179 
0180 #include "moc_test_indexedstring.cpp"