Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add test-dds-adapter-depth test #13605

Merged
merged 6 commits into from
Jan 6, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
#pragma once


namespace rsutils {
namespace concurrency {


// A handler for catching Control-C input from the user
//
// NOTE: only a single instance should be in use: using more than one has undefined behavior
//
class control_c_handler
{
public:
control_c_handler();
~control_c_handler();

// Return true if a Control-C happened
bool was_pressed() const;

// Make was_pressed() return false
void reset();

// Block until a Control-C happens
// If already was_pressed(), the state is cleared and a new Control-C is waited on
void wait();
};


} // namespace concurrency
} // namespace rsutils
100 changes: 100 additions & 0 deletions third-party/rsutils/include/rsutils/concurrency/event.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
#pragma once

#include <chrono>
#include <mutex>
#include <condition_variable>


namespace rsutils {
namespace concurrency {


// A Python Event-like implementation, simplifying condition-variable and mutex access
//
class event
{
mutable std::condition_variable _cv;
mutable std::mutex _m;
bool _is_set;

public:
event()
: _is_set( false )
{
}

// Return true if the event was set()
bool is_set() const
{
std::unique_lock< std::mutex > lock( _m );
return _is_set;
}

operator bool() const { return is_set(); }

// Trigger the event
// Threads waiting on it will wake up
void set()
{
{
std::unique_lock< std::mutex > lock( _m );
_is_set = true;
}
_cv.notify_all();
}

// Untrigger the event
// Does not affect any threads
void clear()
{
std::unique_lock< std::mutex > lock( _m );
_is_set = false;
}

// Block until the event is set()
// If already set, returns immediately
// The event remains set when returning: it needs to be cleared...
void wait() const
{
std::unique_lock< std::mutex > lock( _m );
if( ! _is_set )
_cv.wait( lock );
}

// Clear and block until the event is set() again
void clear_and_wait()
{
std::unique_lock< std::mutex > lock( _m );
_is_set = false;
_cv.wait( lock );
}

// Block until the event is set(), or the timeout occurs
// If already set, returns immediately
// Returns true unless a timeout occurred
template< class Rep, class Period >
bool wait( std::chrono::duration< Rep, Period > const & timeout ) const
{
std::unique_lock< std::mutex > lock( _m );
if( ! _is_set )
_is_set = ( std::cv_status::timeout != _cv.wait( lock, timeout ) );
return _is_set;
}

// Clear and block until the event is set() again or timeout occurs
// Returns true unless a timeout occurred
template< class Rep, class Period >
bool clear_and_wait( std::chrono::duration< Rep, Period > const & timeout )
{
std::unique_lock< std::mutex > lock( _m );
_is_set = false;
_is_set = ( std::cv_status::timeout != _cv.wait( lock, timeout ) );
return _is_set;
}
};


} // namespace concurrency
} // namespace rsutils
86 changes: 86 additions & 0 deletions third-party/rsutils/src/control-c-handler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
#include <rsutils/concurrency/control-c-handler.h>
#include <rsutils/concurrency/event.h>
#include <rsutils/easylogging/easyloggingpp.h>

#include <signal.h>
#include <atomic>


namespace rsutils {
namespace concurrency {


namespace {

event sigint_ev;
std::atomic_bool in_use( false );


void handle_signal( int signal )
{
switch( signal )
{
case SIGINT:
sigint_ev.set();
break;
}
}

} // namespace


control_c_handler::control_c_handler()
{
if( in_use.exchange( true ) )
throw std::runtime_error( "a Control-C handler is already in effect" );
#ifdef _WIN32
signal( SIGINT, handle_signal );
#else
struct sigaction sa;
sa.sa_handler = &handle_signal;
sa.sa_flags = SA_RESTART;
sigfillset( &sa.sa_mask );
if( sigaction( SIGINT, &sa, NULL ) == -1 )
LOG_ERROR( "Cannot install SIGINT handler" );
#endif
}


control_c_handler::~control_c_handler()
{
#ifdef _WIN32
signal( SIGINT, SIG_DFL );
#else
struct sigaction sa;
sa.sa_handler = SIG_DFL;
sa.sa_flags = SA_RESTART;
sigfillset( &sa.sa_mask );
if( sigaction( SIGINT, &sa, NULL ) == -1 )
LOG_DEBUG( "cannot uninstall SIGINT handler" );
#endif
in_use = false;
}


bool control_c_handler::was_pressed() const
{
return sigint_ev.is_set();
}


void control_c_handler::reset()
{
sigint_ev.clear();
}


void control_c_handler::wait()
{
sigint_ev.clear_and_wait();
}


} // namespace concurrency
} // namespace rsutils
7 changes: 5 additions & 2 deletions tools/dds/dds-adapter/rs-dds-adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <rsutils/easylogging/easyloggingpp.h>
#include <rsutils/json.h>
#include <rsutils/json-config.h>
#include <rsutils/concurrency/control-c-handler.h>

#include <string>
#include <iostream>
Expand Down Expand Up @@ -195,8 +196,10 @@ try
device_handlers_list.erase( dev );
} );

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 0);// Pend until CTRL + C is pressed

{
rsutils::concurrency::control_c_handler control_c;
control_c.wait();
}
std::cout << "Shutting down rs-dds-adapter..." << std::endl;

