1 #include <muleunit/test.h>
6 #include <kademlia/utils/UInt128.h>
8 using Kademlia::CUInt128
;
9 using namespace muleunit
;
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;
25 //! Needed for ASSERT_EQUALS with CMD4Hash values
27 wxString StringFrom
<CMD4Hash
>(const CMD4Hash
& hash
) {
31 //! Needed for ASSERT_EQUALS with CUInt128 values
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
) {
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
65 // The following functions should be overridden:
69 template <typename TYPE
>
70 struct FileDataIOFixture
;
74 class FileDataIOFixture
<CFile
> : public Test
77 FileDataIOFixture(const wxString
& testName
)
78 : Test(wxT("FileDataIO"), wxT("CFile - ") + testName
) {}
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());
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());
112 wxRemoveFile(wxT("FileDataIOTest.dat"));
113 wxRemoveFile(wxT("FileDataIOTest.empty"));
119 class FileDataIOFixture
<CMemFile
> : public Test
122 FileDataIOFixture(const wxString
& testName
)
123 : Test(wxT("FileDataIO"), wxT("CMemFile - ") + testName
) {}
126 CMemFile
* m_emptyFile
;
127 CMemFile
* m_predefFile
;
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());
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
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
>
165 struct RWInterface
<uint8
>
167 static uint8
genValue(size_t j
) {
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"); }
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"); }
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"); }
222 struct RWInterface
<CMD4Hash
>
224 static CMD4Hash
genValue(size_t j
) {
226 for (size_t y
= j
; y
< j
+ 16; y
++) {
227 value
[y
- j
] = y
& 0xff;
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"); }
246 struct RWInterface
<CUInt128
>
248 static CUInt128
genValue(size_t j
) {
250 for (size_t y
= 0; y
< 16; y
+= 4) {
251 value
.Set32BitChunk(y
>> 2,
253 ((j
+ y
+ 1) & 0xff) << 8 |
254 ((j
+ y
+ 2) & 0xff) << 16 |
255 ((j
+ y
+ 3) & 0xff) << 24);
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
;
284 : FileDataIOFixture
<IMPL
>(wxT("Read ") + RW::name()) {}
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
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
]);
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
;
334 : FileDataIOFixture
<IMPL
>(wxT("Write ") + RW::name()) {}
337 const unsigned char CanaryData
= 170;
338 const 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
= -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
= -SIZE
; t
< (int)(2*SIZE
); ++t
) {
366 if ((j
+ t
) < TEST_LENGTH
&& ((int)j
+ t
) >= 0) {
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());
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
>
392 : FileDataIOFixture
<IMPL
>(wxT("Seek")) {}
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());
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
>
440 : FileDataIOFixture
<IMPL
>(wxT("Write Past End")) {}
443 CFileDataIO
* file
= this->m_emptyFile
;
445 ASSERT_EQUALS(0u, file
->GetLength());
446 ASSERT_EQUALS(0u, file
->GetPosition());
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());
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
>
496 : FileDataIOFixture
<IMPL
>(wxT("String")) {}
502 const size_t headLen
;
508 // Raw and UTF8 expected lengths ...
509 const size_t lengths
[2];
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
]));
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
));
579 for (size_t enc
= 0; enc
< ArraySize(encodings
); ++enc
) {
580 CONTEXT(wxString::Format(wxT("Testing encoding against poisoning: %i"), encodings
[enc
]));
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
>
608 : FileDataIOFixture
<IMPL
>(wxT("LargeFile")) {}
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
)
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
)
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;
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."));
748 if (testFile
.FileExists()) {
749 CPath::RemoveFile(testFile
);
755 TEST(CFile
, Constructor
)
757 // Test initial conditions
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
.GetFilePath());
770 ASSERT_RAISES(CRunTimeException
, file
.Flush());
771 ASSERT_RAISES(CRunTimeException
, file
.Close());
772 ASSERT_TRUE(!file
.IsOpened());
773 ASSERT_TRUE(file
.fd() == CFile::fd_invalid
);
779 ASSERT_TRUE(file
.Create(testFile
, false, testMode
));
780 ASSERT_EQUALS(testFile
, file
.GetFilePath());
785 CFile
file(testFile
, CFile::read
);
787 ASSERT_TRUE(file
.IsOpened());
788 ASSERT_TRUE(file
.fd() != CFile::fd_invalid
);
789 ASSERT_EQUALS(testFile
, file
.GetFilePath());
790 ASSERT_EQUALS(4u, file
.GetLength());
791 ASSERT_EQUALS(1u, file
.ReadUInt32());
793 ASSERT_RAISES(CIOFailureException
, file
.WriteUInt8(0));
797 CFile
file(testFile
, CFile::write
);
799 ASSERT_TRUE(file
.IsOpened());
800 ASSERT_TRUE(file
.fd() != CFile::fd_invalid
);
801 ASSERT_EQUALS(testFile
, file
.GetFilePath());
802 ASSERT_EQUALS(0u, file
.GetPosition());
803 ASSERT_EQUALS(0u, file
.GetLength());
805 ASSERT_EQUALS(0u, file
.Seek(0, wxFromStart
));
807 ASSERT_RAISES(CIOFailureException
, file
.ReadUInt8());
811 CFile
file(testFile
, CFile::read_write
);
813 ASSERT_TRUE(file
.IsOpened());
814 ASSERT_TRUE(file
.fd() != CFile::fd_invalid
);
815 ASSERT_EQUALS(testFile
, file
.GetFilePath());
816 ASSERT_EQUALS(4u, file
.GetLength());
817 ASSERT_EQUALS(0u, file
.GetPosition());
818 ASSERT_EQUALS(1u, file
.ReadUInt32());
819 ASSERT_EQUALS(0u, file
.Seek(0, wxFromStart
));
821 ASSERT_EQUALS(0u, file
.Seek(0, wxFromStart
));
822 ASSERT_EQUALS(2u, file
.ReadUInt32());
826 CFile
file(testFile
, CFile::write_append
);
828 ASSERT_TRUE(file
.IsOpened());
829 ASSERT_TRUE(file
.fd() != CFile::fd_invalid
);
830 ASSERT_EQUALS(4u, file
.GetLength());
832 ASSERT_EQUALS(0u, file
.Seek(0, wxFromStart
));
834 ASSERT_RAISES(CIOFailureException
, file
.ReadUInt8());
836 ASSERT_TRUE(file
.Close());
837 ASSERT_TRUE(file
.Open(testFile
, CFile::read
));
839 ASSERT_EQUALS(2u, file
.ReadUInt32());
840 ASSERT_EQUALS(1u, file
.ReadUInt32());
847 ASSERT_FALSE(testFile
.FileExists());
849 // Check creation of new file, when none exists, with/without overwrite
850 for (size_t i
= 0; i
< 2; ++i
) {
851 bool overwrite
= (i
== 1);
854 ASSERT_TRUE(!file
.IsOpened());
855 ASSERT_TRUE(file
.fd() == CFile::fd_invalid
);
856 ASSERT_TRUE(file
.Create(testFile
, overwrite
, testMode
));
857 ASSERT_TRUE(file
.IsOpened());
858 ASSERT_TRUE(file
.fd() != CFile::fd_invalid
);
859 ASSERT_EQUALS(testFile
, file
.GetFilePath());
860 ASSERT_TRUE(file
.Close());
861 ASSERT_TRUE(file
.fd() == CFile::fd_invalid
);
862 ASSERT_TRUE(!file
.IsOpened());
864 ASSERT_TRUE(wxFile::Access(testFile
.GetRaw(), wxFile::read
));
865 ASSERT_TRUE(wxFile::Access(testFile
.GetRaw(), wxFile::write
));
867 ASSERT_TRUE(wxRemoveFile(testFile
.GetRaw()));
870 // Create testfile, with a bit of contents
873 ASSERT_TRUE(file
.Create(testFile
, false, testMode
));
874 ASSERT_EQUALS(testFile
, file
.GetFilePath());
878 // Check that owerwrite = false works as expected
881 ASSERT_FALSE(file
.Create(testFile
, false, testMode
));
882 ASSERT_TRUE(file
.fd() == CFile::fd_invalid
);
883 ASSERT_TRUE(!file
.IsOpened());
885 // Open and check contents
886 ASSERT_TRUE(file
.Open(testFile
, CFile::read
));
887 ASSERT_TRUE(file
.IsOpened());
888 ASSERT_TRUE(file
.fd() != CFile::fd_invalid
);
889 ASSERT_EQUALS(testFile
, file
.GetFilePath());
890 ASSERT_EQUALS(4u, file
.GetLength());
891 ASSERT_EQUALS(1u, file
.ReadUInt32());
892 ASSERT_TRUE(file
.Close());
893 ASSERT_TRUE(file
.fd() == CFile::fd_invalid
);
894 ASSERT_TRUE(!file
.IsOpened());
897 // Check that owerwrite = true works as expected
900 ASSERT_TRUE(file
.Create(testFile
, true, testMode
));
901 ASSERT_TRUE(file
.IsOpened());
902 ASSERT_TRUE(file
.fd() != CFile::fd_invalid
);
903 ASSERT_EQUALS(testFile
, file
.GetFilePath());
904 ASSERT_EQUALS(0u, file
.GetLength());
905 ASSERT_TRUE(file
.Close());
906 ASSERT_TRUE(file
.fd() == CFile::fd_invalid
);
907 ASSERT_TRUE(!file
.IsOpened());
910 ASSERT_TRUE(wxFile::Access(testFile
.GetRaw(), wxFile::read
));
911 ASSERT_TRUE(wxFile::Access(testFile
.GetRaw(), wxFile::write
));
915 TEST(CFile
, SetLength
)
917 CFile
file(testFile
, CFile::write
);
919 ASSERT_EQUALS(0u, file
.GetLength());
920 file
.SetLength(1024);
921 ASSERT_EQUALS(1024u, file
.GetLength());
922 ASSERT_EQUALS(1024u, file
.Seek(0, wxFromEnd
));
923 file
.SetLength(512u);
924 ASSERT_EQUALS(512u, file
.GetLength());
925 ASSERT_EQUALS(512u, file
.Seek(0, wxFromEnd
));
929 TEST(CFile
, GetAvailable
)
932 CFile
file(testFile
, CFile::write
);
934 writePredefData(&file
);
937 CFile
file(testFile
, CFile::read
);
939 const uint64 length
= file
.GetLength();
940 while (!file
.Eof()) {
941 ASSERT_EQUALS(length
- file
.GetPosition(), file
.GetAvailable());
943 ASSERT_EQUALS(length
- file
.GetPosition(), file
.GetAvailable());
946 ASSERT_EQUALS(0u, file
.GetAvailable());
948 file
.Seek(1024, wxFromCurrent
);
950 ASSERT_EQUALS(0u, file
.GetAvailable());