diff --git a/CMakeLists.txt b/CMakeLists.txt index 94db02f36d..e64e83ed15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,6 +194,7 @@ if(HIP_FOUND AND Libva_FOUND) # install test cmake install(FILES test/CMakeLists.txt DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/test COMPONENT test) install(DIRECTORY test/testScripts DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/test COMPONENT test) + install(FILES test/rocDecodeNegativeApiTests/CMakeLists.txt test/rocDecodeNegativeApiTests/README.md test/rocDecodeNegativeApiTests/rocdecode_api_negative_tests.cpp test/rocDecodeNegativeApiTests/rocdecode_api_negative_tests.h test/rocDecodeNegativeApiTests/rocdecodenegativetest.cpp DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/test/rocDecodeNegativeApiTests COMPONENT dev) message("-- ${White}AMD ROCm rocDecode -- CMAKE_CXX_FLAGS:${CMAKE_CXX_FLAGS}${ColourReset}") message("-- ${White}AMD ROCm rocDecode -- Link Libraries: ${LINK_LIBRARY_LIST}${ColourReset}") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b8143fdc62..79d61a275b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -230,3 +230,15 @@ add_test( --test-command "videodecoderaw" -i ${ROCM_PATH}/share/rocdecode/video/AMD_driving_virtual_20-VP9.ivf ) + +# 13 - rocDecodeNegativeApiTests +add_test( + NAME + rocDecode_Negative_API_Tests + COMMAND + "${CMAKE_CTEST_COMMAND}" + --build-and-test "${ROCM_PATH}/share/rocdecode/test/rocDecodeNegativeApiTests" + "${CMAKE_CURRENT_BINARY_DIR}/rocdecodenegativetest" + --build-generator "${CMAKE_GENERATOR}" + --test-command "rocdecodenegativetest" +) diff --git a/test/rocDecodeNegativeApiTests/CMakeLists.txt b/test/rocDecodeNegativeApiTests/CMakeLists.txt new file mode 100644 index 0000000000..c0b0062595 --- /dev/null +++ b/test/rocDecodeNegativeApiTests/CMakeLists.txt @@ -0,0 +1,93 @@ +################################################################################ +# Copyright (c) 2023 - 2025 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +################################################################################ + +cmake_minimum_required(VERSION 3.10) +# ROCM Path +if(DEFINED ENV{ROCM_PATH}) + set(ROCM_PATH $ENV{ROCM_PATH} CACHE PATH "Default ROCm installation path") +elseif(ROCM_PATH) + message("-- INFO:ROCM_PATH Set -- ${ROCM_PATH}") +else() + set(ROCM_PATH /opt/rocm CACHE PATH "Default ROCm installation path") +endif() +# Set AMD Clang as default compiler +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED On) +set(CMAKE_CXX_EXTENSIONS ON) +if (NOT DEFINED CMAKE_CXX_COMPILER) + set(CMAKE_C_COMPILER ${ROCM_PATH}/bin/amdclang) + set(CMAKE_CXX_COMPILER ${ROCM_PATH}/bin/amdclang++) +endif() + +project(rocdecodenegativetest) + +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../cmake) +list(APPEND CMAKE_PREFIX_PATH ${ROCM_PATH}/lib/cmake) + +# rocDecode sample build type +set(DEFAULT_BUILD_TYPE "Release") +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE STRING "rocDecode Default Build Type" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release") +endif() +if(CMAKE_BUILD_TYPE MATCHES Debug) + # -O0 -- Don't Optimize output file + # -gdwarf-4 -- generate debugging information, dwarf-4 for making valgrind work + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -gdwarf-4") +else() + # -O3 -- Optimize output file + # -DNDEBUG -- turn off asserts + # -fPIC -- Generate position-independent code if possible + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG -fPIC") +endif() + +find_package(HIP QUIET) +find_package(rocdecode QUIET) +find_package(rocprofiler-register QUIET) + +if(HIP_FOUND AND rocdecode_FOUND AND rocprofiler-register_FOUND) + # HIP + set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} hip::host) + # rocDecode and utils + include_directories (${rocdecode_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} ${rocdecode_LIBRARY}) + # rocprofiler-register + set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} rocprofiler-register::rocprofiler-register) + # sample app exe + list(APPEND SOURCES ${PROJECT_SOURCE_DIR} rocdecodenegativetest.cpp rocdecode_api_negative_tests.cpp) + # --all-warnings/-Wall Enable most warning messages + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") + add_executable(${PROJECT_NAME} ${SOURCES}) + target_link_libraries(${PROJECT_NAME} ${LINK_LIBRARY_LIST}) +else() + message("-- ERROR!: ${PROJECT_NAME} excluded! please install all the dependencies and try again!") + if (NOT HIP_FOUND) + message(FATAL_ERROR "-- ERROR!: HIP Not Found! - please install ROCm and HIP!") + endif() + if (NOT ROCDECODE_FOUND) + message(FATAL_ERROR "-- ERROR!: rocDecode Not Found! - please install rocDecode!") + endif() + if (NOT rocprofiler-register_FOUND) + message(FATAL_ERROR "-- ERROR!: rocprofiler-register Not Found! - please install rocprofiler-register!") + endif() +endif() \ No newline at end of file diff --git a/test/rocDecodeNegativeApiTests/README.md b/test/rocDecodeNegativeApiTests/README.md new file mode 100644 index 0000000000..18fb21d846 --- /dev/null +++ b/test/rocDecodeNegativeApiTests/README.md @@ -0,0 +1,22 @@ +# RocDecode API Negative tests + +This test suite is designed to perform negative testing on all rocDecode APIs. The purpose of these tests is to validate the robustness and error-handling mechanisms of the rocDecode APIs +by providing invalid inputs, unexpected scenarios, or edge cases to ensure the APIs respond with appropriate error messages or behaviors. + +## Prerequisites: + +* Install [rocDecode](../../README.md#build-and-install-instructions) + +## Build + +```shell +mkdir build && cd build +cmake ../ +make -j +``` + +## Run + +```shell +./rocdecodenegativetest +``` \ No newline at end of file diff --git a/test/rocDecodeNegativeApiTests/rocdecode_api_negative_tests.cpp b/test/rocDecodeNegativeApiTests/rocdecode_api_negative_tests.cpp new file mode 100644 index 0000000000..712e97df91 --- /dev/null +++ b/test/rocDecodeNegativeApiTests/rocdecode_api_negative_tests.cpp @@ -0,0 +1,462 @@ + +/* +Copyright (c) 2023 - 2025 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "rocdecode_api_negative_tests.h" + +RocDecodeApiNegativeTests:: RocDecodeApiNegativeTests() : decoder_create_info_{} {}; + +RocDecodeApiNegativeTests::~RocDecodeApiNegativeTests() { + rocDecDestroyDecoder(decoder_handle_); + rocDecDestroyVideoParser(parser_handle_); +} + +int RocDecodeApiNegativeTests::TestInvalidCreateDecoder() { + std::cout << "info: Executing negative test cases for the rocDecCreateDecoder API" << std::endl; + // Scenario 1: Pass nullptr for decoder_handle and decoder_create_info + rocDecStatus rocdecode_status = rocDecCreateDecoder(nullptr, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass an empty decoder_create_info_ + rocdecode_status = rocDecCreateDecoder(&decoder_handle_, &decoder_create_info_); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 3: Pass invalid device_id in decoder_create_info + decoder_create_info_.device_id = 255; // Assuming 255 is an invalid device ID + decoder_create_info_.num_decode_surfaces = 1; + rocdecode_status = rocDecCreateDecoder(&decoder_handle_, &decoder_create_info_); + if (rocdecode_status != ROCDEC_NOT_SUPPORTED) { + std::cerr << "Expected ROCDEC_NOT_SUPPORTED but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 4: Pass zero width and height in decoder_create_info + decoder_create_info_.device_id = 0; // Reset to valid device ID + decoder_create_info_.width = 0; + decoder_create_info_.height = 0; + rocdecode_status = rocDecCreateDecoder(&decoder_handle_, &decoder_create_info_); + if (rocdecode_status != ROCDEC_NOT_SUPPORTED) { + std::cerr << "Expected ROCDEC_NOT_SUPPORTED but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 5: Pass unsupported codec type + decoder_create_info_.width = 1920; + decoder_create_info_.height = 1080; + decoder_create_info_.codec_type = static_cast(999); // Invalid codec type + rocdecode_status = rocDecCreateDecoder(&decoder_handle_, &decoder_create_info_); + if (rocdecode_status != ROCDEC_NOT_SUPPORTED) { + std::cerr << "Expected ROCDEC_NOT_SUPPORTED but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 6: Pass unsupported chroma_format + decoder_create_info_.codec_type = rocDecVideoCodec_HEVC; + decoder_create_info_.chroma_format = static_cast(999); + rocdecode_status = rocDecCreateDecoder(&decoder_handle_, &decoder_create_info_); + if (rocdecode_status != ROCDEC_NOT_SUPPORTED) { + std::cerr << "Expected ROCDEC_NOT_SUPPORTED but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 7: Pass unsupported bit_depth + decoder_create_info_.chroma_format = rocDecVideoChromaFormat_420; + decoder_create_info_.bit_depth_minus_8 = 6; + rocdecode_status = rocDecCreateDecoder(&decoder_handle_, &decoder_create_info_); + if (rocdecode_status != ROCDEC_NOT_SUPPORTED) { + std::cerr << "Expected ROCDEC_NOT_SUPPORTED but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Create a valid decoder_handle - This step ensures a valid decoder_handle_ is available for subsequent negative testing of other rocDecode APIs. + decoder_create_info_.bit_depth_minus_8 = 2; + rocdecode_status = rocDecCreateDecoder(&decoder_handle_, &decoder_create_info_); + if (rocdecode_status != ROCDEC_SUCCESS) { + std::cerr << "Expected ROCDEC_SUCCESS but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestInvalidDestroyDecoder() { + std::cout << "info: Executing negative test cases for the rocDecDestroyDecoder API" << std::endl; + //Scenario 1: Pass nullptr for decoder_handle + rocDecStatus rocdecode_status = rocDecDestroyDecoder(nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestInvalidGetDecoderCaps() { + std::cout << "info: Executing negative test cases for the rocDecGetDecoderCaps API" << std::endl; + // Scenario 1: Pass nullptr for decode_caps + rocDecStatus rocdecode_status = rocDecGetDecoderCaps(nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + // Scenario 2: Pass a decode_caps structure with unsupported codec type + RocdecDecodeCaps decode_caps = {}; + decode_caps.codec_type = static_cast(-1); // Invalid codec type + rocdecode_status = rocDecGetDecoderCaps(&decode_caps); + if (rocdecode_status != ROCDEC_SUCCESS || decode_caps.is_supported != 0) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestInvalidDecodeFrame() { + std::cout << "info: Executing negative test cases for the rocDecDecodeFrame API" << std::endl; + // Scenario 1: Pass nullptr for pic_params + rocDecStatus rocdecode_status = rocDecDecodeFrame(decoder_handle_, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass invalid curr_pic_idx + RocdecPicParams pic_params = {}; + pic_params.curr_pic_idx = -1; + rocdecode_status = rocDecDecodeFrame(decoder_handle_, &pic_params); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 3: Pass invalid reference frame index + pic_params.curr_pic_idx = 0; + pic_params.pic_params.hevc.ref_frames[0].pic_idx = -1; + rocdecode_status = rocDecDecodeFrame(decoder_handle_, &pic_params); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestInvalidGetDecodeStatus() { + std::cout << "info: Executing negative test cases for the rocDecGetDecodeStatus API" << std::endl; + // Scenario 1: Test with invalid picture parameters + rocDecStatus rocdecode_status = rocDecGetDecodeStatus(decoder_handle_, 0, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass with invalid parameter for pic_idx + int pic_idx = 100; + RocdecDecodeStatus decode_status; + rocdecode_status = rocDecGetDecodeStatus(decoder_handle_, pic_idx, &decode_status); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestInvalidReconfigureDecoder() { + std::cout << "info: Executing negative test cases for the rocDecReconfigureDecoder API" << std::endl; + // Scenario 1: Pass nullptr for reconfig_params + rocDecStatus rocdecode_status = rocDecReconfigureDecoder(decoder_handle_, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass an invalid decoder handle + RocdecReconfigureDecoderInfo reconfig_params = {}; + rocdecode_status = rocDecReconfigureDecoder(nullptr, &reconfig_params); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 3: Pass uninitialized reconfig_params + rocdecode_status = rocDecReconfigureDecoder(decoder_handle_, &reconfig_params); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 4: Pass invalid width and height in reconfig_params + reconfig_params.width = 0; + reconfig_params.height = 0; + rocdecode_status = rocDecReconfigureDecoder(decoder_handle_, &reconfig_params); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_NOT_SUPPORTED but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 5: Pass unsupported bit_depth in reconfig_params + reconfig_params.width = 1920; + reconfig_params.height = 1080; + reconfig_params.bit_depth_minus_8 = 4; // Unsupported bit depth + rocdecode_status = rocDecReconfigureDecoder(decoder_handle_, &reconfig_params); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_NOT_SUPPORTED but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + + +int RocDecodeApiNegativeTests::TestinvalidGetVideoFrame() { + std::cout << "info: Executing negative test cases for the rocDecGetVideoFrame API" << std::endl; + // Scenario 1: Pass nullptr for dev_mem_ptr, horizontal_pitch, and vid_postproc_params + rocDecStatus rocdecode_status = rocDecGetVideoFrame(decoder_handle_, 0, nullptr, nullptr, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass an invalid picture index + void *dev_mem_ptr[3] = {}; + uint32_t horizontal_pitch[3] = {}; + RocdecProcParams vid_postproc_params = {}; + rocdecode_status = rocDecGetVideoFrame(decoder_handle_, -1, dev_mem_ptr, horizontal_pitch, &vid_postproc_params); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestinvalidGetErrorName(){ + std::cout << "info: Executing negative test cases for the rocDecGetErrorName API" << std::endl; + // Scenario 1: Pass an invalid error code + rocDecStatus invalid_status = static_cast(-999); // Invalid error code + const char *error_name = rocDecGetErrorName(invalid_status); + if (error_name == nullptr) { + std::cerr << "Expected a valid error but got nullptr" << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass a valid error code and ensure it returns a non-null name + for (int i = 0; i <= -8; i--) { + rocDecStatus valid_status = static_cast(i);; + error_name = rocDecGetErrorName(valid_status); + if (error_name == nullptr) { + std::cerr << "Expected a valid error but got nullptr" << std::endl; + return EXIT_FAILURE; + } + } + + // Scenario 3: Pass a boundary value (e.g., maximum enum value + 1) + rocDecStatus boundary_status = static_cast(ROCDEC_SUCCESS + 1); + error_name = rocDecGetErrorName(boundary_status); + if (error_name == nullptr) { + std::cerr << "Expected a valid error but got nullptr" << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestinvalidCreateVideoParser() { + std::cout << "info: Executing negative test cases for the rocDecCreateVideoParser API" << std::endl; + + // Scenario 1: Pass nullptr for parser_handle and parser parameter + rocDecStatus rocdecode_status = rocDecCreateVideoParser(nullptr, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass a valid parser_handle but nullptr for parser parameter + rocdecode_status = rocDecCreateVideoParser(&parser_handle_, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 3: Pass invalid code_type + RocdecParserParams params = {}; + params.codec_type = static_cast(999); // Invalid codec type + rocdecode_status = rocDecCreateVideoParser(&parser_handle_, ¶ms); + if (rocdecode_status != ROCDEC_NOT_IMPLEMENTED) { + std::cerr << "Expected ROCDEC_NOT_IMPLEMENTED but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 4: Create a dummy parser_handle for testing other parser APIs + params.codec_type = rocDecVideoCodec_HEVC; // Invalid codec type + rocdecode_status = rocDecCreateVideoParser(&parser_handle_, ¶ms); + if (rocdecode_status != ROCDEC_SUCCESS) { + std::cerr << "Expected ROCDEC_SUCCESS but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestinvalidParseVideoData() { + std::cout << "info: Executing negative test cases for the rocDecParseVideoData API" << std::endl; + // Scenario 1: Pass nullptr for parser_handle and parser parameter + rocDecStatus rocdecode_status = rocDecParseVideoData(nullptr, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + // Scenario 2: Pass a parser_handle with a nullptr packet + rocdecode_status = rocDecParseVideoData(parser_handle_, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 3: Pass a packet initialized to 0 + RocdecSourceDataPacket packet = {}; + rocdecode_status = rocDecParseVideoData(parser_handle_, &packet); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestinvalidDestroyVideoParser() { + std::cout << "info: Executing negative test cases for the rocDecDestroyVideoParser API" << std::endl; + // Scenario 1: Pass nullptr for parser_handle + rocDecStatus rocdecode_status = rocDecDestroyVideoParser(nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestinvalidCreateBitstreamReader() { + std::cout << "info: Executing negative test cases for the rocDecCreateBitstreamReader API" << std::endl; + + // Scenario 1: Pass nullptr for bs_reader_handle and input_file_path + rocDecStatus rocdecode_status = rocDecCreateBitstreamReader(nullptr, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass a valid bs_reader_handle but nullptr for input_file_path + RocdecBitstreamReader bs_reader_handle; + rocdecode_status = rocDecCreateBitstreamReader(&bs_reader_handle, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestinvalidGetBitstreamCodecType() { + std::cout << "info: Executing negative test cases for the rocDecGetBitstreamCodecType API" << std::endl; + + // Scenario 1: Pass nullptr for bs_reader_handle and codec_type + rocDecStatus rocdecode_status = rocDecGetBitstreamCodecType(nullptr, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass a valid bs_reader_handle but nullptr for codec_type + RocdecBitstreamReader bs_reader_handle; + rocdecode_status = rocDecGetBitstreamCodecType(&bs_reader_handle, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestinvalidGetBitstreamBitDepth() { + std::cout << "info: Executing negative test cases for the rocDecGetBitstreamBitDepth API" << std::endl; + // Scenario 1: Pass nullptr for bs_reader_handle and bit_depth + rocDecStatus rocdecode_status = rocDecGetBitstreamBitDepth(nullptr, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass a valid bs_reader_handle but nullptr for bit_depth + RocdecBitstreamReader bs_reader_handle; + rocdecode_status = rocDecGetBitstreamBitDepth(&bs_reader_handle, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestinvalidGetBitstreamPicData() { + std::cout << "info: Executing negative test cases for the rocDecGetBitstreamPicData API" << std::endl; + // Scenario 1: Pass nullptr for all parameters + rocDecStatus rocdecode_status = rocDecGetBitstreamPicData(nullptr, nullptr, nullptr, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + // Scenario 2: Pass a valid bs_reader_handle but nullptr for pic_data, pic_size, and pts + RocdecBitstreamReader bs_reader_handle; + rocdecode_status = rocDecGetBitstreamPicData(&bs_reader_handle, nullptr, nullptr, nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::TestinvalidDestroyBitstreamReader() { + std::cout << "info: Executing negative test cases for the rocDecDestroyBitstreamReader API" << std::endl; + // Scenario 1: Pass nullptr for bs_reader_handle + rocDecStatus rocdecode_status = rocDecDestroyBitstreamReader(nullptr); + if (rocdecode_status != ROCDEC_INVALID_PARAMETER) { + std::cerr << "Expected ROCDEC_INVALID_PARAMETER but got " << rocDecGetErrorName(rocdecode_status) << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int RocDecodeApiNegativeTests::RunTests() { + if (TestInvalidCreateDecoder() || TestInvalidDestroyDecoder() || TestInvalidGetDecoderCaps() || TestInvalidDecodeFrame() || + TestInvalidGetDecodeStatus() || TestInvalidReconfigureDecoder() || TestinvalidGetVideoFrame() || TestinvalidGetErrorName() || + TestinvalidCreateVideoParser() || TestinvalidParseVideoData() || TestinvalidDestroyVideoParser() || + TestinvalidCreateBitstreamReader() || TestinvalidGetBitstreamCodecType() || TestinvalidGetBitstreamBitDepth() || + TestinvalidGetBitstreamPicData() || TestinvalidDestroyBitstreamReader()) { + std::cerr << "One or more negative tests failed." << std::endl; + return EXIT_FAILURE; + } else { + return EXIT_SUCCESS; + } +} \ No newline at end of file diff --git a/test/rocDecodeNegativeApiTests/rocdecode_api_negative_tests.h b/test/rocDecodeNegativeApiTests/rocdecode_api_negative_tests.h new file mode 100644 index 0000000000..b6f6711ece --- /dev/null +++ b/test/rocDecodeNegativeApiTests/rocdecode_api_negative_tests.h @@ -0,0 +1,65 @@ +/* +Copyright (c) 2023 - 2025 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#ifndef ROCDECODE_API_NEGATIVE_TESTS_H +#define ROCDECODE_API_NEGATIVE_TESTS_H + +#include +#include +#include +#include + +/** + * @class RocDecodeApiNegativeTests + * @brief A class to perform negative API tests for the rocDecode library. + * + * This class contains a set of test cases designed to validate the behavior + * of the RocDecode library when invalid or unexpected inputs are provided. + * It ensures the robustness and error handling capabilities of the library. + */ +class RocDecodeApiNegativeTests { + public: + RocDecodeApiNegativeTests(); + ~RocDecodeApiNegativeTests(); + int RunTests(); + private: + int TestInvalidCreateDecoder(); + int TestInvalidDestroyDecoder(); + int TestInvalidGetDecoderCaps(); + int TestInvalidDecodeFrame(); + int TestInvalidGetDecodeStatus(); + int TestInvalidReconfigureDecoder(); + int TestinvalidGetVideoFrame(); + int TestinvalidGetErrorName(); + int TestinvalidCreateVideoParser(); + int TestinvalidParseVideoData(); + int TestinvalidDestroyVideoParser(); + int TestinvalidCreateBitstreamReader(); + int TestinvalidGetBitstreamCodecType(); + int TestinvalidGetBitstreamBitDepth(); + int TestinvalidGetBitstreamPicData(); + int TestinvalidDestroyBitstreamReader(); + rocDecDecoderHandle decoder_handle_; + RocDecoderCreateInfo decoder_create_info_; + RocdecVideoParser parser_handle_; +}; + +#endif // ROCDECODE_API_NEGATIVE_TESTS_H \ No newline at end of file diff --git a/test/rocDecodeNegativeApiTests/rocdecodenegativetest.cpp b/test/rocDecodeNegativeApiTests/rocdecodenegativetest.cpp new file mode 100644 index 0000000000..7703ba90b8 --- /dev/null +++ b/test/rocDecodeNegativeApiTests/rocdecodenegativetest.cpp @@ -0,0 +1,33 @@ +/* +Copyright (c) 2023 - 2025 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "rocdecode_api_negative_tests.h" + +int main(int argc, char **argv) { + RocDecodeApiNegativeTests rocdecode_negative_test; + if (rocdecode_negative_test.RunTests()) { + std::cout << "Test Failed!" << std::endl; + return EXIT_FAILURE; + } + std::cout << "Test Passed!" << std::endl; + return EXIT_SUCCESS; +} \ No newline at end of file