Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ coverage:
target: auto
# allow slight decreases in coverage compared to the base ref
threshold: 1%
patch:
default:
target: 80%
threshold: 5%

ignore:
- ^build.* # for generated message wrappers
Expand Down
43 changes: 43 additions & 0 deletions src/nebula_ouster/nebula_ouster_common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,47 @@ install(DIRECTORY include/${PROJECT_NAME}/ DESTINATION include/${PROJECT_NAME})
ament_export_targets(export_nebula_ouster_common)
ament_export_dependencies(nebula_core_common nebula_core_decoders)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
find_package(ament_cmake_gtest REQUIRED)

set(_nebula_ouster_sdk "${CMAKE_CURRENT_SOURCE_DIR}/../vendor/ouster-sdk")

set(BUILD_SENSOR OFF CACHE BOOL "" FORCE)
set(BUILD_PCAP OFF CACHE BOOL "" FORCE)
set(BUILD_OSF OFF CACHE BOOL "" FORCE)
set(BUILD_VIZ OFF CACHE BOOL "" FORCE)
set(BUILD_MAPPING OFF CACHE BOOL "" FORCE)
set(_PARENT_BUILD_TESTING ${BUILD_TESTING})
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(BUILD_PYTHON_MODULE OFF CACHE BOOL "" FORCE)

if(NOT TARGET ouster_client)
add_subdirectory("${_nebula_ouster_sdk}" "${CMAKE_CURRENT_BINARY_DIR}/ouster-sdk-build")
endif()

# Restore BUILD_TESTING after ouster-sdk
set(BUILD_TESTING ${_PARENT_BUILD_TESTING} CACHE BOOL "" FORCE)

set(_ouster_gen_includes "${CMAKE_CURRENT_BINARY_DIR}/ouster-sdk-build/generated")

ament_add_gtest(
test_ouster_calibration_data
test/test_ouster_calibration_data.cpp
)
target_link_libraries(
test_ouster_calibration_data
nebula_ouster_common
nebula_core_common::nebula_core_common
ouster_client
)
target_include_directories(
test_ouster_calibration_data
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
${_nebula_ouster_sdk}/ouster_client/include
${_ouster_gen_includes}
)
endif()

ament_package()
3 changes: 3 additions & 0 deletions src/nebula_ouster/nebula_ouster_common/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
<depend>nebula_core_common</depend>
<depend>nebula_core_decoders</depend>

<test_depend>ament_cmake_gtest</test_depend>
<test_depend>ament_lint_auto</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright 2026 TIER IV, Inc.

#include "nebula_ouster_common/ouster_calibration_data.hpp"

#include <gtest/gtest.h>

#include <cstdio>
#include <fstream>
#include <string>

namespace nebula::drivers
{

class TestOusterCalibrationData : public ::testing::Test
{
protected:
void SetUp() override
{
// Generate a valid metadata JSON from the SDK's default sensor info
auto info = ouster::sdk::core::default_sensor_info(ouster::sdk::core::LidarMode::_512x10);
valid_metadata_json_ = info.to_json_string();
}

std::string valid_metadata_json_;
};

TEST_F(TestOusterCalibrationData, TestLoadFromStringSuccess)
{
auto result = OusterCalibrationData::load_from_string(valid_metadata_json_);
ASSERT_TRUE(result.has_value());

auto calibration = result.value();
EXPECT_FALSE(calibration.metadata_json.empty());
EXPECT_NE(calibration.sensor_info, nullptr);
EXPECT_NE(calibration.packet_format, nullptr);
}

TEST_F(TestOusterCalibrationData, TestLoadFromStringEmpty)
{
auto result = OusterCalibrationData::load_from_string("");
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, OusterCalibrationData::ErrorCode::EMPTY_METADATA);
}

TEST_F(TestOusterCalibrationData, TestLoadFromFileSuccess)
{
// Write valid metadata to a temporary file
std::string tmp_path = "/tmp/test_ouster_metadata.json";
{
std::ofstream f(tmp_path);
f << valid_metadata_json_;
}

auto result = OusterCalibrationData::load_from_file(tmp_path);
ASSERT_TRUE(result.has_value());

auto calibration = result.value();
EXPECT_EQ(calibration.calibration_file, tmp_path);
EXPECT_FALSE(calibration.metadata_json.empty());
EXPECT_NE(calibration.sensor_info, nullptr);
EXPECT_NE(calibration.packet_format, nullptr);

std::remove(tmp_path.c_str());
}

