// Copyright (c) Team CharLS. // SPDX-License-Identifier: BSD-3-Clause #include "pch.h" #include "util.h" #include #include #include using Microsoft::VisualStudio::CppUnitTestFramework::Assert; using std::array; using std::vector; MSVC_WARNING_SUPPRESS(6387) // '_Param_(x)' could be '0': this does not adhere to the specification for the function. #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnonnull" #endif // ReSharper disable CppDeprecatedEntity DISABLE_DEPRECATED_WARNING namespace charls { namespace test { TEST_CLASS(interface_test) { public: TEST_METHOD(get_metadata_info_from_near_lossless_encoded_color_image) // NOLINT { const vector encoded_source{read_file("DataFiles/t8c0e3.jls")}; JlsParameters params{}; const jpegls_errc result{JpegLsReadHeader(encoded_source.data(), encoded_source.size(), ¶ms, nullptr)}; Assert::AreEqual(jpegls_errc::success, result); Assert::AreEqual(params.height, 256); Assert::AreEqual(params.width, 256); Assert::AreEqual(params.bitsPerSample, 8); Assert::AreEqual(params.components, 3); Assert::AreEqual(params.allowedLossyError, 3); } TEST_METHOD(JpegLsReadHeader_nullptr) // NOLINT { JlsParameters params{}; const vector encoded_source{read_file("DataFiles/t8c0e3.jls")}; auto error{JpegLsReadHeader(nullptr, encoded_source.size(), ¶ms, nullptr)}; Assert::AreEqual(jpegls_errc::invalid_argument, error); error = JpegLsReadHeader(encoded_source.data(), encoded_source.size(), nullptr, nullptr); Assert::AreEqual(jpegls_errc::invalid_argument, error); } TEST_METHOD(JpegLsReadHeader_empty_source) // NOLINT { array error_message{}; JlsParameters params{}; constexpr array source{}; const auto error{JpegLsReadHeader(source.data(), 0, ¶ms, error_message.data())}; Assert::AreEqual(jpegls_errc::source_buffer_too_small, error); Assert::IsTrue(strlen(error_message.data()) > 0); } TEST_METHOD(JpegLsReadHeader_custom_preset_parameters) // NOLINT { // NON-DEFAULT parameters T1=T2=T3=9,RESET=31. const vector encoded_source{read_file("DataFiles/t8nde0.jls")}; JlsParameters params{}; const jpegls_errc result{JpegLsReadHeader(encoded_source.data(), encoded_source.size(), ¶ms, nullptr)}; Assert::AreEqual(jpegls_errc::success, result); Assert::AreEqual(255, params.custom.MaximumSampleValue); Assert::AreEqual(9, params.custom.Threshold1); Assert::AreEqual(9, params.custom.Threshold2); Assert::AreEqual(9, params.custom.Threshold3); Assert::AreEqual(31, params.custom.ResetValue); } TEST_METHOD(JpegLsEncode_nullptr) // NOLINT { JlsParameters params{}; params.bitsPerSample = 8; params.height = 10; params.width = 10; params.components = 1; size_t bytes_written{}; vector buffer(10000); auto error{JpegLsEncode(nullptr, buffer.size(), &bytes_written, buffer.data(), buffer.size(), ¶ms, nullptr)}; Assert::AreEqual(jpegls_errc::invalid_argument, error); error = JpegLsEncode(buffer.data(), buffer.size(), nullptr, buffer.data(), buffer.size(), ¶ms, nullptr); Assert::AreEqual(jpegls_errc::invalid_argument, error); error = JpegLsEncode(buffer.data(), buffer.size(), &bytes_written, nullptr, buffer.size(), ¶ms, nullptr); Assert::AreEqual(jpegls_errc::invalid_argument, error); error = JpegLsEncode(buffer.data(), buffer.size(), &bytes_written, buffer.data(), buffer.size(), nullptr, nullptr); Assert::AreEqual(jpegls_errc::invalid_argument, error); } TEST_METHOD(JpegLsEncode_empty_destination) // NOLINT { array error_message{}; JlsParameters params{}; params.bitsPerSample = 8; params.height = 10; params.width = 10; params.components = 1; size_t bytes_written{}; array destination{}; const vector source(100); const auto error{ JpegLsEncode(destination.data(), 0, &bytes_written, source.data(), source.size(), ¶ms, error_message.data())}; Assert::AreEqual(jpegls_errc::destination_buffer_too_small, error); Assert::IsTrue(strlen(error_message.data()) > 0); } TEST_METHOD(JpegLsDecode_nullptr) // NOLINT { constexpr JlsParameters params{}; vector encoded_source{read_file("DataFiles/tulips-gray-8bit-512-512-hp-encoder.jls")}; auto error{JpegLsDecode(nullptr, 100, encoded_source.data(), encoded_source.size(), ¶ms, nullptr)}; Assert::AreEqual(jpegls_errc::invalid_argument, error); error = JpegLsDecode(encoded_source.data(), 100, nullptr, encoded_source.size(), ¶ms, nullptr); Assert::AreEqual(jpegls_errc::invalid_argument, error); } TEST_METHOD(JpegLsDecode_empty_source) // NOLINT { array error_message{}; JlsParameters params{}; params.bitsPerSample = 8; params.height = 10; params.width = 10; params.components = 1; constexpr array source{}; vector destination(100); const auto error{ JpegLsDecode(destination.data(), destination.size(), source.data(), 0, ¶ms, error_message.data())}; Assert::AreEqual(jpegls_errc::source_buffer_too_small, error); Assert::IsTrue(strlen(error_message.data()) > 0); } TEST_METHOD(JpegLsDecodeRect_tulips) // NOLINT { JlsParameters params{}; const vector encoded_source{read_file("DataFiles/tulips-gray-8bit-512-512-hp-encoder.jls")}; auto error{JpegLsReadHeader(encoded_source.data(), encoded_source.size(), ¶ms, nullptr)}; Assert::AreEqual(jpegls_errc::success, error); vector decoded_destination(static_cast(params.width) * params.height * params.components); error = JpegLsDecode(decoded_destination.data(), decoded_destination.size(), encoded_source.data(), encoded_source.size(), ¶ms, nullptr); Assert::IsFalse(static_cast(error)); constexpr size_t width{256}; constexpr JlsRect rect{128, 128, width, 1}; vector decoded_rect(width * rect.Height); // Update the stride to match the width of the rectangle. params.stride = width; // Add a marker byte to detect the case of a buffer overrun. constexpr uint8_t buffer_overrun_detection_marker{0x1f}; decoded_rect.push_back(buffer_overrun_detection_marker); error = JpegLsDecodeRect(decoded_rect.data(), decoded_rect.size(), encoded_source.data(), encoded_source.size(), rect, ¶ms, nullptr); Assert::IsFalse(static_cast(error)); Assert::IsTrue(memcmp(&decoded_destination[rect.X + static_cast(rect.Y) * 512], decoded_rect.data(), width * rect.Height) == 0); // Check that the marker is not overwritten. Assert::IsTrue(decoded_rect[width * rect.Height] == buffer_overrun_detection_marker); } TEST_METHOD(JpegLsDecodeRect_nullptr) // NOLINT { constexpr JlsParameters params{}; constexpr JlsRect roi{}; vector encoded_source{read_file("DataFiles/tulips-gray-8bit-512-512-hp-encoder.jls")}; auto error{JpegLsDecodeRect(nullptr, 100, encoded_source.data(), encoded_source.size(), roi, ¶ms, nullptr)}; Assert::AreEqual(jpegls_errc::invalid_argument, error); error = JpegLsDecodeRect(encoded_source.data(), 100, nullptr, encoded_source.size(), roi, ¶ms, nullptr); Assert::AreEqual(jpegls_errc::invalid_argument, error); } TEST_METHOD(JpegLsDecodeRect_empty_source) // NOLINT { array error_message{}; JlsParameters params{}; params.bitsPerSample = 8; params.height = 10; params.width = 10; params.components = 1; constexpr JlsRect roi{}; constexpr array source{}; vector destination(100); const auto error{JpegLsDecodeRect(destination.data(), destination.size(), source.data(), 0, roi, ¶ms, error_message.data())}; Assert::AreEqual(jpegls_errc::source_buffer_too_small, error); Assert::IsTrue(strlen(error_message.data()) > 0); } TEST_METHOD(noise_image_with_custom_reset) // NOLINT { JlsParameters params{}; params.components = 1; params.bitsPerSample = 16; params.height = 512; params.width = 512; params.custom.MaximumSampleValue = (1 << params.bitsPerSample) - 1; params.custom.ResetValue = 63; const vector noise_image = create_noise_image_16_bit(static_cast(params.height) * params.width, params.bitsPerSample, 21344); test_round_trip_legacy(noise_image, params); } }; }} // namespace charls::test // ReSharper restore CppDeprecatedEntity RESTORE_DEPRECATED_WARNING #if defined(__clang__) #pragma clang diagnostic pop #endif MSVC_WARNING_UNSUPPRESS()