/* * libnbt++ - A library for the Minecraft Named Binary Tag format. * Copyright (C) 2013, 2015 ljfa-ag * * This file is part of libnbt++. * * libnbt++ is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libnbt++ is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libnbt++. If not, see . */ #include #include "io/izlibstream.h" #include "io/ozlibstream.h" #include #include #include "data.h" using namespace zlib; class zlibstream_test : public CxxTest::TestSuite { private: std::string bigtest; public: zlibstream_test() { std::string input(__binary_bigtest_uncompr_start, __binary_bigtest_uncompr_end); std::istringstream bigtest_f(input, std::ios::binary); std::stringbuf bigtest_b; bigtest_f >> &bigtest_b; bigtest = bigtest_b.str(); if(!bigtest_f || bigtest.size() == 0) throw std::runtime_error("Could not read bigtest_uncompr file"); } void test_inflate_gzip() { std::string input(__binary_bigtest_nbt_start, __binary_bigtest_nbt_end); std::istringstream gzip_in(input, std::ios::binary); TS_ASSERT(gzip_in); std::stringbuf data; //Small buffer so not all fits at once (the compressed file is 561 bytes) { izlibstream igzs(gzip_in, 256); igzs.exceptions(std::ios::failbit | std::ios::badbit); TS_ASSERT(igzs.good()); TS_ASSERT_THROWS_NOTHING(igzs >> &data); TS_ASSERT(igzs); TS_ASSERT(igzs.eof()); TS_ASSERT_EQUALS(data.str(), bigtest); } //Clear and reuse buffers data.str(""); gzip_in.clear(); gzip_in.seekg(0); //Now try the same with larger buffer (but not large enough for all output, uncompressed size 1561 bytes) { izlibstream igzs(gzip_in, 1000); igzs.exceptions(std::ios::failbit | std::ios::badbit); TS_ASSERT(igzs.good()); TS_ASSERT_THROWS_NOTHING(igzs >> &data); TS_ASSERT(igzs); TS_ASSERT(igzs.eof()); TS_ASSERT_EQUALS(data.str(), bigtest); } data.str(""); gzip_in.clear(); gzip_in.seekg(0); //Now with large buffer { izlibstream igzs(gzip_in, 4000); igzs.exceptions(std::ios::failbit | std::ios::badbit); TS_ASSERT(igzs.good()); TS_ASSERT_THROWS_NOTHING(igzs >> &data); TS_ASSERT(igzs); TS_ASSERT(igzs.eof()); TS_ASSERT_EQUALS(data.str(), bigtest); } } void test_inflate_zlib() { std::string input(__binary_bigtest_zlib_start, __binary_bigtest_zlib_end); std::istringstream zlib_in(input, std::ios::binary); TS_ASSERT(zlib_in); std::stringbuf data; izlibstream izls(zlib_in, 256); izls.exceptions(std::ios::failbit | std::ios::badbit); TS_ASSERT(izls.good()); TS_ASSERT_THROWS_NOTHING(izls >> &data); TS_ASSERT(izls); TS_ASSERT(izls.eof()); TS_ASSERT_EQUALS(data.str(), bigtest); } void test_inflate_corrupt() { std::string input(__binary_bigtest_corrupt_nbt_start, __binary_bigtest_corrupt_nbt_end); std::istringstream gzip_in(input, std::ios::binary); TS_ASSERT(gzip_in); std::vector buf(bigtest.size()); izlibstream igzs(gzip_in); igzs.exceptions(std::ios::failbit | std::ios::badbit); TS_ASSERT_THROWS(igzs.read(buf.data(), buf.size()), zlib_error); TS_ASSERT(igzs.bad()); } void test_inflate_eof() { std::string input(__binary_bigtest_eof_nbt_start, __binary_bigtest_eof_nbt_end); std::istringstream gzip_in(input, std::ios::binary); TS_ASSERT(gzip_in); std::vector buf(bigtest.size()); izlibstream igzs(gzip_in); igzs.exceptions(std::ios::failbit | std::ios::badbit); TS_ASSERT_THROWS(igzs.read(buf.data(), buf.size()), zlib_error); TS_ASSERT(igzs.bad()); } void test_inflate_trailing() { //This file contains additional uncompressed data after the zlib-compressed data std::string input(__binary_trailing_data_zlib_start, __binary_trailing_data_zlib_end); std::istringstream file(input, std::ios::binary); izlibstream izls(file, 32); TS_ASSERT(file && izls); std::string str; izls >> str; TS_ASSERT(izls); TS_ASSERT(izls.eof()); TS_ASSERT_EQUALS(str, "foobar"); //Now read the uncompressed data TS_ASSERT(file); TS_ASSERT(!file.eof()); file >> str; TS_ASSERT(!file.bad()); TS_ASSERT_EQUALS(str, "barbaz"); } void test_deflate_zlib() { //Here we assume that inflating works and has already been tested std::stringstream str; std::stringbuf output; //Small buffer { ozlibstream ozls(str, -1, false, 256); ozls.exceptions(std::ios::failbit | std::ios::badbit); TS_ASSERT_THROWS_NOTHING(ozls << bigtest); TS_ASSERT(ozls.good()); TS_ASSERT_THROWS_NOTHING(ozls.close()); TS_ASSERT(ozls.good()); } TS_ASSERT(str.good()); { izlibstream izls(str); TS_ASSERT_THROWS_NOTHING(izls >> &output); TS_ASSERT(izls); } TS_ASSERT_EQUALS(output.str(), bigtest); str.clear(); str.str(""); output.str(""); //Medium sized buffer //Write first half, then flush and write second half { ozlibstream ozls(str, 9, false, 512); ozls.exceptions(std::ios::failbit | std::ios::badbit); std::string half1 = bigtest.substr(0, bigtest.size()/2); std::string half2 = bigtest.substr(bigtest.size()/2); TS_ASSERT_THROWS_NOTHING(ozls << half1 << std::flush << half2); TS_ASSERT(ozls.good()); TS_ASSERT_THROWS_NOTHING(ozls.close()); TS_ASSERT(ozls.good()); } TS_ASSERT(str.good()); { izlibstream izls(str); izls >> &output; TS_ASSERT(izls); } TS_ASSERT_EQUALS(output.str(), bigtest); str.clear(); str.str(""); output.str(""); //Large buffer { ozlibstream ozls(str, 1, false, 4000); ozls.exceptions(std::ios::failbit | std::ios::badbit); TS_ASSERT_THROWS_NOTHING(ozls << bigtest); TS_ASSERT(ozls.good()); TS_ASSERT_THROWS_NOTHING(ozls.close()); TS_ASSERT_THROWS_NOTHING(ozls.close()); //closing twice shouldn't be a problem TS_ASSERT(ozls.good()); } TS_ASSERT(str.good()); { izlibstream izls(str); izls >> &output; TS_ASSERT(izls); } TS_ASSERT_EQUALS(output.str(), bigtest); } void test_deflate_gzip() { std::stringstream str; std::stringbuf output; { ozlibstream ozls(str, -1, true); ozls.exceptions(std::ios::failbit | std::ios::badbit); TS_ASSERT_THROWS_NOTHING(ozls << bigtest); TS_ASSERT(ozls.good()); TS_ASSERT_THROWS_NOTHING(ozls.close()); TS_ASSERT(ozls.good()); } TS_ASSERT(str.good()); { izlibstream izls(str); izls >> &output; TS_ASSERT(izls); } TS_ASSERT_EQUALS(output.str(), bigtest); } void test_deflate_closed() { std::stringstream str; { ozlibstream ozls(str); ozls.exceptions(std::ios::failbit | std::ios::badbit); TS_ASSERT_THROWS_NOTHING(ozls << bigtest); TS_ASSERT_THROWS_NOTHING(ozls.close()); TS_ASSERT_THROWS_NOTHING(ozls << "foo"); TS_ASSERT_THROWS_ANYTHING(ozls.close()); TS_ASSERT(ozls.bad()); TS_ASSERT(!str); } str.clear(); str.seekp(0); { ozlibstream ozls(str); //this time without exceptions TS_ASSERT_THROWS_NOTHING(ozls << bigtest); TS_ASSERT_THROWS_NOTHING(ozls.close()); TS_ASSERT_THROWS_NOTHING(ozls << "foo" << std::flush); TS_ASSERT(ozls.bad()); TS_ASSERT_THROWS_NOTHING(ozls.close()); TS_ASSERT(ozls.bad()); TS_ASSERT(!str); } } };