diff options
author | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2017-06-23 07:48:09 -0700 |
---|---|---|
committer | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2017-06-23 07:48:09 -0700 |
commit | 4564d31c76c0c7e4729c1e99fa96e0b82d447c40 (patch) | |
tree | ecf6aabeab27021d0db8f05e8a183a863a538eb2 /tests/test_document.cpp | |
parent | 20a8eced3b86c03d9dce7823feb3536a75c78b3e (diff) |
tests: Add stream coverage tests
These tests simulate various error conditions when reading data from
streams - seeks failing in seekable streams, underflow throwing an
exception causing read to set badbit, etc.
This change also adjusts memory thresholds to cause a reliable out of
memory during construction of a final buffer for non-seekable streams.
Diffstat (limited to 'tests/test_document.cpp')
-rw-r--r-- | tests/test_document.cpp | 112 |
1 files changed, 108 insertions, 4 deletions
diff --git a/tests/test_document.cpp b/tests/test_document.cpp index 2b4c4be..ffe1e8b 100644 --- a/tests/test_document.cpp +++ b/tests/test_document.cpp @@ -18,6 +18,10 @@ #include <string> #include <algorithm> +#ifndef PUGIXML_NO_EXCEPTIONS +# include <stdexcept> +#endif + #ifdef __MINGW32__ # include <io.h> // for unlink in C++0x mode #endif @@ -275,7 +279,7 @@ TEST(document_load_stream_nonseekable_out_of_memory_large) char_array_buffer<char> buffer(&str[0], &str[0] + str.length()); std::basic_istream<char> in(&buffer); - test_runner::_memory_fail_threshold = 10000 * 8 * 3 / 2; + test_runner::_memory_fail_threshold = 32768 * 3 + 4096; xml_document doc; CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory)); @@ -291,7 +295,7 @@ TEST(document_load_stream_wide_nonseekable_out_of_memory_large) char_array_buffer<wchar_t> buffer(&str[0], &str[0] + str.length()); std::basic_istream<wchar_t> in(&buffer); - test_runner::_memory_fail_threshold = 10000 * 8 * 3 / 2; + test_runner::_memory_fail_threshold = 32768 * 3 * sizeof(wchar_t) + 4096; xml_document doc; CHECK_ALLOC_FAIL(CHECK(doc.load(in).status == status_out_of_memory)); @@ -300,10 +304,18 @@ TEST(document_load_stream_wide_nonseekable_out_of_memory_large) template <typename T> class seek_fail_buffer: public std::basic_streambuf<T> { public: + int seeks; + + seek_fail_buffer(): seeks(0) + { + } + typename std::basic_streambuf<T>::pos_type seekoff(typename std::basic_streambuf<T>::off_type, std::ios_base::seekdir, std::ios_base::openmode) PUGIXML_OVERRIDE { - // pretend that our buffer is seekable (this is called by tellg); actual seeks will fail - return 0; + seeks++; + + // pretend that our buffer is seekable (this is called by tellg) + return seeks == 1 ? 0 : -1; } }; @@ -324,6 +336,98 @@ TEST(document_load_stream_wide_seekable_fail_seek) xml_document doc; CHECK(doc.load(in).status == status_io_error); } + +#ifndef PUGIXML_NO_EXCEPTIONS +template <typename T> class read_fail_buffer: public std::basic_streambuf<T> +{ +public: + read_fail_buffer() + { + } + + typename std::basic_streambuf<T>::int_type underflow() PUGIXML_OVERRIDE + { + throw std::runtime_error("underflow failed"); + + #ifdef __DMC__ + return 0; + #endif + } +}; + +TEST(document_load_stream_nonseekable_fail_read) +{ + read_fail_buffer<char> buffer; + std::basic_istream<char> in(&buffer); + + xml_document doc; + CHECK(doc.load(in).status == status_io_error); +} + +TEST(document_load_stream_wide_nonseekable_fail_read) +{ + read_fail_buffer<wchar_t> buffer; + std::basic_istream<wchar_t> in(&buffer); + + xml_document doc; + CHECK(doc.load(in).status == status_io_error); +} + +template <typename T> class read_fail_seekable_buffer: public std::basic_streambuf<T> +{ +public: + typename std::basic_streambuf<T>::pos_type offset; + + read_fail_seekable_buffer(): offset(0) + { + } + + typename std::basic_streambuf<T>::int_type underflow() PUGIXML_OVERRIDE + { + throw std::runtime_error("underflow failed"); + + #ifdef __DMC__ + return 0; + #endif + } + + typename std::basic_streambuf<T>::pos_type seekoff(typename std::basic_streambuf<T>::off_type off, std::ios_base::seekdir dir, std::ios_base::openmode) PUGIXML_OVERRIDE + { + switch (dir) + { + case std::ios_base::beg: offset = off; break; + case std::ios_base::cur: offset += off; break; + case std::ios_base::end: offset = 16 + off; break; + default: ; + } + return offset; + } + + typename std::basic_streambuf<T>::pos_type seekpos(typename std::basic_streambuf<T>::pos_type pos, std::ios_base::openmode) PUGIXML_OVERRIDE + { + offset = pos; + return pos; + } +}; + +TEST(document_load_stream_seekable_fail_read) +{ + read_fail_seekable_buffer<char> buffer; + std::basic_istream<char> in(&buffer); + + xml_document doc; + CHECK(doc.load(in).status == status_io_error); +} + +TEST(document_load_stream_wide_seekable_fail_read) +{ + read_fail_seekable_buffer<wchar_t> buffer; + std::basic_istream<wchar_t> in(&buffer); + + xml_document doc; + CHECK(doc.load(in).status == status_io_error); +} +#endif #endif TEST(document_load_string) |