C++ Utilities  4.17.0
Useful C++ classes and routines such as argument parser, IO and conversion utilities
iotests.cpp
Go to the documentation of this file.
1 #include "./testutils.h"
2 
3 #include "../conversion/conversionexception.h"
4 #include "../conversion/stringbuilder.h"
5 
6 #include "../io/ansiescapecodes.h"
7 #include "../io/binaryreader.h"
8 #include "../io/binarywriter.h"
9 #include "../io/bitreader.h"
10 #include "../io/catchiofailure.h"
11 #include "../io/copy.h"
12 #include "../io/inifile.h"
13 #include "../io/misc.h"
14 #include "../io/nativefilestream.h"
15 #include "../io/path.h"
16 
17 #include <cppunit/TestFixture.h>
18 #include <cppunit/extensions/HelperMacros.h>
19 
20 #include <algorithm>
21 #include <fstream>
22 #include <regex>
23 #include <sstream>
24 
25 #ifdef PLATFORM_WINDOWS
26 #include <cstdio>
27 #endif
28 
29 #ifdef PLATFORM_UNIX
30 #include <sys/fcntl.h>
31 #include <sys/types.h>
32 #endif
33 
34 using namespace std;
35 using namespace IoUtilities;
36 using namespace TestUtilities;
37 using namespace TestUtilities::Literals;
38 using namespace ConversionUtilities;
39 
40 using namespace CPPUNIT_NS;
41 
45 class IoTests : public TestFixture {
46  CPPUNIT_TEST_SUITE(IoTests);
47 #ifndef PLATFORM_WINDOWS
48  CPPUNIT_TEST(testFailure);
49 #endif
50  CPPUNIT_TEST(testBinaryReader);
51  CPPUNIT_TEST(testBinaryWriter);
52  CPPUNIT_TEST(testBitReader);
53  CPPUNIT_TEST(testPathUtilities);
54  CPPUNIT_TEST(testIniFile);
55  CPPUNIT_TEST(testCopy);
56  CPPUNIT_TEST(testReadFile);
57  CPPUNIT_TEST(testAnsiEscapeCodes);
58 #ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER
59  CPPUNIT_TEST(testNativeFileStream);
60 #endif
61  CPPUNIT_TEST_SUITE_END();
62 
63 public:
64  void setUp();
65  void tearDown();
66 
67 #ifndef PLATFORM_WINDOWS
68  void testFailure();
69 #endif
70  void testBinaryReader();
71  void testBinaryWriter();
72  void testBitReader();
73  void testPathUtilities();
74  void testIniFile();
75  void testCopy();
76  void testReadFile();
77  void testAnsiEscapeCodes();
78 #ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER
79  void testNativeFileStream();
80 #endif
81 };
82 
84 
86 {
87 }
88 
90 {
91 }
92 
93 #ifndef PLATFORM_WINDOWS
94 
103 {
104  // check whether workaround works
105  try {
106  fstream stream;
107  stream.exceptions(ios_base::failbit | ios_base::badbit);
108  stream.open("path/to/file/which/does/not/exist", ios_base::in);
109  } catch (...) {
110  catchIoFailure();
111  }
112 
113  // check other relevatn exceptions, too
114  vector<int> testVec;
115  map<string, string> testMap;
116  CPPUNIT_ASSERT_THROW(testVec.at(1), out_of_range);
117  CPPUNIT_ASSERT_THROW(testMap.at("test"), out_of_range);
118 }
119 #endif
120 
125 {
126  // read test file
127  fstream testFile;
128  testFile.exceptions(ios_base::failbit | ios_base::badbit);
129  testFile.open(TestUtilities::testFilePath("some_data"), ios_base::in | ios_base::binary);
130  BinaryReader reader(&testFile);
131  CPPUNIT_ASSERT_EQUAL(reader.readStreamsize(), static_cast<istream::pos_type>(398));
132  CPPUNIT_ASSERT(reader.readUInt16LE() == 0x0102u);
133  CPPUNIT_ASSERT(reader.readUInt16BE() == 0x0102u);
134  CPPUNIT_ASSERT(reader.readUInt24LE() == 0x010203u);
135  CPPUNIT_ASSERT(reader.readUInt24BE() == 0x010203u);
136  CPPUNIT_ASSERT(reader.readUInt32LE() == 0x01020304u);
137  CPPUNIT_ASSERT(reader.readUInt32BE() == 0x01020304u);
138  CPPUNIT_ASSERT(reader.readUInt40LE() == 0x0102030405u);
139  CPPUNIT_ASSERT(reader.readUInt40BE() == 0x0102030405u);
140  CPPUNIT_ASSERT(reader.readUInt56LE() == 0x01020304050607u);
141  CPPUNIT_ASSERT(reader.readUInt56BE() == 0x01020304050607u);
142  CPPUNIT_ASSERT(reader.readUInt64LE() == 0x0102030405060708u);
143  CPPUNIT_ASSERT(reader.readUInt64BE() == 0x0102030405060708u);
144  testFile.seekg(0);
145  CPPUNIT_ASSERT(reader.readInt16LE() == 0x0102);
146  CPPUNIT_ASSERT(reader.readInt16BE() == 0x0102);
147  CPPUNIT_ASSERT(reader.readInt24LE() == 0x010203);
148  CPPUNIT_ASSERT(reader.readInt24BE() == 0x010203);
149  CPPUNIT_ASSERT(reader.readInt32LE() == 0x01020304);
150  CPPUNIT_ASSERT(reader.readInt32BE() == 0x01020304);
151  CPPUNIT_ASSERT(reader.readInt40LE() == 0x0102030405);
152  CPPUNIT_ASSERT(reader.readInt40BE() == 0x0102030405);
153  CPPUNIT_ASSERT(reader.readInt56LE() == 0x01020304050607);
154  CPPUNIT_ASSERT(reader.readInt56BE() == 0x01020304050607);
155  CPPUNIT_ASSERT(reader.readInt64LE() == 0x0102030405060708);
156  CPPUNIT_ASSERT(reader.readInt64BE() == 0x0102030405060708);
157  CPPUNIT_ASSERT(reader.readFloat32LE() == 1.125);
158  CPPUNIT_ASSERT(reader.readFloat64LE() == 1.625);
159  CPPUNIT_ASSERT(reader.readFloat32BE() == 1.125);
160  CPPUNIT_ASSERT(reader.readFloat64BE() == 1.625);
161  CPPUNIT_ASSERT(reader.readBool() == false);
162  CPPUNIT_ASSERT(reader.readBool() == true);
163  CPPUNIT_ASSERT(reader.readString(3) == "abc");
164  CPPUNIT_ASSERT(reader.readLengthPrefixedString() == "ABC");
165  CPPUNIT_ASSERT(reader.readLengthPrefixedString()
166  == "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"
167  "23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"
168  "45678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345"
169  "678901234567890123456789");
170  CPPUNIT_ASSERT_EQUAL("def"s, reader.readTerminatedString());
171  testFile.seekg(-4, ios_base::cur);
172  CPPUNIT_ASSERT_EQUAL("def"s, reader.readTerminatedString(5, 0));
173  testFile.seekg(-4, ios_base::cur);
174  CPPUNIT_ASSERT_EQUAL("de"s, reader.readMultibyteTerminatedStringBE(5, 0x6600));
175  testFile.seekg(-4, ios_base::cur);
176  CPPUNIT_ASSERT_EQUAL("de"s, reader.readMultibyteTerminatedStringLE(5, 0x0066));
177  testFile.seekg(-4, ios_base::cur);
178  CPPUNIT_ASSERT_EQUAL("de"s, reader.readMultibyteTerminatedStringBE(static_cast<uint16>(0x6600)));
179  testFile.seekg(-4, ios_base::cur);
180  CPPUNIT_ASSERT_EQUAL("de"s, reader.readMultibyteTerminatedStringLE(static_cast<uint16>(0x0066)));
181  CPPUNIT_ASSERT_THROW(reader.readLengthPrefixedString(), ConversionException);
182  CPPUNIT_ASSERT_MESSAGE("pos in stream not advanced on conversion error", reader.readByte() == 0);
183 
184  // test ownership
185  reader.setStream(nullptr, true);
186  reader.setStream(new fstream(), true);
187  BinaryReader reader2(reader);
188  CPPUNIT_ASSERT(reader2.stream() == reader.stream());
189  CPPUNIT_ASSERT(!reader2.hasOwnership());
190  reader.setStream(&testFile, false);
191  reader.setStream(new fstream(), true);
192 }
193 
198 {
199  // prepare reading expected data
200  fstream testFile;
201  testFile.exceptions(ios_base::failbit | ios_base::badbit);
202  testFile.open(TestUtilities::testFilePath("some_data"), ios_base::in | ios_base::binary);
203 
204  // prepare output stream
205  stringstream outputStream(ios_base::in | ios_base::out | ios_base::binary);
206  outputStream.exceptions(ios_base::failbit | ios_base::badbit);
207  char testData[397];
208  outputStream.rdbuf()->pubsetbuf(testData, sizeof(testData));
209 
210  // write test data
211  BinaryWriter writer(&outputStream);
212  writer.writeUInt16LE(0x0102u);
213  writer.writeUInt16BE(0x0102u);
214  writer.writeUInt24LE(0x010203u);
215  writer.writeUInt24BE(0x010203u);
216  writer.writeUInt32LE(0x01020304u);
217  writer.writeUInt32BE(0x01020304u);
218  writer.writeUInt40LE(0x0102030405u);
219  writer.writeUInt40BE(0x0102030405u);
220  writer.writeUInt56LE(0x01020304050607u);
221  writer.writeUInt56BE(0x01020304050607u);
222  writer.writeUInt64LE(0x0102030405060708u);
223  writer.writeUInt64BE(0x0102030405060708u);
224 
225  // test written values
226  for (char c : testData) {
227  CPPUNIT_ASSERT(c == static_cast<char>(testFile.get()));
228  if (testFile.tellg() >= 58) {
229  break;
230  }
231  }
232  testFile.seekg(0);
233  outputStream.seekp(0);
234 
235  // write more test data
236  writer.writeInt16LE(0x0102);
237  writer.writeInt16BE(0x0102);
238  writer.writeInt24LE(0x010203);
239  writer.writeInt24BE(0x010203);
240  writer.writeInt32LE(0x01020304);
241  writer.writeInt32BE(0x01020304);
242  writer.writeInt40LE(0x0102030405);
243  writer.writeInt40BE(0x0102030405);
244  writer.writeInt56LE(0x01020304050607);
245  writer.writeInt56BE(0x01020304050607);
246  writer.writeInt64LE(0x0102030405060708);
247  writer.writeInt64BE(0x0102030405060708);
248  writer.writeFloat32LE(1.125);
249  writer.writeFloat64LE(1.625);
250  writer.writeFloat32BE(1.125);
251  writer.writeFloat64BE(1.625);
252  writer.writeBool(false);
253  writer.writeBool(true);
254  writer.writeString("abc");
255  writer.writeLengthPrefixedString("ABC");
256  writer.writeLengthPrefixedString("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
257  "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"
258  "234567890123456789012345678901234567890123456789012345678901234567890123456789");
259  writer.writeTerminatedString("def");
260 
261  // test written values
262  for (char c : testData) {
263  CPPUNIT_ASSERT(c == static_cast<char>(testFile.get()));
264  }
265 
266  // test ownership
267  writer.setStream(nullptr, true);
268  writer.setStream(new fstream(), true);
269  BinaryWriter writer2(writer);
270  CPPUNIT_ASSERT(writer2.stream() == writer.stream());
271  CPPUNIT_ASSERT(!writer2.hasOwnership());
272  writer.setStream(&testFile, false);
273  writer.setStream(new fstream(), true);
274 }
275 
280 {
281  const byte testData[] = { 0x81, 0x90, 0x3C, 0x44, 0x28, 0x00, 0x44, 0x10, 0x20, 0xFF, 0xFA };
282  BitReader reader(reinterpret_cast<const char *>(testData), sizeof(testData));
283  CPPUNIT_ASSERT(reader.readBit() == 1);
284  reader.skipBits(6);
285  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(3), reader.showBits<byte>(2));
286  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(3), reader.readBits<byte>(2));
287  CPPUNIT_ASSERT_EQUAL(static_cast<uint32>(0x103C4428 << 1), reader.readBits<uint32>(32));
288  reader.align();
289  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(0x44), reader.readBits<byte>(8));
290  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(7), reader.readUnsignedExpGolombCodedBits<byte>());
291  CPPUNIT_ASSERT_EQUAL(static_cast<sbyte>(4), reader.readSignedExpGolombCodedBits<sbyte>());
292  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(0), reader.readBit());
293  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(0), reader.readBit());
294  reader.skipBits(8 + 4);
295  CPPUNIT_ASSERT_EQUAL(4_st, reader.bitsAvailable());
296  CPPUNIT_ASSERT_EQUAL(static_cast<byte>(0xA), reader.readBits<byte>(4));
297  try {
298  reader.readBit();
299  CPPUNIT_FAIL("no exception");
300  } catch (...) {
301 #ifndef PLATFORM_WINDOWS
302  catchIoFailure();
303 #endif
304  }
305  try {
306  reader.skipBits(1);
307  CPPUNIT_FAIL("no exception");
308  } catch (...) {
309 #ifndef PLATFORM_WINDOWS
310  catchIoFailure();
311 #endif
312  }
313  reader.reset(reinterpret_cast<const char *>(testData), sizeof(testData));
314  CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(8 * sizeof(testData)), reader.bitsAvailable());
315 }
316 
321 {
322  CPPUNIT_ASSERT_EQUAL("libc++utilities.so"s, fileName("C:\\libs\\libc++utilities.so"));
323  CPPUNIT_ASSERT_EQUAL("libc++utilities.so"s, fileName("C:\\libs/libc++utilities.so"));
324  CPPUNIT_ASSERT_EQUAL("libc++utilities.so"s, fileName("/usr/lib/libc++utilities.so"));
325  CPPUNIT_ASSERT_EQUAL("/usr/lib/"s, directory("/usr/lib/libc++utilities.so"));
326  CPPUNIT_ASSERT_EQUAL(string(), directory("libc++utilities.so"));
327  CPPUNIT_ASSERT_EQUAL("C:\\libs\\"s, directory("C:\\libs\\libc++utilities.so"));
328  CPPUNIT_ASSERT_EQUAL("C:\\libs/"s, directory("C:\\libs/libc++utilities.so"));
329  string invalidPath("lib/c++uti*lities.so?");
330  removeInvalidChars(invalidPath);
331  CPPUNIT_ASSERT(invalidPath == "libc++utilities.so");
332 #ifdef PLATFORM_UNIX
333  const string iniFilePath = TestUtilities::testFilePath("test.ini");
334  const string testFilesDir = iniFilePath.substr(0, iniFilePath.size() - 9);
335  auto testFilesDirEntries = directoryEntries(testFilesDir.c_str(), DirectoryEntryType::All);
336  CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "test.ini") != testFilesDirEntries.cend());
337  CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), ".") != testFilesDirEntries.cend());
338  CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "..") != testFilesDirEntries.cend());
339  testFilesDirEntries = directoryEntries(testFilesDir.c_str(), DirectoryEntryType::Directory);
340  CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "test.ini") == testFilesDirEntries.cend());
341  CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), ".") != testFilesDirEntries.cend());
342  CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "..") != testFilesDirEntries.cend());
343  testFilesDirEntries = directoryEntries(testFilesDir.c_str(), DirectoryEntryType::File);
344  CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "test.ini") != testFilesDirEntries.cend());
345  CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), ".") == testFilesDirEntries.cend());
346  CPPUNIT_ASSERT(find(testFilesDirEntries.cbegin(), testFilesDirEntries.cend(), "..") == testFilesDirEntries.cend());
347 #endif
348 }
349 
354 {
355  // prepare reading test file
356  fstream inputFile;
357  inputFile.exceptions(ios_base::failbit | ios_base::badbit);
358  inputFile.open(TestUtilities::testFilePath("test.ini"), ios_base::in);
359 
360  IniFile ini;
361  ini.parse(inputFile);
362  const auto globalScope = ini.data().at(0);
363  const auto scope1 = ini.data().at(1);
364  const auto scope2 = ini.data().at(2);
365  CPPUNIT_ASSERT(globalScope.first.empty());
366  CPPUNIT_ASSERT(globalScope.second.find("key0") != globalScope.second.cend());
367  CPPUNIT_ASSERT(globalScope.second.find("key0")->second == "value 0");
368  CPPUNIT_ASSERT(globalScope.second.find("key1") == globalScope.second.cend());
369  CPPUNIT_ASSERT(scope1.first == "scope 1");
370  CPPUNIT_ASSERT(scope1.second.find("key1") != scope1.second.cend());
371  CPPUNIT_ASSERT(scope1.second.find("key1")->second == "value 1");
372  CPPUNIT_ASSERT(scope1.second.find("key2") != scope1.second.cend());
373  CPPUNIT_ASSERT(scope1.second.find("key2")->second == "value=2");
374  CPPUNIT_ASSERT(scope2.first == "scope 2");
375  CPPUNIT_ASSERT(scope2.second.find("key5") == scope2.second.cend());
376 
377  // write values to another file
378  fstream outputFile;
379  outputFile.exceptions(ios_base::failbit | ios_base::badbit);
380  outputFile.open(workingCopyPathMode("output.ini", WorkingCopyMode::NoCopy), ios_base::out | ios_base::trunc);
381  ini.make(outputFile);
382 
383  // parse written values (again)
384  outputFile.close();
385  outputFile.open(workingCopyPathMode("output.ini", WorkingCopyMode::NoCopy), ios_base::in);
386  IniFile ini2;
387  ini2.parse(outputFile);
388  CPPUNIT_ASSERT(ini.data() == ini2.data());
389 }
390 
395 {
396  // prepare streams
397  fstream testFile;
398  testFile.exceptions(ios_base::failbit | ios_base::badbit);
399  testFile.open(TestUtilities::testFilePath("some_data"), ios_base::in | ios_base::binary);
400  stringstream outputStream(ios_base::in | ios_base::out | ios_base::binary);
401  outputStream.exceptions(ios_base::failbit | ios_base::badbit);
402 
403  // copy
404  CopyHelper<13> copyHelper;
405  copyHelper.copy(testFile, outputStream, 50);
406 
407  // test
408  testFile.seekg(0);
409  for (byte i = 0; i < 50; ++i) {
410  CPPUNIT_ASSERT(testFile.get() == outputStream.get());
411  }
412 }
413 
418 {
419  // read a file successfully
420  const string iniFilePath(testFilePath("test.ini"));
421  CPPUNIT_ASSERT_EQUAL("# file for testing INI parser\n"
422  "key0=value 0\n"
423  "\n"
424  "[scope 1]\n"
425  "key1=value 1 # comment\n"
426  "key2=value=2\n"
427  "key3=value 3\n"
428  "\n"
429  "[scope 2]\n"
430  "key4=value 4\n"
431  "#key5=value 5\n"
432  "key6=value 6\n"s,
433  readFile(iniFilePath));
434 
435  // fail by exceeding max size
436  try {
437  readFile(iniFilePath, 10);
438  cout << "no exception" << endl;
439  CPPUNIT_FAIL("no exception");
440  } catch (...) {
441 #ifndef PLATFORM_WINDOWS
442  catchIoFailure();
443 #endif
444  }
445 
446  // handle UTF-8 in path and file contents correctly via NativeFileStream
447 #if !defined(PLATFORM_WINDOWS) || defined(CPP_UTILITIES_USE_NATIVE_FILE_BUFFER)
448  CPPUNIT_ASSERT_EQUAL("file with non-ASCII character 'ä' in its name\n"s, readFile(testFilePath("täst.txt")));
449 #endif
450 }
451 
453 {
454  stringstream ss1;
455  EscapeCodes::enabled = true;
456  ss1 << EscapeCodes::Phrases::Error << "some error" << EscapeCodes::Phrases::End;
457  ss1 << EscapeCodes::Phrases::Warning << "some warning" << EscapeCodes::Phrases::End;
458  ss1 << EscapeCodes::Phrases::Info << "some info" << EscapeCodes::Phrases::End;
459  ss1 << EscapeCodes::Phrases::ErrorMessage << "Arch-style error" << EscapeCodes::Phrases::End;
460  ss1 << EscapeCodes::Phrases::WarningMessage << "Arch-style warning" << EscapeCodes::Phrases::End;
461  ss1 << EscapeCodes::Phrases::PlainMessage << "Arch-style message" << EscapeCodes::Phrases::End;
462  ss1 << EscapeCodes::Phrases::SuccessMessage << "Arch-style success" << EscapeCodes::Phrases::End;
463  ss1 << EscapeCodes::Phrases::SubMessage << "Arch-style sub-message" << EscapeCodes::Phrases::End;
465  << "blue, blinking text on red background" << EscapeCodes::TextAttribute::Reset << '\n';
466  cout << "\noutput for formatting with ANSI escape codes:\n" << ss1.str() << "---------------------------------------------\n";
467  fstream("/tmp/test.txt", ios_base::out | ios_base::trunc) << ss1.str();
468  CPPUNIT_ASSERT_EQUAL("\e[1;31mError: \e[0m\e[1msome error\e[0m\n"
469  "\e[1;33mWarning: \e[0m\e[1msome warning\e[0m\n"
470  "\e[1;34mInfo: \e[0m\e[1msome info\e[0m\n"
471  "\e[1;31m==> ERROR: \e[0m\e[1mArch-style error\e[0m\n"
472  "\e[1;33m==> WARNING: \e[0m\e[1mArch-style warning\e[0m\n"
473  " \e[0m\e[1mArch-style message\e[0m\n"
474  "\e[1;32m==> \e[0m\e[1mArch-style success\e[0m\n"
475  "\e[1;32m -> \e[0m\e[1mArch-style sub-message\e[0m\n"
476  "\e[5;34;41mblue, blinking text on red background\e[0m\n"s,
477  ss1.str());
478 
479  stringstream ss2;
480  EscapeCodes::enabled = false;
481  ss2 << EscapeCodes::Phrases::Info << "some info" << EscapeCodes::Phrases::End;
482  CPPUNIT_ASSERT_EQUAL("Info: some info\n"s, ss2.str());
483 }
484 
485 #ifdef CPP_UTILITIES_USE_NATIVE_FILE_BUFFER
486 
489 void IoTests::testNativeFileStream()
490 {
491  // open file by path
492  const auto txtFilePath(workingCopyPath("täst.txt"));
493  NativeFileStream fileStream;
494  fileStream.exceptions(ios_base::badbit | ios_base::failbit);
495  CPPUNIT_ASSERT(!fileStream.is_open());
496  fileStream.open(txtFilePath, ios_base::in);
497  CPPUNIT_ASSERT(fileStream.is_open());
498  CPPUNIT_ASSERT_EQUAL(static_cast<char>(fileStream.get()), 'f');
499  fileStream.seekg(0, ios_base::end);
500  CPPUNIT_ASSERT_EQUAL(fileStream.tellg(), static_cast<NativeFileStream::pos_type>(47));
501  fileStream.close();
502  CPPUNIT_ASSERT(!fileStream.is_open());
503  try {
504  fileStream.open("non existing file", ios_base::in | ios_base::out | ios_base::binary);
505  CPPUNIT_FAIL("expected exception");
506  } catch (...) {
507 #ifdef PLATFORM_WINDOWS
508  //CPPUNIT_ASSERT_EQUAL(string(catchIoFailure()), "CreateFileW failed: iostream error"s);
509 #else
510  CPPUNIT_ASSERT_EQUAL(string(catchIoFailure()), "open failed: iostream error"s);
511 #endif
512  }
513  fileStream.clear();
514 
515  // open file from file descriptor
516 #ifndef PLATFORM_WINDOWS
517  auto readWriteFileDescriptor = open(txtFilePath.data(), O_RDWR);
518  CPPUNIT_ASSERT(readWriteFileDescriptor);
519  fileStream.openFromFileDescriptor(readWriteFileDescriptor, ios_base::in | ios_base::out | ios_base::binary);
520  CPPUNIT_ASSERT(fileStream.is_open());
521  CPPUNIT_ASSERT_EQUAL(static_cast<char>(fileStream.get()), 'f');
522  fileStream.seekg(0, ios_base::end);
523  CPPUNIT_ASSERT_EQUAL(fileStream.tellg(), static_cast<NativeFileStream::pos_type>(47));
524  fileStream.flush();
525  fileStream.close();
526  CPPUNIT_ASSERT(!fileStream.is_open());
527 #endif
528  try {
529  fileStream.openFromFileDescriptor(-1, ios_base::in | ios_base::out | ios_base::binary);
530  fileStream.get();
531  CPPUNIT_FAIL("expected exception");
532  } catch (...) {
533 #ifndef PLATFORM_WINDOWS
534  const string msg = catchIoFailure();
535  TESTUTILS_ASSERT_LIKE("expected error message", "(fdopen failed|failed reading: Bad file descriptor): iostream error", msg);
536 #endif
537  }
538  fileStream.clear();
539 
540  // append + write file via path
541  NativeFileStream fileStream2;
542  fileStream2.exceptions(ios_base::failbit | ios_base::badbit);
543  fileStream2.open(txtFilePath, ios_base::in | ios_base::out | ios_base::app);
544  CPPUNIT_ASSERT(fileStream2.is_open());
545  fileStream2 << "foo";
546  fileStream2.flush();
547  fileStream2.close();
548  CPPUNIT_ASSERT(!fileStream2.is_open());
549  CPPUNIT_ASSERT_EQUAL("file with non-ASCII character 'ä' in its name\nfoo"s, readFile(txtFilePath, 50));
550 
551  // truncate + write file via path
552  fileStream2.open(txtFilePath, ios_base::out | ios_base::trunc);
553  CPPUNIT_ASSERT(fileStream2.is_open());
554  fileStream2 << "bar";
555  fileStream2.close();
556  CPPUNIT_ASSERT(!fileStream2.is_open());
557  CPPUNIT_ASSERT_EQUAL("bar"s, readFile(txtFilePath, 4));
558 
559  // append + write via file descriptor from file handle
560 #ifdef PLATFORM_WINDOWS
561  const auto wideTxtFilePath = NativeFileStream::makeWidePath(txtFilePath);
562  const auto appendFileHandle = _wfopen(wideTxtFilePath.get(), L"a+");
563 #else
564  const auto appendFileHandle = fopen(txtFilePath.data(), "a");
565 #endif
566  CPPUNIT_ASSERT(appendFileHandle);
567  fileStream2.openFromFileDescriptor(fileno(appendFileHandle), ios_base::out | ios_base::app);
568  CPPUNIT_ASSERT(fileStream2.is_open());
569  fileStream2 << "foo";
570  fileStream2.close();
571  CPPUNIT_ASSERT(!fileStream2.is_open());
572  CPPUNIT_ASSERT_EQUAL("barfoo"s, readFile(txtFilePath, 7));
573 }
574 #endif
int64 readInt64LE()
Reads a 64-bit little endian signed integer from the current stream and advances the current position...
Definition: binaryreader.h:477
constexpr auto color(Color foreground, Color background, TextAttribute displayAttribute=TextAttribute::Reset)
bool readBool()
Reads a boolean value from the current stream and advances the current position of the stream by one ...
Definition: binaryreader.h:542
void writeInt24LE(int32 value)
Writes a 24-bit little endian signed integer to the current stream and advances the current position ...
Definition: binarywriter.h:379
float32 readFloat32BE()
Reads a 32-bit big endian floating point value from the current stream and advances the current posit...
Definition: binaryreader.h:351
int64 readInt40BE()
Reads a 40-bit big endian signed integer from the current stream and advances the current position of...
Definition: binaryreader.h:275
int16 readInt16LE()
Reads a 16-bit little endian signed integer from the current stream and advances the current position...
Definition: binaryreader.h:369
void writeFloat64LE(float64 value)
Writes a 64-bit little endian floating point value to the current stream and advances the current pos...
Definition: binarywriter.h:494
void writeInt56LE(int64 value)
Writes a 56-bit big endian signed integer to the current stream and advances the current position of ...
Definition: binarywriter.h:439
Reads primitive data types from a std::istream.
Definition: binaryreader.h:11
float64 readFloat64LE()
Reads a 64-bit little endian floating point value from the current stream and advances the current po...
Definition: binaryreader.h:514
bool hasOwnership() const
Returns whether the writer takes ownership over the assigned stream.
Definition: binarywriter.h:125
int32 readInt32LE()
Reads a 32-bit little endian signed integer from the current stream and advances the current position...
Definition: binaryreader.h:411
Writes primitive data types to a std::ostream.
Definition: binarywriter.h:14
float32 readFloat32LE()
Reads a 32-bit little endian floating point value from the current stream and advances the current po...
Definition: binaryreader.h:505
void testReadFile()
Tests readFile().
Definition: iotests.cpp:417
intType readSignedExpGolombCodedBits()
Reads "Exp-Golomb coded" bits (signed).
Definition: bitreader.h:119
uint32 readUInt24BE()
Reads a 24-bit big endian unsigned integer from the current stream and advances the current position ...
Definition: binaryreader.h:247
int16 readInt16BE()
Reads a 16-bit big endian signed integer from the current stream and advances the current position of...
Definition: binaryreader.h:215
intType readUnsignedExpGolombCodedBits()
Reads "Exp-Golomb coded" bits (unsigned).
Definition: bitreader.h:102
CPP_UTILITIES_EXPORT std::list< std::string > directoryEntries(const char *path, DirectoryEntryType types=DirectoryEntryType::All)
Returns the names of the directory entries in the specified path with the specified types.
Definition: path.cpp:181
The ConversionException class is thrown by the various conversion functions of this library when a co...
void testBinaryReader()
Tests the most important methods of the BinaryReader.
Definition: iotests.cpp:124
void writeInt40LE(int64 value)
Writes a 40-bit big endian signed integer to the current stream and advances the current position of ...
Definition: binarywriter.h:419
The IoTests class tests classes and methods of the IoUtilities namespace.
Definition: iotests.cpp:45
CPP_UTILITIES_EXPORT std::string workingCopyPathMode(const std::string &relativeTestFilePath, WorkingCopyMode mode)
Convenience function to invoke TestApplication::workingCopyPathMode().
Definition: testutils.h:125
void writeUInt24BE(uint32 value)
Writes a 24-bit big endian unsigned integer to the current stream and advances the current position o...
Definition: binarywriter.h:247
#define TESTUTILS_ASSERT_LIKE(message, expectedRegex, actualString)
Asserts whether the specified string matches the specified regex.
Definition: testutils.h:235
void make(std::ostream &outputStream)
Write the current data to the specified outputStream.
Definition: inifile.cpp:153
void testCopy()
Tests CopyHelper.
Definition: iotests.cpp:394
void writeUInt16BE(uint16 value)
Writes a 16-bit big endian unsigned integer to the current stream and advances the current position o...
Definition: binarywriter.h:227
The CopyHelper class helps to copy bytes from one stream to another.
Definition: copy.h:16
void writeUInt56BE(uint64 value)
Writes a 56-bit big endian unsigned integer to the current stream and advances the current position o...
Definition: binarywriter.h:306
int64 readInt64BE()
Reads a 64-bit big endian signed integer from the current stream and advances the current position of...
Definition: binaryreader.h:323
Contains literals to ease asserting with CPPUNIT_ASSERT_EQUAL.
Definition: testutils.h:268
std::fstream NativeFileStream
void writeUInt40BE(uint64 value)
Writes a 40-bit big endian unsigned integer to the current stream and advances the current position o...
Definition: binarywriter.h:286
void writeUInt16LE(uint16 value)
Writes a 16-bit little endian unsigned integer to the current stream and advances the current positio...
Definition: binarywriter.h:369
void writeBool(bool value)
Writes a boolean value to the current stream and advances the current position of the stream by one b...
Definition: binarywriter.h:210
void writeUInt24LE(uint32 value)
Writes a 24-bit little endian unsigned integer to the current stream and advances the current positio...
Definition: binarywriter.h:390
CPP_UTILITIES_EXPORT std::string workingCopyPath(const std::string &relativeTestFilePath)
Convenience function to invoke TestApplication::workingCopyPath().
Definition: testutils.h:116
The BitReader class provides bitwise reading of buffered data.
Definition: bitreader.h:14
float64 readFloat64BE()
Reads a 64-bit big endian floating point value from the current stream and advances the current posit...
Definition: binaryreader.h:360
std::vector< std::pair< std::string, std::multimap< std::string, std::string > > > & data()
Returns the data of the file.
Definition: inifile.h:38
int64 readInt56BE()
Reads a 56-bit big endian signed integer from the current stream and advances the current position of...
Definition: binaryreader.h:299
std::size_t bitsAvailable()
Returns the number of bits which are still available to read.
Definition: bitreader.h:137
uint64 readUInt56LE()
Reads a 56-bit little endian unsigned integer from the current stream and advances the current positi...
Definition: binaryreader.h:467
void writeInt16LE(int16 value)
Writes a 16-bit little endian signed integer to the current stream and advances the current position ...
Definition: binarywriter.h:360
CPP_UTILITIES_EXPORT std::string readFile(const std::string &path, std::string::size_type maxSize=std::string::npos)
Reads all contents of the specified file in a single call.
Definition: misc.cpp:16
bool hasOwnership() const
Returns whether the reader takes ownership over the assigned stream.
Definition: binaryreader.h:132
void writeLengthPrefixedString(const std::string &value)
Writes the length of a string and the string itself to the current stream.
uint32 readUInt32LE()
Reads a 32-bit little endian unsigned integer from the current stream and advances the current positi...
Definition: binaryreader.h:420
CPPUNIT_TEST_SUITE_REGISTRATION(IoTests)
void writeFloat64BE(float64 value)
Writes a 64-bit big endian floating point value to the current stream and advances the current positi...
Definition: binarywriter.h:351
void writeFloat32BE(float32 value)
Writes a 32-bit big endian floating point value to the current stream and advances the current positi...
Definition: binarywriter.h:342
uint32 readUInt32BE()
Reads a 32-bit big endian unsigned integer from the current stream and advances the current position ...
Definition: binaryreader.h:266
Contains utility classes helping to read and write streams.
Definition: binaryreader.h:10
Contains classes and functions utilizing creating of test applications.
Definition: testutils.h:13
void writeUInt40LE(uint64 value)
Writes a 40-bit big endian unsigned integer to the current stream and advances the current position o...
Definition: binarywriter.h:429
std::int8_t sbyte
signed byte
Definition: types.h:9
void setUp()
Definition: iotests.cpp:85
CPP_UTILITIES_EXPORT bool enabled
Controls whether the functions inside the EscapeCodes namespace actually make use of escape codes.
constexpr int i
void testBinaryWriter()
Tests the most important methods of the BinaryWriter.
Definition: iotests.cpp:197
void setStream(std::ostream *stream, bool giveOwnership=false)
Assigns the stream the writer will write to when calling one of the write-methods.
void writeString(const std::string &value)
Writes a string to the current stream and advances the current position of the stream by the length o...
Definition: binarywriter.h:503
uint64 readUInt40BE()
Reads a 40-bit big endian unsigned integer from the current stream and advances the current position ...
Definition: binaryreader.h:289
void writeInt56BE(int64 value)
Writes a 56-bit big endian signed integer to the current stream and advances the current position of ...
Definition: binarywriter.h:296
Contains several functions providing conversions between different data types.
void copy(std::istream &input, std::ostream &output, std::size_t count)
Copies count bytes from input to output.
Definition: copy.h:40
std::istream::pos_type readStreamsize()
Returns the size of the assigned stream.
uint64 readUInt64BE()
Reads a 64-bit big endian unsigned integer from the current stream and advances the current position ...
Definition: binaryreader.h:332
std::uint32_t uint32
unsigned 32-bit integer
Definition: types.h:44
void writeUInt56LE(uint64 value)
Writes a 56-bit big endian unsigned integer to the current stream and advances the current position o...
Definition: binarywriter.h:449
uint16 readUInt16LE()
Reads a 16-bit little endian unsigned integer from the current stream and advances the current positi...
Definition: binaryreader.h:378
uint16 readUInt16BE()
Reads a 16-bit big endian unsigned integer from the current stream and advances the current position ...
Definition: binaryreader.h:224
void writeUInt32LE(uint32 value)
Writes a 32-bit little endian unsigned integer to the current stream and advances the current positio...
Definition: binarywriter.h:409
int32 readInt24LE()
Reads a 24-bit little endian signed integer from the current stream and advances the current position...
Definition: binaryreader.h:387
void writeInt32LE(int32 value)
Writes a 32-bit little endian signed integer to the current stream and advances the current position ...
Definition: binarywriter.h:400
void writeInt16BE(int16 value)
Writes a 16-bit big endian signed integer to the current stream and advances the current position of ...
Definition: binarywriter.h:218
void testPathUtilities()
Tests fileName() and removeInvalidChars().
Definition: iotests.cpp:320
void testIniFile()
Tests IniFile.
Definition: iotests.cpp:353
void writeInt64LE(int64 value)
Writes a 64-bit little endian signed integer to the current stream and advances the current position ...
Definition: binarywriter.h:458
void setStream(std::istream *stream, bool giveOwnership=false)
Assigns the stream the reader will read from when calling one of the read-methods.
CPP_UTILITIES_EXPORT std::string directory(const std::string &path)
Returns the directory of the specified path string (including trailing slash).
Definition: path.cpp:52
std::string readTerminatedString(byte termination=0)
Reads a terminated string from the current stream.
const std::ostream * stream() const
Returns a pointer to the stream the writer will write to when calling one of the write-methods.
Definition: binarywriter.h:113
void writeUInt32BE(uint32 value)
Writes a 32-bit big endian unsigned integer to the current stream and advances the current position o...
Definition: binarywriter.h:266
void writeInt24BE(int32 value)
Writes a 24-bit big endian signed integer to the current stream and advances the current position of ...
Definition: binarywriter.h:237
const std::istream * stream() const
Returns a pointer to the stream the reader will read from when calling one of the read-methods.
Definition: binaryreader.h:120
void skipBits(std::size_t bitCount)
Skips the specified number of bits without reading it.
Definition: bitreader.cpp:19
intType readBits(byte bitCount)
Reads the specified number of bits from the buffer advancing the current position by bitCount bits.
Definition: bitreader.h:68
void writeFloat32LE(float32 value)
Writes a 32-bit little endian floating point value to the current stream and advances the current pos...
Definition: binarywriter.h:485
void parse(std::istream &inputStream)
Parses all data from the specified inputStream.
Definition: inifile.cpp:18
int32 readInt32BE()
Reads a 32-bit big endian signed integer from the current stream and advances the current position of...
Definition: binaryreader.h:257
int32 readInt24BE()
Reads a 24-bit big endian signed integer from the current stream and advances the current position of...
Definition: binaryreader.h:233
void reset(const char *buffer, std::size_t bufferSize)
Resets the reader.
Definition: bitreader.h:148
void writeInt64BE(int64 value)
Writes a 64-bit big endian signed integer to the current stream and advances the current position of ...
Definition: binarywriter.h:315
The IniFile class parses and makes INI files.
Definition: inifile.h:12
void testFailure()
Tests workaround for GCC Bug 66145.
Definition: iotests.cpp:102
std::string readMultibyteTerminatedStringLE(uint16 termination=0)
Reads a multibyte-terminated string from the current stream.
uint32 readUInt24LE()
Reads a 24-bit little endian unsigned integer from the current stream and advances the current positi...
Definition: binaryreader.h:401
int64 readInt56LE()
Reads a 56-bit little endian signed integer from the current stream and advances the current position...
Definition: binaryreader.h:453
byte readByte()
Reads a single byte/unsigned character from the current stream and advances the current position of t...
Definition: binaryreader.h:532
void writeUInt64LE(uint64 value)
Writes a 64-bit little endian unsigned integer to the current stream and advances the current positio...
Definition: binarywriter.h:467
void writeInt32BE(int32 value)
Writes a 32-bit big endian signed integer to the current stream and advances the current position of ...
Definition: binarywriter.h:257
CPP_UTILITIES_EXPORT const char * catchIoFailure()
Provides a workaround for GCC Bug 66145.
CPP_UTILITIES_EXPORT std::string fileName(const std::string &path)
Returns the file name and extension of the specified path string.
Definition: path.cpp:32
uint64 readUInt64LE()
Reads a 64-bit little endian unsigned integer from the current stream and advances the current positi...
Definition: binaryreader.h:486
void testBitReader()
Tests the BitReader.
Definition: iotests.cpp:279
CPP_UTILITIES_EXPORT void removeInvalidChars(std::string &fileName)
Removes invalid characters from the specified fileName.
Definition: path.cpp:74
void align()
Re-establishes alignment.
Definition: bitreader.h:171
void tearDown()
Definition: iotests.cpp:89
std::string readLengthPrefixedString()
Reads a length prefixed string from the current stream.
byte readBit()
Reads the one bit from the buffer advancing the current position by one bit.
Definition: bitreader.h:89
void writeUInt64BE(uint64 value)
Writes a 64-bit big endian unsigned integer to the current stream and advances the current position o...
Definition: binarywriter.h:324
std::string readMultibyteTerminatedStringBE(uint16 termination=0)
Reads a multibyte-terminated string from the current stream.
void writeTerminatedString(const std::string &value)
Writes a terminated string to the current stream and advances the current position of the stream by t...
Definition: binarywriter.h:511
uint64 readUInt56BE()
Reads a 56-bit big endian unsigned integer from the current stream and advances the current position ...
Definition: binaryreader.h:313
std::string readString(std::size_t length)
Reads a string from the current stream of the given length from the stream and advances the current p...
int64 readInt40LE()
Reads a 40-bit little endian signed integer from the current stream and advances the current position...
Definition: binaryreader.h:429
intType showBits(byte bitCount)
Reads the specified number of bits from the buffer without advancing the current position.
Definition: bitreader.h:128
void testAnsiEscapeCodes()
Definition: iotests.cpp:452
CPP_UTILITIES_EXPORT std::string testFilePath(const std::string &relativeTestFilePath)
Convenience function to invoke TestApplication::testFilePath().
Definition: testutils.h:107
uint64 readUInt40LE()
Reads a 40-bit little endian unsigned integer from the current stream and advances the current positi...
Definition: binaryreader.h:443
void writeInt40BE(int64 value)
Writes a 40-bit big endian signed integer to the current stream and advances the current position of ...
Definition: binarywriter.h:276