File indexing completed on 2023-12-03 12:33:13
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 }