File indexing completed on 2024-03-24 17:19:20

0001 /*
0002     SPDX-FileCopyrightText: 2018 Milian Wolff <mail@milianw.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-or-later
0005 */
0006 
0007 #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
0008 #include "3rdparty/doctest.h"
0009 
0010 #include "util/linereader.h"
0011 #include "util/linewriter.h"
0012 
0013 #include "tempfile.h"
0014 
0015 #include <limits>
0016 
0017 using namespace std;
0018 
0019 constexpr uint64_t operator"" _u64(unsigned long long v)
0020 {
0021     return static_cast<uint64_t>(v);
0022 }
0023 
0024 TEST_CASE ("write data") {
0025     TempFile file;
0026     REQUIRE(file.open());
0027 
0028     LineWriter writer(file.fd);
0029     REQUIRE(writer.canWrite());
0030     REQUIRE(writer.write("hello world\n"));
0031     REQUIRE(writer.write("%d %x\n", 42, 42));
0032     REQUIRE(writer.writeHexLine('t', 0u, 0ul, 1u, 1ul, 15u, 15ul, 16u, 16ul));
0033     REQUIRE(writer.writeHexLine('u', std::numeric_limits<uint32_t>::max() - 1, std::numeric_limits<uint32_t>::max()));
0034     REQUIRE(writer.writeHexLine('l', std::numeric_limits<uint64_t>::max() - 1, std::numeric_limits<uint64_t>::max()));
0035 
0036     REQUIRE(file.readContents().empty());
0037 
0038     REQUIRE(writer.flush());
0039 
0040     const string expectedContents = "hello world\n"
0041                                     "42 2a\n"
0042                                     "t 0 0 1 1 f f 10 10\n"
0043                                     "u fffffffe ffffffff\n"
0044                                     "l fffffffffffffffe ffffffffffffffff\n";
0045 
0046     REQUIRE(file.readContents() == expectedContents);
0047 }
0048 
0049 TEST_CASE ("buffered write") {
0050     TempFile file;
0051     REQUIRE(file.open());
0052 
0053     LineWriter writer(file.fd);
0054     REQUIRE(writer.canWrite());
0055     ostringstream expectedContents;
0056     for (unsigned i = 0; i < 10000; ++i) {
0057         REQUIRE(writer.write("%d %x\n", 42, 42));
0058         expectedContents << "42 2a\n";
0059         if (i % 1000 == 0) {
0060             const string longString(LineWriter::BUFFER_CAPACITY * 2, '*');
0061             REQUIRE(writer.write(longString));
0062             expectedContents << std::hex << longString.size() << ' ' << longString;
0063         }
0064     }
0065     for (unsigned i = 0; i < LineWriter::BUFFER_CAPACITY * 2; ++i) {
0066         const string longString(i, '*');
0067         REQUIRE(writer.write(longString));
0068         expectedContents << std::hex << longString.size() << ' ' << longString;
0069     }
0070 
0071     expectedContents.flush();
0072 
0073     REQUIRE(expectedContents.str().size() > LineWriter::BUFFER_CAPACITY);
0074     REQUIRE(writer.flush());
0075 
0076     REQUIRE(file.readContents() == expectedContents.str());
0077 }
0078 
0079 TEST_CASE ("buffered writeHex") {
0080     TempFile file;
0081     REQUIRE(file.open());
0082 
0083     LineWriter writer(file.fd);
0084     REQUIRE(writer.canWrite());
0085     string expectedContents;
0086     for (unsigned i = 0; i < 10000; ++i) {
0087         REQUIRE(writer.writeHexLine('t', 0x123u, 0x456u));
0088         expectedContents += "t 123 456\n";
0089     }
0090     REQUIRE(expectedContents.size() > LineWriter::BUFFER_CAPACITY);
0091     REQUIRE(writer.flush());
0092 
0093     REQUIRE(file.readContents() == expectedContents);
0094 }
0095 
0096 TEST_CASE ("write flush") {
0097     TempFile file;
0098     REQUIRE(file.open());
0099 
0100     LineWriter writer(file.fd);
0101     REQUIRE(writer.canWrite());
0102 
0103     string data1(LineWriter::BUFFER_CAPACITY - 10, '#');
0104     REQUIRE(writer.write(data1.c_str()));
0105     // not yet written
0106     REQUIRE(file.readContents().empty());
0107 
0108     // NOTE: while this data would fit,
0109     //       snprintf used by the writer tries to append a \0 too which doesn't fit
0110     string data2(10, '+');
0111     REQUIRE(writer.write(data2.c_str()));
0112     // so the above flushes, but only the first chunk
0113     REQUIRE(file.readContents() == data1);
0114 
0115     writer.flush();
0116     REQUIRE(file.readContents() == data1 + data2);
0117 }
0118 
0119 TEST_CASE ("read line 64bit") {
0120     const string contents =
0121         "m /tmp/KDevelop-5.2.1-x86_64/usr/lib/libKF5Completion.so.5 7f48beedc00 0 36854 236858 2700\n";
0122     stringstream stream(contents);
0123 
0124     LineReader reader;
0125     REQUIRE(reader.getLine(stream));
0126     REQUIRE(reader.line()
0127             == "m /tmp/KDevelop-5.2.1-x86_64/usr/lib/libKF5Completion.so.5 7f48beedc00 0 36854 236858 2700");
0128     REQUIRE(reader.mode() == 'm');
0129 
0130     string module;
0131     REQUIRE((reader >> module));
0132     REQUIRE(module == "/tmp/KDevelop-5.2.1-x86_64/usr/lib/libKF5Completion.so.5");
0133 
0134     for (auto expected : {0x7f48beedc00_u64, 0x0_u64, 0x36854_u64, 0x236858_u64, 0x2700_u64}) {
0135         uint64_t addr = 0;
0136         REQUIRE((reader >> addr));
0137         REQUIRE(addr == expected);
0138     }
0139 
0140     uint64_t x = 0;
0141     REQUIRE(!(reader >> x));
0142     REQUIRE(!(reader >> module));
0143 }
0144 
0145 TEST_CASE ("read line 32bit") {
0146     const string contents = "t 4 3\n"
0147                             "a 11c00 4\n"
0148                             "+ 0\n";
0149     stringstream stream(contents);
0150     LineReader reader;
0151     uint32_t idx = 0;
0152 
0153     REQUIRE(reader.getLine(stream));
0154     REQUIRE(reader.line() == "t 4 3");
0155     REQUIRE(reader.mode() == 't');
0156     REQUIRE((reader >> idx));
0157     REQUIRE(idx == 0x4);
0158     REQUIRE((reader >> idx));
0159     REQUIRE(idx == 0x3);
0160     REQUIRE(!(reader >> idx));
0161 
0162     REQUIRE(reader.getLine(stream));
0163     REQUIRE(reader.line() == "a 11c00 4");
0164     REQUIRE(reader.mode() == 'a');
0165     REQUIRE((reader >> idx));
0166     REQUIRE(idx == 0x11c00);
0167     REQUIRE((reader >> idx));
0168     REQUIRE(idx == 0x4);
0169     REQUIRE(!(reader >> idx));
0170 
0171     REQUIRE(reader.getLine(stream));
0172     REQUIRE(reader.line() == "+ 0");
0173     REQUIRE(reader.mode() == '+');
0174 
0175     REQUIRE((reader >> idx));
0176     REQUIRE(idx == 0x0);
0177     REQUIRE(!(reader >> idx));
0178 }