Fixes to the unittests
[amule.git] / unittests / tests / FileDataIOTest.cpp
blobcdb24c6524a934d715f0acdadc2dbf0aadf1d0b3
1 #include <muleunit/test.h>
2 #include <CFile.h>
3 #include <MemFile.h>
4 #include <MD4Hash.h>
5 #include <limits>
6 #include <kademlia/utils/UInt128.h>
8 using Kademlia::CUInt128;
9 using namespace muleunit;
11 namespace muleunit
13 template <>
14 wxString StringFrom<CPath>(const CPath& path)
16 return path.GetPrintable();
21 //! The max file-size of auto-generated files to test.
22 const size_t TEST_LENGTH = 512;
24 namespace muleunit {
25 //! Needed for ASSERT_EQUALS with CMD4Hash values
26 template <>
27 wxString StringFrom<CMD4Hash>(const CMD4Hash& hash) {
28 return hash.Encode();
31 //! Needed for ASSERT_EQUALS with CUInt128 values
32 template <>
33 wxString StringFrom<CUInt128>(const CUInt128& value) {
34 return value.ToHexString();
39 void writePredefData(CFileDataIO* file)
41 char data[TEST_LENGTH];
43 for (size_t j = 0; j < TEST_LENGTH; ++j) {
44 data[j] = j & 0xff;
47 file->Write(data, TEST_LENGTH);
48 file->Seek(0, wxFromStart);
53 /////////////////////////////////////////////////////////////////////
54 // Specialize this template for each implemention
55 // of the CFileDataIO interface you wish to test.
57 // This struct must be a subclass of Test.
59 // Two pointers are to be defined:
60 // m_emptyFile, which must be an empty, zero-length file
61 // m_predefFile, which must be TEST_LENGTH in size and
62 // and contain the sequence 0..255 repeated
63 // as needed.
65 // The following functions should be overridden:
66 // - setUp()
67 // - tearDown()
69 template <typename TYPE>
70 struct FileDataIOFixture;
73 template <>
74 class FileDataIOFixture<CFile> : public Test
76 public:
77 FileDataIOFixture(const wxString& testName)
78 : Test(wxT("FileDataIO"), wxT("CFile - ") + testName) {}
81 CFile* m_emptyFile;
82 CFile* m_predefFile;
84 void setUp() {
85 m_emptyFile = m_predefFile = NULL;
86 const CPath emptyPath = CPath(wxT("FileDataIOTest.empty"));
87 const CPath datPath = CPath(wxT("FileDataIOTest.dat"));
89 m_emptyFile = new CFile();
90 m_emptyFile->Create(emptyPath, true);
91 ASSERT_TRUE(m_emptyFile->IsOpened());
92 m_emptyFile->Close();
93 m_emptyFile->Open(emptyPath, CFile::read_write);
94 ASSERT_TRUE(m_emptyFile->IsOpened());
96 m_predefFile = new CFile();
97 m_predefFile->Create(datPath, true);
98 ASSERT_TRUE(m_predefFile->IsOpened());
99 m_predefFile->Close();
100 m_predefFile->Open(datPath, CFile::read_write);
101 ASSERT_TRUE(m_predefFile->IsOpened());
103 writePredefData(m_predefFile);
104 ASSERT_EQUALS(0u, m_predefFile->GetPosition());
105 ASSERT_EQUALS(TEST_LENGTH, m_predefFile->GetLength());
108 void tearDown() {
109 delete m_emptyFile;
110 delete m_predefFile;
112 wxRemoveFile(wxT("FileDataIOTest.dat"));
113 wxRemoveFile(wxT("FileDataIOTest.empty"));
118 template <>
119 class FileDataIOFixture<CMemFile> : public Test
121 public:
122 FileDataIOFixture(const wxString& testName)
123 : Test(wxT("FileDataIO"), wxT("CMemFile - ") + testName) {}
126 CMemFile* m_emptyFile;
127 CMemFile* m_predefFile;
129 void setUp() {
130 m_emptyFile = m_predefFile = NULL;
132 m_emptyFile = new CMemFile();
133 m_predefFile = new CMemFile();
135 writePredefData(m_predefFile);
136 ASSERT_EQUALS(0u, m_predefFile->GetPosition());
137 ASSERT_EQUALS(TEST_LENGTH, m_predefFile->GetLength());
140 void tearDown() {
141 delete m_emptyFile;
142 delete m_predefFile;
147 /////////////////////////////////////////////////////////////////////
148 // A writeWrite interface should be implemented for each set of
149 // read/write functions that is to be tested. The following 3
150 // static functions must be implemented in each specialization of the
151 // template:
153 // - TYPE genValue(size_t j), which returns the expected value at
154 // position j in the files with predefined data.
155 // - TYPE readValue(CFileDataIO*), which returns and returns the
156 // value at the current position in the file.
157 // - void writeValue(CFileDataIO*, TYPE), which writes the given
158 // value at the current position in the file.
159 // - wxString name(), which returns the human-readble name of the type
161 template <typename TYPE>
162 struct RWInterface;
164 template <>
165 struct RWInterface<uint8>
167 static uint8 genValue(size_t j) {
168 return j & 0xff;
171 static uint8 readValue(CFileDataIO* file) {
172 return file->ReadUInt8();
175 static void writeValue(CFileDataIO* file, uint8 value) {
176 file->WriteUInt8(value);
179 static wxString name() { return wxT("UInt8"); }
183 template <>
184 struct RWInterface<uint16>
186 static uint16 genValue(size_t j) {
187 return (((j + 1) & 0xff) << 8) | (j & 0xff);
190 static uint16 readValue(CFileDataIO* file) {
191 return file->ReadUInt16();
194 static void writeValue(CFileDataIO* file, uint16 value) {
195 file->WriteUInt16(value);
198 static wxString name() { return wxT("UInt16"); }
202 template <>
203 struct RWInterface<uint32>
205 static uint32 genValue(size_t j) {
206 return (((j + 3) & 0xff) << 24) | (((j + 2) & 0xff) << 16) | (((j + 1) & 0xff) << 8) | (j & 0xff);
209 static uint32 readValue(CFileDataIO* file) {
210 return file->ReadUInt32();
213 static void writeValue(CFileDataIO* file, uint32 value) {
214 file->WriteUInt32(value);
217 static wxString name() { return wxT("UInt32"); }
221 template <>
222 struct RWInterface<CMD4Hash>
224 static CMD4Hash genValue(size_t j) {
225 CMD4Hash value;
226 for (size_t y = j; y < j + 16; y++) {
227 value[y - j] = y & 0xff;
230 return value;
233 static CMD4Hash readValue(CFileDataIO* file) {
234 return file->ReadHash();
237 static void writeValue(CFileDataIO* file, CMD4Hash value) {
238 file->WriteHash(value);
241 static wxString name() { return wxT("CMD4Hash"); }
245 template <>
246 struct RWInterface<CUInt128>
248 static CUInt128 genValue(size_t j) {
249 CUInt128 value;
250 for (size_t y = 0; y < 16; y += 4) {
251 value.Set32BitChunk(y >> 2,
252 ((j + y ) & 0xff) |
253 ((j + y + 1) & 0xff) << 8 |
254 ((j + y + 2) & 0xff) << 16 |
255 ((j + y + 3) & 0xff) << 24);
258 return value;
261 static CUInt128 readValue(CFileDataIO* file) {
262 return file->ReadUInt128();
265 static void writeValue(CFileDataIO* file, CUInt128 value) {
266 file->WriteUInt128(value);
269 static wxString name() { return wxT("CUInt128"); }
273 /////////////////////////////////////////////////////////////////////
274 // The following tests ensure that the given implementations
275 // of the CFileDataIO interface properly does so.
277 template <typename IMPL, typename TYPE, size_t SIZE>
278 class ReadTest : public FileDataIOFixture<IMPL>
280 typedef RWInterface<TYPE> RW;
282 public:
283 ReadTest()
284 : FileDataIOFixture<IMPL>(wxT("Read ") + RW::name()) {}
286 void run() {
287 CFileDataIO* file = this->m_predefFile;
289 for (size_t j = 0; j < TEST_LENGTH + 1 - SIZE; ++j) {
290 ASSERT_EQUALS(j, file->Seek(j, wxFromStart));
291 ASSERT_EQUALS(j, file->GetPosition());
292 ASSERT_EQUALS(RW::genValue(j), RW::readValue(file));
293 ASSERT_EQUALS(j + SIZE, file->GetPosition());
296 ASSERT_EQUALS(TEST_LENGTH, file->GetLength());
298 // Check reads past EOF
299 for (size_t i = 0; i < SIZE; ++i) {
300 ASSERT_EQUALS(TEST_LENGTH - i, file->Seek(-(signed)i, wxFromEnd));
301 ASSERT_RAISES(CEOFException, RW::readValue(file));
304 // Check that only the given length is written to the target buffer
305 char testBuffer[32];
306 memset(testBuffer, 127, 32);
307 char* buf = testBuffer + 8;
309 for (int i = 0; i < 16; ++i) {
310 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
311 ASSERT_EQUALS(0u, file->GetPosition());
313 file->Read(buf, i + 1);
315 for (int j = 0; j < 32; ++j) {
316 if (j < 8 || j > i + 8) {
317 ASSERT_EQUALS(127, (int)testBuffer[j]);
318 } else {
319 ASSERT_EQUALS(j - 8, (int)testBuffer[j]);
327 template <typename IMPL, typename TYPE, size_t SIZE>
328 class WriteTest : public FileDataIOFixture<IMPL>
330 typedef RWInterface<TYPE> RW;
332 public:
333 WriteTest()
334 : FileDataIOFixture<IMPL>(wxT("Write ") + RW::name()) {}
336 void run() {
337 const unsigned char CanaryData = 170;
338 const unsigned char canaryBlock[] = { CanaryData };
340 CFileDataIO* file = this->m_predefFile;
342 for (size_t j = 0; j < TEST_LENGTH + 1 - SIZE; ++j) {
343 // Clear before, after and at the target byte(s)
344 for (int t = -static_cast<int>(SIZE); t < (int)(2*SIZE); ++t) {
345 if ((j + t) < TEST_LENGTH && ((int)j + t) >= 0) {
346 file->Seek(j + t, wxFromStart);
347 ASSERT_EQUALS(j + t, file->GetPosition());
348 file->Write(canaryBlock, 1);
349 ASSERT_EQUALS(j + t + 1, file->GetPosition());
351 // Check that canary was written
352 file->Seek(j + t, wxFromStart);
353 ASSERT_EQUALS(CanaryData, file->ReadUInt8());
354 ASSERT_EQUALS(j + t + 1, file->GetPosition());
358 file->Seek(j, wxFromStart);
360 ASSERT_EQUALS(j, file->GetPosition());
361 RW::writeValue(file, RW::genValue(j));
362 ASSERT_EQUALS(j + SIZE, file->GetPosition());
364 // Check before, after and at the target byte
365 for (int t = -static_cast<int>(SIZE); t < (int)(2*SIZE); ++t) {
366 if ((j + t) < TEST_LENGTH && ((int)j + t) >= 0) {
367 if (t) {
368 if (t < 0 || t >= (int)SIZE) {
369 file->Seek(j + t, wxFromStart);
370 ASSERT_EQUALS(CanaryData, file->ReadUInt8());
371 ASSERT_EQUALS(j + t + 1, file->GetPosition());
373 } else {
374 file->Seek(j + t, wxFromStart);
375 ASSERT_EQUALS(RW::genValue(j), RW::readValue(file));
376 ASSERT_EQUALS(j + t + SIZE, file->GetPosition());
382 ASSERT_EQUALS(TEST_LENGTH, file->GetLength());
387 template <typename IMPL>
388 class SeekTest : public FileDataIOFixture<IMPL>
390 public:
391 SeekTest()
392 : FileDataIOFixture<IMPL>(wxT("Seek")) {}
394 void run() {
395 CFileDataIO* file = this->m_predefFile;
397 ASSERT_EQUALS(0u, file->GetPosition());
398 for (size_t pos = 0; pos < TEST_LENGTH * 2; pos += pos + 1) {
399 ASSERT_EQUALS(pos, file->Seek(pos, wxFromStart));
400 ASSERT_EQUALS(pos, file->GetPosition());
403 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
404 ASSERT_EQUALS(0u, file->GetPosition());
406 for (size_t pos = 0, cur = 0; pos < TEST_LENGTH * 2; pos += ++cur) {
407 ASSERT_EQUALS(pos, file->Seek(cur, wxFromCurrent));
408 ASSERT_EQUALS(pos, file->GetPosition());
411 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
412 ASSERT_EQUALS(0u, file->GetPosition());
414 for (size_t pos = 0; pos < TEST_LENGTH; pos += pos + 1) {
415 ASSERT_EQUALS(TEST_LENGTH - pos, file->Seek(-(signed)pos, wxFromEnd));
416 ASSERT_EQUALS(TEST_LENGTH - pos, file->GetPosition());
419 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
420 ASSERT_EQUALS(0u, file->GetPosition());
422 // Seek to negative is invalid
423 for (off_t pos = 1; pos < 10; ++pos) {
424 ASSERT_RAISES(CInvalidParamsEx, file->Seek(-1 * pos));
425 ASSERT_EQUALS(0u, file->GetPosition());
428 // Corner-case
429 ASSERT_RAISES(CInvalidParamsEx, file->Seek(std::numeric_limits<off_t>::min()));
430 ASSERT_EQUALS(0u, file->GetPosition());
435 template <typename IMPL>
436 class WritePastEndTest : public FileDataIOFixture<IMPL>
438 public:
439 WritePastEndTest()
440 : FileDataIOFixture<IMPL>(wxT("Write Past End")) {}
442 void run() {
443 CFileDataIO* file = this->m_emptyFile;
445 ASSERT_EQUALS(0u, file->GetLength());
446 ASSERT_EQUALS(0u, file->GetPosition());
448 file->WriteUInt8(0);
450 ASSERT_EQUALS(1u, file->GetLength());
451 ASSERT_EQUALS(1u, file->GetPosition());
453 file->WriteUInt16(0);
455 ASSERT_EQUALS(3u, file->GetLength());
456 ASSERT_EQUALS(3u, file->GetPosition());
458 file->WriteUInt32(0);
460 ASSERT_EQUALS(7u, file->GetLength());
461 ASSERT_EQUALS(7u, file->GetPosition());
463 file->WriteHash(CMD4Hash());
465 ASSERT_EQUALS(23u, file->GetLength());
466 ASSERT_EQUALS(23u, file->GetPosition());
468 // TODO: ReadUInt128
471 char tmp[42];
472 memset(tmp, 0, 42);
473 file->Write(tmp, 42);
475 ASSERT_EQUALS(65u, file->GetLength());
476 ASSERT_EQUALS(65u, file->GetPosition());
478 // Check that the length is always increased, regardless of starting pos
479 size_t length = file->GetLength();
480 for (size_t j = 0; j < 16; ++j) {
481 ASSERT_EQUALS(length + j - 15u, file->Seek(-15, wxFromEnd));
482 ASSERT_EQUALS(length + j - 15u, file->GetPosition());
483 file->WriteHash(CMD4Hash());
484 ASSERT_EQUALS(length + j + 1u, file->GetLength());
485 ASSERT_EQUALS(length + j + 1u, file->GetPosition());
491 template <typename IMPL>
492 class StringTest : public FileDataIOFixture<IMPL>
494 public:
495 StringTest()
496 : FileDataIOFixture<IMPL>(wxT("String")) {}
498 struct Encoding
500 const EUtf8Str id;
501 const char* header;
502 const size_t headLen;
505 struct TestString
507 const wxChar* str;
508 // Raw and UTF8 expected lengths ...
509 const size_t lengths[2];
512 void run() {
513 CFileDataIO* file = this->m_emptyFile;
515 // TODO: Need to test non-ascii values when using unicode/etc, zero-length lengthfields
516 Encoding encodings[] =
518 {utf8strNone, NULL, 0},
519 {utf8strOptBOM, "\xEF\xBB\xBF", 3},
520 {utf8strRaw, NULL, 0}
523 TestString testData[] =
525 { wxT("0123456789abcdef"), { 16, 16 } },
526 { wxT(""), { 0, 0 } },
527 { wxT("abc ø def æ ghi å"), { 17, 20 } },
528 { wxT("aáeéuúó"), { 7, 11 } },
529 { wxT("uüoöÿeëaäyÿ"), { 11, 17 } },
533 for (size_t str = 0; str < ArraySize(testData); ++str) {
534 CONTEXT(wxString(wxT("Testing string: '")) << testData[str].str << wxT("'"));
536 for (size_t enc = 0; enc < ArraySize(encodings); ++enc) {
537 CONTEXT(wxString::Format(wxT("Testing encoding: %i"), encodings[enc].id));
539 const wxChar* curStr = testData[str].str;
540 size_t strLen = testData[str].lengths[(encodings[enc].id == utf8strNone) ? 0 : 1];
541 size_t headLen = encodings[enc].headLen;
543 file->WriteString(curStr, encodings[enc].id, 2);
544 ASSERT_EQUALS(strLen + 2 + headLen, file->GetPosition());
545 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
546 ASSERT_EQUALS(strLen + headLen, file->ReadUInt16());
548 // Check header (if any)
549 if (encodings[enc].header) {
550 wxCharBuffer head(headLen);
551 file->Read(head.data(), headLen);
552 ASSERT_EQUALS(0, memcmp(head, encodings[enc].header, headLen));
555 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
556 ASSERT_EQUALS(curStr, file->ReadString(encodings[enc].id, 2));
557 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
560 file->WriteString(curStr, encodings[enc].id, 4);
561 ASSERT_EQUALS(strLen + 4 + headLen, file->GetPosition());
562 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
563 ASSERT_EQUALS(strLen + headLen, file->ReadUInt32());
565 // Check header (if any)
566 if (encodings[enc].header) {
567 wxCharBuffer head(headLen);
568 file->Read(head.data(), headLen);
569 ASSERT_EQUALS(0, memcmp(head, encodings[enc].header, headLen));
572 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
573 ASSERT_EQUALS(curStr, file->ReadString(encodings[enc].id, 4));
574 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
578 CAssertOff silence;
579 for (size_t enc = 0; enc < ArraySize(encodings); ++enc) {
580 CONTEXT(wxString::Format(wxT("Testing encoding against poisoning: %i"), encodings[enc].id));
582 //////////////////////////////////////////////
583 // Check if we guard against "poisoning".
584 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
586 const size_t rawLen = (((uint16)-1) * 3) / 4;
587 wxString badStr(wxT('\xfe'), rawLen);
589 // This will cause the string to be UTF-8 encoded,
590 // thereby exceeding the max length-field size (16b).
591 file->WriteString(badStr, encodings[enc].id, 2);
592 file->WriteUInt16(0x7913);
594 ASSERT_EQUALS(0u, file->Seek(0, wxFromStart));
595 file->ReadString(true, 2);
596 ASSERT_EQUALS(0x7913, file->ReadUInt16());
602 // Do not attempt to use this test with CMemFile.
603 template <typename IMPL>
604 class LargeFileTest : public FileDataIOFixture<IMPL>
606 public:
607 LargeFileTest()
608 : FileDataIOFixture<IMPL>(wxT("LargeFile")) {}
610 void run() {
611 CFile* file = dynamic_cast<CFile*>(this->m_emptyFile);
613 ASSERT_TRUE(file != NULL);
614 ASSERT_EQUALS(2147483647UL, file->Seek(2147483647L, wxFromStart));
615 ASSERT_EQUALS(2147483648UL, file->Seek(1, wxFromCurrent));
616 ASSERT_EQUALS(2147483648UL, file->GetPosition());
617 ASSERT_EQUALS(4294967296ULL, file->Seek(4294967296ULL, wxFromStart));
618 ASSERT_EQUALS(4294967296ULL, file->GetPosition());
624 /////////////////////////////////////////////////////////////////////
625 // Registration of all tests
627 ReadTest<CFile, uint8, 1> CFileReadUInt8Test;
628 ReadTest<CFile, uint16, 2> CFileReadUInt16Test;
629 ReadTest<CFile, uint32, 4> CFileReadUInt32Test;
630 ReadTest<CFile, CMD4Hash, 16> CFileReadCMD4HashTest;
631 ReadTest<CFile, CUInt128, 16> CFileReadCUInt128Test;
633 WriteTest<CFile, uint8, 1> CFileWriteUInt8Test;
634 WriteTest<CFile, uint16, 2> CFileWriteUInt16Test;
635 WriteTest<CFile, uint32, 4> CFileWriteUInt32Test;
636 WriteTest<CFile, CMD4Hash, 16> CFileWriteCMD4HashTest;
637 WriteTest<CFile, CUInt128, 16> CFileWriteCUInt128Test;
639 SeekTest<CFile> CFileSeekTest;
640 WritePastEndTest<CFile> CFileWritePastEnd;
641 StringTest<CFile> CFileStringTest;
643 LargeFileTest<CFile> CFileLargeFileTest;
646 ReadTest<CMemFile, uint8, 1> CMemFileReadUInt8Test;
647 ReadTest<CMemFile, uint16, 2> CMemFileReadUInt16Test;
648 ReadTest<CMemFile, uint32, 4> CMemFileReadUInt32Test;
649 ReadTest<CMemFile, CMD4Hash, 16> CMemFileReadCMD4HashTest;
650 ReadTest<CMemFile, CUInt128, 16> CMemFileReadCUInt128Test;
652 WriteTest<CMemFile, uint8, 1> CMemFileWriteUInt8Test;
653 WriteTest<CMemFile, uint16, 2> CMemFileWriteUInt16Test;
654 WriteTest<CMemFile, uint32, 4> CMemFileWriteUInt32Test;
655 WriteTest<CMemFile, CMD4Hash, 16> CMemFileWriteCMD4HashTest;
656 WriteTest<CMemFile, CUInt128, 16> CMemFileWriteCUInt128Test;
658 SeekTest<CMemFile> CMemFileSeekTest;
659 WritePastEndTest<CMemFile> CMemFileWritePastEnd;
660 StringTest<CMemFile> CMemFileStringTest;
663 /////////////////////////////////////////////////////////////////////
664 // CMemFile specific tests
666 DECLARE_SIMPLE(CMemFile);
668 TEST(CMemFile, AttachedBuffer)
670 const size_t BufferLength = 1024;
671 byte buffer[BufferLength];
673 for (size_t i = 0; i < BufferLength; ++i) {
674 buffer[i] = i & 0xFF;
677 CMemFile file(buffer, BufferLength);
678 for (size_t i = 0; i < BufferLength; ++i) {
679 ASSERT_EQUALS(file.ReadUInt8(), i & 0xFF);
682 // Resizing upwards should fail
683 ASSERT_RAISES(CRunTimeException, file.SetLength(BufferLength * 2));
684 ASSERT_EQUALS(BufferLength, file.GetLength());
686 // Resizing downwards should be ok, as should resizes up (but within bufferlen)
687 file.SetLength(BufferLength / 2);
688 ASSERT_EQUALS(BufferLength / 2, file.GetLength());
689 file.SetLength(BufferLength);
690 ASSERT_EQUALS(BufferLength, file.GetLength());
692 // Write past end should fail
693 ASSERT_EQUALS(BufferLength, file.Seek(0, wxFromEnd));
694 ASSERT_RAISES(CRunTimeException, file.WriteUInt8(0));
696 // Init with invalid buffer should fail
697 ASSERT_RAISES(CRunTimeException, new CMemFile(static_cast<const byte*>(NULL), 1024));
698 ASSERT_RAISES(CRunTimeException, new CMemFile(static_cast<byte*>(NULL), 1024));
702 TEST(CMemFile, ConstBuffer)
704 byte arr[10];
705 CMemFile file(const_cast<const byte*>(arr), sizeof(arr));
707 ASSERT_RAISES(CRunTimeException, file.WriteUInt8(0));
708 ASSERT_RAISES(CRunTimeException, file.WriteUInt16(0));
709 ASSERT_RAISES(CRunTimeException, file.WriteUInt32(0));
710 ASSERT_RAISES(CRunTimeException, file.WriteUInt64(0));
712 char buffer[sizeof(arr)];
713 ASSERT_RAISES(CRunTimeException, file.Write(buffer, sizeof(arr)));
717 TEST(CMemFile, SetLength)
719 CMemFile file;
721 ASSERT_EQUALS(0u, file.GetLength());
722 file.SetLength(1024);
723 ASSERT_EQUALS(1024u, file.GetLength());
724 ASSERT_EQUALS(1024u, file.Seek(0, wxFromEnd));
725 file.SetLength(512u);
726 ASSERT_EQUALS(512u, file.GetLength());
727 ASSERT_EQUALS(512u, file.Seek(0, wxFromEnd));
731 /////////////////////////////////////////////////////////////////////
732 // CFile specific tests
734 const CPath testFile = CPath(wxT("TestFile.dat"));
735 const unsigned testMode = 0600;
737 DECLARE(CFile);
738 void setUp() {
739 // Ensure that the testfile doesn't exist
740 if (testFile.FileExists()) {
741 if (!CPath::RemoveFile(testFile)) {
742 MULE_VALIDATE_STATE(false, wxT("Failed to remove temporary file."));
747 void tearDown() {
748 if (testFile.FileExists()) {
749 CPath::RemoveFile(testFile);
752 END_DECLARE;
755 TEST(CFile, Constructor)
757 // Test initial conditions
759 CFile file;
761 ASSERT_TRUE(!file.IsOpened());
762 ASSERT_TRUE(file.fd() == CFile::fd_invalid);
763 ASSERT_RAISES(CRunTimeException, file.WriteUInt8(0));
764 ASSERT_RAISES(CRunTimeException, file.ReadUInt8());
765 ASSERT_RAISES(CRunTimeException, file.Seek(0, wxFromStart));
766 ASSERT_RAISES(CRunTimeException, file.GetLength());
767 ASSERT_RAISES(CRunTimeException, file.GetPosition());
768 ASSERT_RAISES(CRunTimeException, file.SetLength(13));
769 ASSERT_RAISES(CRunTimeException, file.Flush());
770 ASSERT_RAISES(CRunTimeException, file.Close());
771 ASSERT_TRUE(!file.IsOpened());
772 ASSERT_TRUE(file.fd() == CFile::fd_invalid);
775 // Create test file
777 CFile file;
778 ASSERT_TRUE(file.Create(testFile, false, testMode));
779 ASSERT_EQUALS(testFile, file.GetFilePath());
780 file.WriteUInt32(1);
784 CFile file(testFile, CFile::read);
786 ASSERT_TRUE(file.IsOpened());
787 ASSERT_TRUE(file.fd() != CFile::fd_invalid);
788 ASSERT_EQUALS(testFile, file.GetFilePath());
789 ASSERT_EQUALS(4u, file.GetLength());
790 ASSERT_EQUALS(1u, file.ReadUInt32());
792 ASSERT_RAISES(CIOFailureException, file.WriteUInt8(0));
796 CFile file(testFile, CFile::write);
798 ASSERT_TRUE(file.IsOpened());
799 ASSERT_TRUE(file.fd() != CFile::fd_invalid);
800 ASSERT_EQUALS(testFile, file.GetFilePath());
801 ASSERT_EQUALS(0u, file.GetPosition());
802 ASSERT_EQUALS(0u, file.GetLength());
803 file.WriteUInt32(1);
804 ASSERT_EQUALS(0u, file.Seek(0, wxFromStart));
806 ASSERT_RAISES(CIOFailureException, file.ReadUInt8());
810 CFile file(testFile, CFile::read_write);
812 ASSERT_TRUE(file.IsOpened());
813 ASSERT_TRUE(file.fd() != CFile::fd_invalid);
814 ASSERT_EQUALS(testFile, file.GetFilePath());
815 ASSERT_EQUALS(4u, file.GetLength());
816 ASSERT_EQUALS(0u, file.GetPosition());
817 ASSERT_EQUALS(1u, file.ReadUInt32());
818 ASSERT_EQUALS(0u, file.Seek(0, wxFromStart));
819 file.WriteUInt32(2);
820 ASSERT_EQUALS(0u, file.Seek(0, wxFromStart));
821 ASSERT_EQUALS(2u, file.ReadUInt32());
825 CFile file(testFile, CFile::write_append);
827 ASSERT_TRUE(file.IsOpened());
828 ASSERT_TRUE(file.fd() != CFile::fd_invalid);
829 ASSERT_EQUALS(4u, file.GetLength());
830 file.WriteUInt32(1);
831 ASSERT_EQUALS(0u, file.Seek(0, wxFromStart));
833 ASSERT_RAISES(CIOFailureException, file.ReadUInt8());
835 ASSERT_TRUE(file.Close());
836 ASSERT_TRUE(file.Open(testFile, CFile::read));
838 ASSERT_EQUALS(2u, file.ReadUInt32());
839 ASSERT_EQUALS(1u, file.ReadUInt32());
844 TEST(CFile, Create)
846 ASSERT_FALSE(testFile.FileExists());
848 // Check creation of new file, when none exists, with/without overwrite
849 for (size_t i = 0; i < 2; ++i) {
850 bool overwrite = (i == 1);
852 CFile file;
853 ASSERT_TRUE(!file.IsOpened());
854 ASSERT_TRUE(file.fd() == CFile::fd_invalid);
855 ASSERT_TRUE(file.Create(testFile, overwrite, testMode));
856 ASSERT_TRUE(file.IsOpened());
857 ASSERT_TRUE(file.fd() != CFile::fd_invalid);
858 ASSERT_EQUALS(testFile, file.GetFilePath());
859 ASSERT_TRUE(file.Close());
860 ASSERT_TRUE(file.fd() == CFile::fd_invalid);
861 ASSERT_TRUE(!file.IsOpened());
863 ASSERT_TRUE(wxFile::Access(testFile.GetRaw(), wxFile::read));
864 ASSERT_TRUE(wxFile::Access(testFile.GetRaw(), wxFile::write));
866 ASSERT_TRUE(wxRemoveFile(testFile.GetRaw()));
869 // Create testfile, with a bit of contents
871 CFile file;
872 ASSERT_TRUE(file.Create(testFile, false, testMode));
873 ASSERT_EQUALS(testFile, file.GetFilePath());
874 file.WriteUInt32(1);
877 // Check that owerwrite = false works as expected
879 CFile file;
880 ASSERT_FALSE(file.Create(testFile, false, testMode));
881 ASSERT_TRUE(file.fd() == CFile::fd_invalid);
882 ASSERT_TRUE(!file.IsOpened());
884 // Open and check contents
885 ASSERT_TRUE(file.Open(testFile, CFile::read));
886 ASSERT_TRUE(file.IsOpened());
887 ASSERT_TRUE(file.fd() != CFile::fd_invalid);
888 ASSERT_EQUALS(testFile, file.GetFilePath());
889 ASSERT_EQUALS(4u, file.GetLength());
890 ASSERT_EQUALS(1u, file.ReadUInt32());
891 ASSERT_TRUE(file.Close());
892 ASSERT_TRUE(file.fd() == CFile::fd_invalid);
893 ASSERT_TRUE(!file.IsOpened());
896 // Check that owerwrite = true works as expected
898 CFile file;
899 ASSERT_TRUE(file.Create(testFile, true, testMode));
900 ASSERT_TRUE(file.IsOpened());
901 ASSERT_TRUE(file.fd() != CFile::fd_invalid);
902 ASSERT_EQUALS(testFile, file.GetFilePath());
903 ASSERT_EQUALS(0u, file.GetLength());
904 ASSERT_TRUE(file.Close());
905 ASSERT_TRUE(file.fd() == CFile::fd_invalid);
906 ASSERT_TRUE(!file.IsOpened());
909 ASSERT_TRUE(wxFile::Access(testFile.GetRaw(), wxFile::read));
910 ASSERT_TRUE(wxFile::Access(testFile.GetRaw(), wxFile::write));
914 TEST(CFile, SetLength)
916 CFile file(testFile, CFile::write);
918 ASSERT_EQUALS(0u, file.GetLength());
919 file.SetLength(1024);
920 ASSERT_EQUALS(1024u, file.GetLength());
921 ASSERT_EQUALS(1024u, file.Seek(0, wxFromEnd));
922 file.SetLength(512u);
923 ASSERT_EQUALS(512u, file.GetLength());
924 ASSERT_EQUALS(512u, file.Seek(0, wxFromEnd));
928 TEST(CFile, GetAvailable)
931 CFile file(testFile, CFile::write);
933 writePredefData(&file);
936 CFile file(testFile, CFile::read);
938 const uint64 length = file.GetLength();
939 while (!file.Eof()) {
940 ASSERT_EQUALS(length - file.GetPosition(), file.GetAvailable());
941 file.ReadUInt32();
942 ASSERT_EQUALS(length - file.GetPosition(), file.GetAvailable());
945 ASSERT_EQUALS(0u, file.GetAvailable());
947 file.Seek(1024, wxFromCurrent);
949 ASSERT_EQUALS(0u, file.GetAvailable());