TEST_F(TestOusterCalibrationData, TestLoadFromFileNotFound)
{
auto result = OusterCalibrationData::load_from_file("/nonexistent/path/metadata.json");
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, OusterCalibrationData::ErrorCode::OPEN_FOR_READ_FAILED);
}

TEST_F(TestOusterCalibrationData, TestLoadFromFileEmpty)
{
std::string tmp_path = "/tmp/test_ouster_empty_metadata.json";
{
std::ofstream f(tmp_path);
// Write empty file
}

auto result = OusterCalibrationData::load_from_file(tmp_path);
ASSERT_FALSE(result.has_value());
EXPECT_EQ(result.error().code, OusterCalibrationData::ErrorCode::EMPTY_METADATA);

std::remove(tmp_path.c_str());
}

TEST_F(TestOusterCalibrationData, TestSaveToFileSuccess)
{
auto load_result = OusterCalibrationData::load_from_string(valid_metadata_json_);
ASSERT_TRUE(load_result.has_value());

auto calibration = load_result.value();
std::string tmp_path = "/tmp/test_ouster_save_metadata.json";
auto save_result = calibration.save_to_file(tmp_path);
ASSERT_TRUE(save_result.has_value());

// Verify file content
std::ifstream f(tmp_path);
std::string content((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
EXPECT_EQ(content, valid_metadata_json_);

std::remove(tmp_path.c_str());
}

TEST_F(TestOusterCalibrationData, TestSaveToFileInvalidPath)
{
auto load_result = OusterCalibrationData::load_from_string(valid_metadata_json_);
ASSERT_TRUE(load_result.has_value());

auto calibration = load_result.value();
auto save_result = calibration.save_to_file("/nonexistent/directory/metadata.json");
ASSERT_FALSE(save_result.has_value());
EXPECT_EQ(save_result.error().code, OusterCalibrationData::ErrorCode::OPEN_FOR_WRITE_FAILED);
}

} // namespace nebula::drivers

int main(int argc, char * argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
26 changes: 26 additions & 0 deletions src/nebula_ouster/nebula_ouster_decoders/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ set(BUILD_PCAP OFF CACHE BOOL "Ouster SDK: pcap" FORCE)
set(BUILD_OSF OFF CACHE BOOL "Ouster SDK: osf" FORCE)
set(BUILD_VIZ OFF CACHE BOOL "Ouster SDK: visualizer" FORCE)
set(BUILD_MAPPING OFF CACHE BOOL "Ouster SDK: mapping" FORCE)
set(_PARENT_BUILD_TESTING ${BUILD_TESTING})
set(BUILD_TESTING OFF CACHE BOOL "Ouster SDK: tests" FORCE)
set(BUILD_EXAMPLES OFF CACHE BOOL "Ouster SDK: examples" FORCE)
set(BUILD_PYTHON_MODULE OFF CACHE BOOL "Ouster SDK: python" FORCE)

add_subdirectory("${_nebula_ouster_sdk}" "${CMAKE_CURRENT_BINARY_DIR}/ouster-sdk-build")

# Restore BUILD_TESTING after ouster-sdk subdirectory
set(BUILD_TESTING ${_PARENT_BUILD_TESTING} CACHE BOOL "Build tests" FORCE)

if(TARGET ouster_client)
# ouster-sdk has few C++ warnings which are treated as errors by the CI. Disable them for now.
target_compile_options(ouster_client PRIVATE -Wno-pedantic)
Expand Down Expand Up @@ -94,4 +98,26 @@ ament_export_dependencies(
nebula_core_decoders
OpenSSL)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
find_package(ament_cmake_gtest REQUIRED)

ament_add_gtest(
test_ouster_decoder
test/test_ouster_decoder.cpp
)
target_link_libraries(
test_ouster_decoder
nebula_ouster_decoders
nebula_core_common::nebula_core_common
nebula_ouster_common::nebula_ouster_common
)
target_include_directories(
test_ouster_decoder
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
${_nebula_ouster_sdk}/ouster_client/include
${_ouster_gen_includes}
)
endif()

ament_package()
3 changes: 3 additions & 0 deletions src/nebula_ouster/nebula_ouster_decoders/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
<depend>nebula_core_decoders</depend>
<depend>nebula_ouster_common</depend>

<test_depend>ament_cmake_gtest</test_depend>
<test_depend>ament_lint_auto</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
Expand Down
Loading
Loading