# include <QEventLoop>
# include <QMap>
# include <QThread>
# include "catch2/catch.hpp"
# include "selfdrive/ui/soundd/sound.h"
class TestSound : public Sound {
public :
TestSound ( ) : Sound ( ) {
for ( auto i = sounds . constBegin ( ) ; i ! = sounds . constEnd ( ) ; + + i ) {
sound_stats [ i . key ( ) ] = { 0 , 0 } ;
QObject : : connect ( i . value ( ) . first , & QSoundEffect : : playingChanged , [ = , s = i . value ( ) . first , a = i . key ( ) ] ( ) {
if ( s - > isPlaying ( ) ) {
sound_stats [ a ] . first + + ;
} else {
sound_stats [ a ] . second + + ;
}
} ) ;
}
}
QMap < AudibleAlert , std : : pair < int , int > > sound_stats ;
} ;
void controls_thread ( int loop_cnt ) {
PubMaster pm ( { " controlsState " , " deviceState " } ) ;
MessageBuilder deviceStateMsg ;
auto deviceState = deviceStateMsg . initEvent ( ) . initDeviceState ( ) ;
deviceState . setStarted ( true ) ;
const int DT_CTRL = 10 ; // ms
for ( int i = 0 ; i < loop_cnt ; + + i ) {
for ( auto & [ alert , fn , loops ] : sound_list ) {
printf ( " testing %s \n " , qPrintable ( fn ) ) ;
for ( int j = 0 ; j < 1000 / DT_CTRL ; + + j ) {
MessageBuilder msg ;
auto cs = msg . initEvent ( ) . initControlsState ( ) ;
cs . setAlertSound ( alert ) ;
cs . setAlertType ( fn . toStdString ( ) ) ;
pm . send ( " controlsState " , msg ) ;
pm . send ( " deviceState " , deviceStateMsg ) ;
QThread : : msleep ( DT_CTRL ) ;
}
}
}
// send no alert sound
for ( int j = 0 ; j < 1000 / DT_CTRL ; + + j ) {
MessageBuilder msg ;
msg . initEvent ( ) . initControlsState ( ) ;
pm . send ( " controlsState " , msg ) ;
QThread : : msleep ( DT_CTRL ) ;
}
QThread : : currentThread ( ) - > quit ( ) ;
}
TEST_CASE ( " test soundd " ) {
QEventLoop loop ;
TestSound test_sound ;
const int test_loop_cnt = 2 ;
QThread t ;
QObject : : connect ( & t , & QThread : : started , [ = ] ( ) { controls_thread ( test_loop_cnt ) ; } ) ;
QObject : : connect ( & t , & QThread : : finished , [ & ] ( ) { loop . quit ( ) ; } ) ;
t . start ( ) ;
loop . exec ( ) ;
for ( const AudibleAlert alert : test_sound . sound_stats . keys ( ) ) {
auto [ play , stop ] = test_sound . sound_stats [ alert ] ;
REQUIRE ( play = = test_loop_cnt ) ;
REQUIRE ( stop = = test_loop_cnt ) ;
}
}