From ec8253edf2d3a2ebbb427a7fd578388f4b862c0e Mon Sep 17 00:00:00 2001 From: marcojob <44396071+marcojob@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:24:53 +0100 Subject: [PATCH] ci: Add script to test raft, failing --- .github/workflows/ci.yml | 2 +- CMakeLists.txt | 29 ++++----- ci/pr_run_tests.sh | 30 ++++++++++ include/usb_cam/learning/interface.hpp | 12 ++-- src/interface.cpp | 32 +++++----- test/test_learning_interface.cpp | 61 +++++++++++++++++++ test/test_pixel_formats.cpp | 49 --------------- test/test_usb_cam_lib.cpp | 59 ------------------ test/test_usb_cam_utils.cpp | 83 -------------------------- 9 files changed, 130 insertions(+), 227 deletions(-) create mode 100755 ci/pr_run_tests.sh create mode 100644 test/test_learning_interface.cpp delete mode 100644 test/test_pixel_formats.cpp delete mode 100644 test/test_usb_cam_lib.cpp delete mode 100644 test/test_usb_cam_utils.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a4b6bf3..f9e6ab43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: - ci_script: [pr_compile] + ci_script: [pr_compile, pr_run_tests] steps: - name: Checkout diff --git a/CMakeLists.txt b/CMakeLists.txt index 733b3bd4..397d0731 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,22 +103,19 @@ target_include_directories(${PROJECT_NAME}_node PUBLIC # Testing if(BUILD_TESTING) - if($ENV{ROS_VERSION} EQUAL 2) - find_package(ament_lint_auto REQUIRED) - ament_lint_auto_find_test_dependencies() - find_package(ament_cmake_gtest) - - # Unit tests - ament_add_gtest(test_usb_cam_utils test/test_usb_cam_utils.cpp) - target_link_libraries(test_usb_cam_utils ${PROJECT_NAME}) - - ament_add_gtest(test_pixel_formats test/test_pixel_formats.cpp) - target_link_libraries(test_pixel_formats ${PROJECT_NAME}) - - # Integration tests (commented out as per TODO) - # ament_add_gtest(test_usb_cam_lib test/test_usb_cam_lib.cpp) - # target_link_libraries(test_usb_cam_lib ${PROJECT_NAME}) - endif() + # Find GTest package + find_package(GTest REQUIRED) + include_directories(${GTEST_INCLUDE_DIRS}) + + catkin_add_gtest(test_learning_interface test/test_learning_interface.cpp) + target_link_libraries(test_learning_interface + ${PROJECT_NAME} + ${catkin_LIBRARIES} + GTest::gtest_main + ${NVINFER} + ${NVINFER_PLUGIN} + ${CUDA_LIBRARIES} + ) endif() # Installation rules diff --git a/ci/pr_run_tests.sh b/ci/pr_run_tests.sh new file mode 100755 index 00000000..faac19a7 --- /dev/null +++ b/ci/pr_run_tests.sh @@ -0,0 +1,30 @@ +#!/bin/bash +source /opt/ros/noetic/setup.bash + +rm -rf build +mkdir -p build +cd build +if cmake .. -DBUILD_TESTING=ON +then + echo "CMake successfull" + if make test_learning_interface + then + echo "Make successfull" + else + echo "Make failed" + exit 1 + fi +else + echo "CMake failed" + exit 1 +fi + +if ./devel/lib/usb_cam/test_learning_interface +then + echo "Tests successful" +else + echo "Tests failed" + exit 1 +fi + + diff --git a/include/usb_cam/learning/interface.hpp b/include/usb_cam/learning/interface.hpp index 30e75dcc..ba88724d 100644 --- a/include/usb_cam/learning/interface.hpp +++ b/include/usb_cam/learning/interface.hpp @@ -22,7 +22,6 @@ class LearningInterface { void load_model(); bool run_inference(size_t batch_size); - virtual ~LearningInterface() { // if (_context) _context->destroy(); @@ -36,9 +35,17 @@ class LearningInterface { delete[] _output_buffer; } + float* get_input_buffer() { return _input_buffer; } + nvinfer1::ICudaEngine* get_engine() { return _engine; } + nvinfer1::IExecutionContext* get_context() { return _context; } + nvinfer1::IRuntime* get_runtime() { return _runtime; } + protected: float* _input_buffer = nullptr; float* _output_buffer = nullptr; + nvinfer1::ICudaEngine* _engine = nullptr; + nvinfer1::IExecutionContext* _context = nullptr; + nvinfer1::IRuntime* _runtime = nullptr; size_t input_height; size_t input_width; size_t output_height; @@ -46,9 +53,6 @@ class LearningInterface { std::string _model_path; private: - nvinfer1::ICudaEngine* _engine = nullptr; - nvinfer1::IExecutionContext* _context = nullptr; - nvinfer1::IRuntime* _runtime = nullptr; void* _buffers[2] = { nullptr, nullptr }; }; diff --git a/src/interface.cpp b/src/interface.cpp index 1a402f48..77d70d66 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -30,23 +30,25 @@ void LearningInterface::load_model() { // Allocate buffers for input and output size_t input_size; size_t output_size; - // for (int io = 0; io < _engine->getNbIOTensors(); io++) { - // const char* name = _engine->getIOTensorName(io); - // std::cout << io << ": " << name; - // const nvinfer1::Dims dims = _engine->getTensorShape(name); + for (int io = 0; io < _engine->getNbBindings(); io++) { + const char* name = _engine->getBindingName(io); + std::cout << io << ": " << name; + const nvinfer1::Dims dims = _engine->getBindingDimensions(io); - // size_t total_dims = 1; - // for (int d = 0; d < dims.nbDims; d++) { - // total_dims *= dims.d[d]; - // } + size_t total_dims = 1; + for (int d = 0; d < dims.nbDims; d++) { + total_dims *= dims.d[d]; + } - // std::cout << " size: " << total_dims << std::endl; - // if (io == 0) { - // input_size = total_dims * sizeof(float); - // } else if (io == 1) { - // output_size = total_dims * sizeof(float); - // } - // } + std::cout << " size: " << total_dims << std::endl; + + // Check if it's an input or output binding + if (_engine->bindingIsInput(io)) { + input_size = total_dims * sizeof(float); + } else { + output_size = total_dims * sizeof(float); + } + } // Allocate device buffers cudaMalloc(&_buffers[0], input_size); diff --git a/test/test_learning_interface.cpp b/test/test_learning_interface.cpp new file mode 100644 index 00000000..c6eaeb7b --- /dev/null +++ b/test/test_learning_interface.cpp @@ -0,0 +1,61 @@ +#include +#include "usb_cam/learning/raft.hpp" +#include +#include +#include + +// Define a fixture for Raft tests +class RaftTest : public ::testing::Test { +protected: + // Initialize variables for the test + std::string model_path = "path/to/model.onnx"; // Change to a valid model path + size_t input_height = 224; + size_t input_width = 224; + + Raft* raft; + + void SetUp() override { + // Instantiate the Raft model with the test parameters + raft = new Raft(model_path, input_height, input_width); + raft->load_model(); + } + + void TearDown() override { + delete raft; + } +}; + +TEST_F(RaftTest, TestModelLoad) { + // Test that the model loads successfully + ASSERT_NE(raft->get_engine(), nullptr); + ASSERT_NE(raft->get_context(), nullptr); + ASSERT_NE(raft->get_runtime(), nullptr); +} + +TEST_F(RaftTest, TestSetInput) { + // Create a dummy input buffer + std::vector input_data(input_height * input_width, 128); + + // Set input and check if it is copied to the device + raft->set_input(input_data.data(), input_height, input_width); + + // Allocate host memory to copy back the data from GPU for verification + std::vector host_input(input_height * input_width); + cudaMemcpy(host_input.data(), raft->get_input_buffer(), input_height * input_width * sizeof(float), cudaMemcpyDeviceToHost); + + // Verify the data (simple check to see if values are scaled correctly) + for (size_t i = 0; i < host_input.size(); ++i) { + ASSERT_NEAR(host_input[i], 128.0f / 255.0f, 1e-5); + } +} + +TEST_F(RaftTest, TestRunInference) { + // Dummy batch size + size_t batch_size = 1; + + // Run inference + bool success = raft->run_inference(batch_size); + + // Check if inference ran successfully + ASSERT_TRUE(success); +} diff --git a/test/test_pixel_formats.cpp b/test/test_pixel_formats.cpp deleted file mode 100644 index 44a9a566..00000000 --- a/test/test_pixel_formats.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2023 Evan Flynn -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// * Neither the name of the Evan Flynn nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - - -#include - -#include - -#include "usb_cam/formats/pixel_format_base.hpp" - -TEST(test_pixel_formats, pixel_format_base_class) { - auto test_pix_fmt = usb_cam::formats::default_pixel_format(); - - EXPECT_EQ(test_pix_fmt.name(), "yuyv"); - EXPECT_EQ(test_pix_fmt.v4l2(), V4L2_PIX_FMT_YUYV); - EXPECT_EQ(test_pix_fmt.channels(), 2); - EXPECT_EQ(test_pix_fmt.bit_depth(), 8); - EXPECT_EQ(test_pix_fmt.requires_conversion(), false); - - EXPECT_EQ(test_pix_fmt.is_bayer(), false); - // TOOD(flynneva): should this be true for `yuyv`? - EXPECT_EQ(test_pix_fmt.is_color(), false); - EXPECT_EQ(test_pix_fmt.is_mono(), false); -} diff --git a/test/test_usb_cam_lib.cpp b/test/test_usb_cam_lib.cpp deleted file mode 100644 index f0801586..00000000 --- a/test/test_usb_cam_lib.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2023 Evan Flynn -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// * Neither the name of the Evan Flynn nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include - -#include -#include -#include - -#include "usb_cam/usb_cam.hpp" -#include "usb_cam/utils.hpp" - -TEST(test_usb_cam_lib, test_usb_cam_class) { - usb_cam::UsbCam test_usb_cam; - - auto supported_fmts = test_usb_cam.get_supported_formats(); - - // TODO(flynneva): iterate over availble formats with test_usb_cam obj - for (auto fmt : supported_fmts) { - std::cerr << "format: " << fmt.format.type << std::endl; - } - - // TODO(flynneva): rework these tests in another MR - { - // test_usb_cam.configure( - // "/dev/video0", - // usb_cam::utils::IO_METHOD_MMAP, - // "yuyv2rgb", 640, 480, 30); - // test_usb_cam.start(); - // TODO(flynneva): uncomment once /dev/video0 can be simulated in CI - // EXPECT_TRUE(test_usb_cam.is_capturing()); - // test_usb_cam.shutdown(); - } -} diff --git a/test/test_usb_cam_utils.cpp b/test/test_usb_cam_utils.cpp deleted file mode 100644 index a0ac6fcb..00000000 --- a/test/test_usb_cam_utils.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2023 Evan Flynn -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// * Neither the name of the Evan Flynn nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include -#include - -#include - -#include "usb_cam/utils.hpp" -#include "usb_cam/formats/utils.hpp" - - -using usb_cam::utils::io_method_from_string; - - -TEST(test_usb_cam_utils, test_io_method_from_string) { - usb_cam::utils::io_method_t test_io; - - test_io = io_method_from_string("mmap"); - EXPECT_EQ(test_io, usb_cam::utils::IO_METHOD_MMAP); - - test_io = io_method_from_string("read"); - EXPECT_EQ(test_io, usb_cam::utils::IO_METHOD_READ); - - test_io = io_method_from_string("userptr"); - EXPECT_EQ(test_io, usb_cam::utils::IO_METHOD_USERPTR); - - test_io = io_method_from_string("bananas"); - EXPECT_EQ(test_io, usb_cam::utils::IO_METHOD_UNKNOWN); -} - -TEST(test_usb_cam_utils, test_clip_value) { - // Clip values to 0 if -128<=val<0 - for (int i = -128; i < 0; i++) { - EXPECT_EQ(0, usb_cam::formats::CLIPVALUE(i)); - } - // Do not clip values between 0 383 - // these will use the old method (non-array method) - EXPECT_EQ(0, usb_cam::formats::CLIPVALUE(-129)); - EXPECT_EQ(255, usb_cam::formats::CLIPVALUE(400)); -} - -TEST(test_usb_cam_utils, test_monotonic_to_real_time) { - // Get timeval to use for test - - const time_t test_time_t = usb_cam::utils::get_epoch_time_shift_us(); - - EXPECT_NE(test_time_t, 0); -}