/* * Split testing for Tiny PNG Output (C++) * * Copyright (c) 2022 Project Nayuki * https://www.nayuki.io/page/tiny-png-output * * This program 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. * * This program 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 this program (see COPYING.txt and COPYING.LESSER.txt). * If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "TinyPngOut.hpp" using std::uint8_t; using std::uint32_t; using std::uint64_t; using std::size_t; using std::uniform_int_distribution; static void test(uint32_t width, uint32_t height, long trials); std::default_random_engine randGen((std::random_device())()); uniform_int_distribution byteDist(0x00, 0xFF); int main() { try { uniform_int_distribution dimensionDist(0, 100000); for (long i = 0; ; ) { uint32_t width = dimensionDist(randGen); uint32_t height = dimensionDist(randGen); if (width > 0 && height > 0 && static_cast(width) * height * 3 < 1000000) { std::cerr << "Test " << i << ": "; std::cerr << "width=" << width << " "; std::cerr << "height=" << height << " "; std::cerr << "pixels=" << width * height << " "; std::cerr << "bytes=" << width * height * 3 << std::endl; test(width, height, 10); if (i < std::numeric_limits::max()) i++; } } return EXIT_SUCCESS; } catch (std::exception &e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } } static void test(uint32_t width, uint32_t height, long trials) { // Generate array of random pixel values size_t numPixels = static_cast(width) * height; std::vector pixelBytes(numPixels * 3); for (auto it = pixelBytes.begin(); it != pixelBytes.cend(); ++it) *it = byteDist(randGen); // Write entire image in one shot std::string reference; { std::stringstream out; TinyPngOut pngout(static_cast(width), static_cast(height), out); pngout.write(pixelBytes.data(), numPixels); reference = out.str(); } // Try writing in different splits for (long i = 0; i < trials; i++) { std::cerr << " Trial " << i << ": "; std::stringstream out; TinyPngOut pngout(static_cast(width), static_cast(height), out); size_t offset = 0; while (offset < numPixels) { uniform_int_distribution dist(0, numPixels - offset); size_t count = dist(randGen); std::cerr << count << " " << std::flush; pngout.write(pixelBytes.data() + offset * 3, count); offset += count; } std::string actual = out.str(); std::cerr << (actual == reference ? "Same" : "Different") << std::endl; if (actual != reference) throw std::runtime_error("Data mismatch"); } }