return EXIT_SUCCESS;
Expand Down
86 changes: 86 additions & 0 deletions unit-tests/dds/adapter/test-depth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# License: Apache 2.0. See LICENSE file in root directory.
# Copyright(c) 2024 Intel Corporation. All Rights Reserved.

#test:donotrun:!dds
#test:device D400*

from rspy import log, repo, test
import time


with test.closure( 'Run rs-dds-adapter', on_fail=test.ABORT ):
adapter_path = repo.find_built_exe( 'tools/dds/dds-adapter', 'rs-dds-adapter' )
if test.check( adapter_path ):
import subprocess, signal
cmd = [adapter_path, '--domain-id', '123']
if log.is_debug_on():
cmd.append( '--debug' )
adapter_process = subprocess.Popen( cmd,
stdout=None,
stderr=subprocess.STDOUT,
universal_newlines=True ) # don't fail on errors

from rspy import librs as rs
if log.is_debug_on():
rs.log_to_console( rs.log_severity.debug )

with test.closure( 'Initialize librealsense context', on_fail=test.ABORT ):
context = rs.context( { 'dds': { 'enabled': True, 'domain': 123, 'participant': 'client' }} )

with test.closure( 'Wait for a device', on_fail=test.ABORT ):
# Note: takes time for a device to enumerate, and more to get it discovered
dev = rs.wait_for_devices( context, rs.only_sw_devices, n=1., timeout=8 )

with test.closure( 'Get sensor', on_fail=test.ABORT ):
sensor = dev.first_depth_sensor()
test.check( sensor )

with test.closure( 'Find profile', on_fail=test.ABORT ):
for p in sensor.profiles:
log.d( p )
profile = next( p for p in sensor.profiles
if p.fps() == 30
and p.stream_type() == rs.stream.depth )
test.check( profile )

n_frames = 0
start_time = None
def frame_callback( frame ):
global n_frames, start_time
if n_frames == 0:
start_time = time.perf_counter()
n_frames += 1

with test.closure( f'Stream {profile}', on_fail=test.ABORT ):
sensor.open( [profile] )
sensor.start( frame_callback )

with test.closure( 'Let it stream' ):
time.sleep( 3 )
end_time = time.perf_counter()
if test.check( n_frames > 0 ):
test.info( 'start_time', start_time )
test.info( 'end_time', end_time )
test.info( 'n_frames', n_frames )
test.check_approx_abs( n_frames / (end_time-start_time), 29.5, 1 )

with test.closure( 'Open the same profile while streaming!' ):
test.check_throws( lambda:
sensor.open( [profile] ),
RuntimeError, 'open(...) failed. Software device is streaming!' )

with test.closure( 'Stop streaming' ):
sensor.stop()
sensor.close()

del profile
del sensor
del dev
del context

with test.closure( 'Stop rs-dds-adapter' ):
adapter_process.send_signal( signal.SIGTERM )
adapter_process.wait( timeout=2 )

test.print_results()

2 changes: 1 addition & 1 deletion unit-tests/dds/test-librs-connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import d435i
import d405
import librs as rs
from rspy import librs as rs
if log.is_debug_on():
rs.log_to_console( rs.log_severity.debug )
from time import sleep
Expand Down
2 changes: 1 addition & 1 deletion unit-tests/dds/test-librs-device-properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import d435i
import d405
import d455
import librs as rs
from rspy import librs as rs

if log.is_debug_on():
rs.log_to_console( rs.log_severity.debug )
Expand Down
2 changes: 1 addition & 1 deletion unit-tests/dds/test-librs-extrinsics.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from rspy import log, test
log.nested = 'C '

import librs as rs
from rspy import librs as rs
if log.is_debug_on():
rs.log_to_console( rs.log_severity.debug )
from time import sleep
Expand Down
2 changes: 1 addition & 1 deletion unit-tests/dds/test-librs-formats-conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#test:retries:gha 2

from rspy import log, test
import librs as rs
from rspy import librs as rs

if log.is_debug_on():
rs.log_to_console( rs.log_severity.debug )
Expand Down
2 changes: 1 addition & 1 deletion unit-tests/dds/test-librs-intrinsics.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def close_server( instance ):

log.nested = 'C '

import librs as rs
from rspy import librs as rs
if log.is_debug_on():
rs.log_to_console( rs.log_severity.debug )

Expand Down
2 changes: 1 addition & 1 deletion unit-tests/dds/test-librs-options.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def _on_set_option( server, option, value ):
###############################################################################################################
# The client is LibRS
#
import librs as rs
from rspy import librs as rs
if log.is_debug_on():
rs.log_to_console( rs.log_severity.debug )

Expand Down
2 changes: 1 addition & 1 deletion unit-tests/dds/test-metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def __exit__( self, type, value, traceback ):
#############################################################################################
#
with test.closure( "Initialize librs device", on_fail=test.ABORT ):
import librs as rs
from rspy import librs as rs
if log.is_debug_on():
rs.log_to_console( rs.log_severity.debug )
context = rs.context( { 'dds': { 'enabled': True, 'domain': 123, 'participant': 'librs' }} )
Expand Down
Loading
Loading