diff --git a/unit-tests/func/alt-ir/alt-ir-common.h b/unit-tests/func/alt-ir/alt-ir-common.h new file mode 100644 index 0000000000..e63806e175 --- /dev/null +++ b/unit-tests/func/alt-ir/alt-ir-common.h @@ -0,0 +1,96 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#include "../../test.h" +#include + +using namespace rs2; + + +bool alt_ir_supported_or_message( const rs2::depth_sensor & depth_sens ) +{ + REQUIRE( depth_sens ); + + if( depth_sens.supports( RS2_OPTION_ALTERNATE_IR ) ) + return true; + + std::cout << "FW version " << depth_sens.get_info( RS2_CAMERA_INFO_FIRMWARE_VERSION ) + << " doesn't support alt IR option"; + return false; +} + +void set_alt_ir_if_needed( const rs2::depth_sensor & depth_sens, float val ) +{ + REQUIRE( depth_sens.supports( RS2_OPTION_ALTERNATE_IR ) ); + auto alt_ir = depth_sens.get_option( RS2_OPTION_ALTERNATE_IR ); + if( alt_ir != val ) + REQUIRE_NOTHROW( depth_sens.set_option( RS2_OPTION_ALTERNATE_IR, val ) ); +} + +void enable_alt_ir_and_check_that_AC_fails( + const rs2::device & dev, + const rs2::depth_sensor & depth_sens, + const std::vector< stream_profile > & expected_profiles ) +{ + std::vector< stream_profile > profiles = expected_profiles; + REQUIRE_NOTHROW( depth_sens.open( profiles ) ); + REQUIRE_NOTHROW( depth_sens.start( [&]( rs2::frame f ) {} ) ); + + set_alt_ir_if_needed( depth_sens, 1 ); + + auto calib = dev.as< rs2::device_calibration >(); + if( calib ) + { + rs2_calibration_status status; + calib.register_calibration_change_callback( [&]( rs2_calibration_status cal_status ) { + status = cal_status; + } ); + + // Before throwing, AC will notify of a BAD_CONDITIONS status + REQUIRE_THROWS( calib.trigger_device_calibration( RS2_CALIBRATION_MANUAL_DEPTH_TO_RGB ) ); + + REQUIRE( status == RS2_CALIBRATION_BAD_CONDITIONS ); + } + + REQUIRE_NOTHROW( depth_sens.stop() ); + REQUIRE_NOTHROW( depth_sens.close() ); +} + +void enable_alt_ir_and_check_that_all_streams_arrived( + const rs2::device & dev, + const rs2::depth_sensor & depth_sens, + const std::vector< stream_profile > & expected_profiles ) +{ + std::vector< stream_profile > profiles = expected_profiles; + REQUIRE_NOTHROW( depth_sens.open( profiles ) ); + + std::condition_variable cv; + std::mutex m; + + auto wait_for_streams = [&]() { + profiles = expected_profiles; + std::unique_lock< std::mutex > lock( m ); + REQUIRE( cv.wait_for( lock, std::chrono::seconds( 20 ), [&]() { + return profiles.size() == 0; + } ) ); + }; + + REQUIRE_NOTHROW( depth_sens.start( [&]( rs2::frame f ) { + std::unique_lock< std::mutex > lock( m ); + remove_all_streams_arrived( f, profiles ); + cv.notify_one(); + } ) ); + + set_alt_ir_if_needed( depth_sens, 1 ); + wait_for_streams(); + + set_alt_ir_if_needed( depth_sens, 0 ); + wait_for_streams(); + + set_alt_ir_if_needed( depth_sens, 1 ); + wait_for_streams(); + + REQUIRE_NOTHROW( depth_sens.stop() ); + REQUIRE_NOTHROW( depth_sens.close() ); + +} diff --git a/unit-tests/func/alt-ir/test-ac-before.cpp b/unit-tests/func/alt-ir/test-ac-before.cpp new file mode 100644 index 0000000000..8aafa70134 --- /dev/null +++ b/unit-tests/func/alt-ir/test-ac-before.cpp @@ -0,0 +1,24 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#include "../func-common.h" +#include "alt-ir-common.h" + +using namespace rs2; + +TEST_CASE( "AC fails if AltIR was enabled before stream start", "[l500][live]" ) +{ + auto devices = find_devices_by_product_line_or_exit( RS2_PRODUCT_LINE_L500 ); + auto dev = devices[0]; + + auto depth_sens = dev.first< rs2::depth_sensor >(); + if( alt_ir_supported_or_message( depth_sens ) ) + { + REQUIRE_NOTHROW( depth_sens.set_option( RS2_OPTION_ALTERNATE_IR, 1 ) ); + + auto depth = find_default_depth_profile( depth_sens ); + auto ir = find_default_ir_profile( depth_sens ); + + enable_alt_ir_and_check_that_AC_fails( dev, depth_sens, { depth, ir } ); + } +} diff --git a/unit-tests/func/alt-ir/test-ac-while.cpp b/unit-tests/func/alt-ir/test-ac-while.cpp new file mode 100644 index 0000000000..1564421bc9 --- /dev/null +++ b/unit-tests/func/alt-ir/test-ac-while.cpp @@ -0,0 +1,22 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#include "../func-common.h" +#include "alt-ir-common.h" + +using namespace rs2; + +TEST_CASE( "AC fails if AltIR was enable after stream start", "[l500][live]" ) +{ + auto devices = find_devices_by_product_line_or_exit( RS2_PRODUCT_LINE_L500 ); + auto dev = devices[0]; + + auto depth_sens = dev.first< rs2::depth_sensor >(); + if( alt_ir_supported_or_message( depth_sens ) ) + { + auto depth = find_default_depth_profile( depth_sens ); + auto ir = find_default_ir_profile( depth_sens ); + + enable_alt_ir_and_check_that_AC_fails( dev, depth_sens, { depth, ir } ); + } +} \ No newline at end of file diff --git a/unit-tests/func/alt-ir/test-sanity-while-streaming.cpp b/unit-tests/func/alt-ir/test-sanity-while-streaming.cpp new file mode 100644 index 0000000000..46d9e11aeb --- /dev/null +++ b/unit-tests/func/alt-ir/test-sanity-while-streaming.cpp @@ -0,0 +1,39 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#include "../func-common.h" +#include "alt-ir-common.h" + +using namespace rs2; + +TEST_CASE( "AltIR", "[l500][live]" ) +{ + + auto devices = find_devices_by_product_line_or_exit( RS2_PRODUCT_LINE_L500 ); + auto dev = devices[0]; + + auto depth_sens = dev.first< rs2::depth_sensor >(); + if( alt_ir_supported_or_message( depth_sens ) ) + { + option_range r; + REQUIRE_NOTHROW( r = depth_sens.get_option_range( RS2_OPTION_ALTERNATE_IR ) ); + + auto depth = find_default_depth_profile( depth_sens ); + auto ir = find_default_ir_profile( depth_sens ); + auto confidence = find_confidence_corresponding_to_depth( depth_sens, depth ); + + REQUIRE_NOTHROW( depth_sens.open( { depth, ir, confidence } ) ); + REQUIRE_NOTHROW( depth_sens.start( [&]( rs2::frame f ) {} ) ); + + for( auto i = r.min; i <= r.max; i+=r.step ) + { + // We expect that no delay is needed between set and get, as would be the case + // with XU options (during streaming) + CHECK_NOTHROW( depth_sens.set_option( RS2_OPTION_ALTERNATE_IR, i ) ); + CHECK( depth_sens.get_option( RS2_OPTION_ALTERNATE_IR ) == i ); + } + + depth_sens.stop(); + depth_sens.close(); + } +} diff --git a/unit-tests/func/alt-ir/test-sanity.cpp b/unit-tests/func/alt-ir/test-sanity.cpp new file mode 100644 index 0000000000..18ae535dd0 --- /dev/null +++ b/unit-tests/func/alt-ir/test-sanity.cpp @@ -0,0 +1,27 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#include "../func-common.h" +#include "alt-ir-common.h" + +using namespace rs2; + +TEST_CASE( "AltIR", "[l500][live]" ) +{ + auto devices = find_devices_by_product_line_or_exit( RS2_PRODUCT_LINE_L500 ); + auto dev = devices[0]; + + auto depth_sens = dev.first< rs2::depth_sensor >(); + if( alt_ir_supported_or_message( depth_sens ) ) + { + option_range r; + REQUIRE_NOTHROW( r = depth_sens.get_option_range( RS2_OPTION_ALTERNATE_IR ) ); + + for( auto i = r.min; i <= r.max; i += r.step ) + { + // Outside of streaming, no delay is expected between set and get + CHECK_NOTHROW( depth_sens.set_option( RS2_OPTION_ALTERNATE_IR, i ) ); + CHECK( depth_sens.get_option( RS2_OPTION_ALTERNATE_IR ) == i ); + } + } +} diff --git a/unit-tests/func/alt-ir/test-streamimg-before.cpp b/unit-tests/func/alt-ir/test-streamimg-before.cpp new file mode 100644 index 0000000000..c05cc7122e --- /dev/null +++ b/unit-tests/func/alt-ir/test-streamimg-before.cpp @@ -0,0 +1,28 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#include "../func-common.h" //todo functional-common.h +#include "alt-ir-common.h" //todo alt-ir-common.h + + +using namespace rs2; + +TEST_CASE( "Enable AltIR before stream start and check that all streams arrived", "[l500][live]" ) +{ + auto devices = find_devices_by_product_line_or_exit( RS2_PRODUCT_LINE_L500 ); + auto dev = devices[0]; + + auto depth_sens = dev.first< rs2::depth_sensor >(); + if( alt_ir_supported_or_message( depth_sens ) ) + { + REQUIRE_NOTHROW( depth_sens.set_option( RS2_OPTION_ALTERNATE_IR, 1 ) ); + + auto depth = find_default_depth_profile( depth_sens ); + auto ir = find_default_ir_profile( depth_sens ); + auto confidence = find_confidence_corresponding_to_depth( depth_sens, depth ); + + enable_alt_ir_and_check_that_all_streams_arrived( dev, + depth_sens, + { depth, ir, confidence } ); + } +} \ No newline at end of file diff --git a/unit-tests/func/alt-ir/test-streaming-while.cpp b/unit-tests/func/alt-ir/test-streaming-while.cpp new file mode 100644 index 0000000000..0c81feb5b8 --- /dev/null +++ b/unit-tests/func/alt-ir/test-streaming-while.cpp @@ -0,0 +1,26 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + + +#include "../func-common.h" +#include "alt-ir-common.h" + +using namespace rs2; + +TEST_CASE( "Enable AltIR while streaming and check that all streams arrived", "[l500][live]" ) +{ + auto devices = find_devices_by_product_line_or_exit( RS2_PRODUCT_LINE_L500 ); + auto dev = devices[0]; + + auto depth_sens = dev.first< rs2::depth_sensor >(); + if( alt_ir_supported_or_message( depth_sens ) ) + { + auto depth = find_default_depth_profile( depth_sens ); + auto ir = find_default_ir_profile( depth_sens ); + auto confidence = find_confidence_corresponding_to_depth( depth_sens, depth ); + + enable_alt_ir_and_check_that_all_streams_arrived( dev, + depth_sens, + { depth, ir, confidence } ); + } +} diff --git a/unit-tests/func/func-common.h b/unit-tests/func/func-common.h new file mode 100644 index 0000000000..52f56a01a2 --- /dev/null +++ b/unit-tests/func/func-common.h @@ -0,0 +1,96 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2020 Intel Corporation. All Rights Reserved. + +#include "../test.h" +#include "librealsense2/rs.hpp" + +using namespace rs2; + +inline rs2::device_list find_devices_by_product_line_or_exit( int product ) +{ + rs2::context ctx; + rs2::device_list devices_list = ctx.query_devices( product ); + if( devices_list.size() == 0 ) + { + std::cout << "No device of the " << product << " product line was found; skipping test" + << std::endl; + exit( 0 ); + } + + return devices_list; +} + +// Remove the frame's stream (or streams if a frameset) from the list of streams we expect to arrive +// If any stream is unexpected, it is ignored +inline void remove_all_streams_arrived( rs2::frame f, + std::vector< rs2::stream_profile > & expected_streams ) +{ + auto remove_stream = [&]() { + auto it = std::remove_if( expected_streams.begin(), + expected_streams.end(), + [&]( rs2::stream_profile s ) { + return s.stream_type() == f.get_profile().stream_type(); + } ); + + + if( it != expected_streams.end() ) + expected_streams.erase( it ); + }; + + if( f.is< rs2::frameset >() ) + { + auto set = f.as< rs2::frameset >(); + set.foreach_rs( [&]( rs2::frame fr ) { remove_stream(); } ); + } + else + { + remove_stream(); + } +} + +inline stream_profile find_default_depth_profile( rs2::depth_sensor depth_sens ) +{ + std::vector< stream_profile > stream_profiles; + REQUIRE_NOTHROW( stream_profiles = depth_sens.get_stream_profiles() ); + + auto depth_profile + = std::find_if( stream_profiles.begin(), stream_profiles.end(), []( stream_profile sp ) { + return sp.is_default() && sp.stream_type() == RS2_STREAM_DEPTH; + } ); + + REQUIRE( depth_profile != stream_profiles.end() ); + return *depth_profile; +} + +inline stream_profile find_default_ir_profile( rs2::depth_sensor depth_sens ) +{ + std::vector< stream_profile > stream_profiles; + REQUIRE_NOTHROW( stream_profiles = depth_sens.get_stream_profiles() ); + + auto ir_profile + = std::find_if( stream_profiles.begin(), stream_profiles.end(), []( stream_profile sp ) { + return sp.is_default() && sp.stream_type() == RS2_STREAM_INFRARED; + } ); + + REQUIRE( ir_profile != stream_profiles.end() ); + return *ir_profile; +} + +inline stream_profile find_confidence_corresponding_to_depth( rs2::depth_sensor depth_sens, + stream_profile depth_profile ) +{ + std::vector< stream_profile > stream_profiles; + REQUIRE_NOTHROW( stream_profiles = depth_sens.get_stream_profiles() ); + + auto confidence_profile + = std::find_if( stream_profiles.begin(), stream_profiles.end(), [&]( stream_profile sp ) { + return sp.stream_type() == RS2_STREAM_CONFIDENCE + && sp.as< rs2::video_stream_profile >().width() + == depth_profile.as< rs2::video_stream_profile >().width() + && sp.as< rs2::video_stream_profile >().height() + == depth_profile.as< rs2::video_stream_profile >().height(); + } ); + + REQUIRE( confidence_profile != stream_profiles.end() ); + return *confidence_profile; +} diff --git a/unit-tests/test.h b/unit-tests/test.h new file mode 100644 index 0000000000..5550903821 --- /dev/null +++ b/unit-tests/test.h @@ -0,0 +1,21 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2015 Intel Corporation. All Rights Reserved. + +#pragma once + +#include "librealsense2/rs.hpp" + +#if ! defined( NO_CATCH_CONFIG_MAIN ) +#define CATCH_CONFIG_MAIN +#endif + +#include "catch.h" + +#include +#ifdef BUILD_SHARED_LIBS +// With static linkage, ELPP is initialized by librealsense, so doing it here will +// create errors. When we're using the shared .so/.dll, the two are separate and we have +// to initialize ours if we want to use the APIs! +INITIALIZE_EASYLOGGINGPP +#endif +