DECLARE_TEST( fs, event ) { event_stream_t* stream; event_block_t* block; event_t* event; char pathstr[] = "/some/path/to/some/file/being/tested"; stream = fs_event_stream(); EXPECT_NE( stream, 0 ); fs_post_event( FOUNDATIONEVENT_FILE_CREATED, pathstr, 36 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_NE( event, 0 ); EXPECT_EQ( event->system, SYSTEM_FOUNDATION ); EXPECT_EQ( event->id, FOUNDATIONEVENT_FILE_CREATED ); EXPECT_STREQ( event->payload, pathstr ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); return 0; }
void* event_thread( object_t thread, void* arg ) { event_block_t* block; event_t* event = 0; while( !thread_should_terminate( thread ) ) { block = event_stream_process( system_event_stream() ); event = 0; while( ( event = event_next( block, event ) ) ) { switch( event->id ) { case FOUNDATIONEVENT_TERMINATE: log_warn( HASH_TEST, WARNING_SUSPICIOUS, "Terminating tests due to event" ); process_exit( -2 ); break; default: break; } } thread_sleep( 10 ); } return 0; }
static void* event_thread( object_t thread, void* arg ) { event_block_t* block; event_t* event = 0; FOUNDATION_UNUSED( arg ); while( !thread_should_terminate( thread ) ) { block = event_stream_process( system_event_stream() ); event = 0; while( ( event = event_next( block, event ) ) ) { switch( event->id ) { case FOUNDATIONEVENT_START: #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID log_debug( HASH_TEST, "Application start event received" ); _test_should_start = true; #endif break; case FOUNDATIONEVENT_TERMINATE: #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID log_debug( HASH_TEST, "Application stop/terminate event received" ); _test_should_terminate = true; #else log_warn( HASH_TEST, WARNING_SUSPICIOUS, "Terminating tests due to event" ); process_exit( -2 ); #endif break; case FOUNDATIONEVENT_FOCUS_GAIN: _test_have_focus = true; break; case FOUNDATIONEVENT_FOCUS_LOST: _test_have_focus = false; break; default: break; } } thread_sleep( 10 ); } log_debug( HASH_TEST, "Application event thread exiting" ); return 0; }
static void* event_loop(void* arg) { event_block_t* block; event_t* event = 0; FOUNDATION_UNUSED(arg); event_stream_set_beacon(system_event_stream(), &thread_self()->beacon); while (!_test_should_terminate) { block = event_stream_process(system_event_stream()); event = 0; while ((event = event_next(block, event))) { switch (event->id) { case FOUNDATIONEVENT_START: #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL log_debug(HASH_TEST, STRING_CONST("Application start event received")); _test_should_start = true; #endif break; case FOUNDATIONEVENT_TERMINATE: #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_PNACL log_debug(HASH_TEST, STRING_CONST("Application stop/terminate event received")); _test_should_terminate = true; break; #else log_warn(HASH_TEST, WARNING_SUSPICIOUS, STRING_CONST("Terminating tests due to event")); process_exit(-2); #endif case FOUNDATIONEVENT_FOCUS_GAIN: _test_have_focus = true; break; case FOUNDATIONEVENT_FOCUS_LOST: _test_have_focus = false; break; default: break; } test_event(event); } thread_wait(); } log_debug(HASH_TEST, STRING_CONST("Application event thread exiting")); return 0; }
static void* event_thread( object_t thread, void* arg ) { event_block_t* block; event_t* event = 0; while( !thread_should_terminate( thread ) ) { block = event_stream_process( system_event_stream() ); event = 0; while( ( event = event_next( block, event ) ) ) { switch( event->id ) { case FOUNDATIONEVENT_START: #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_IOS log_infof( HASH_TEST, "Application start event received" ); _test_should_start = true; #endif break; case FOUNDATIONEVENT_TERMINATE: #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_IOS log_infof( HASH_TEST, "Application terminate event received" ); _test_should_terminate = true; #else log_warn( HASH_TEST, WARNING_SUSPICIOUS, "Terminating tests due to event" ); process_exit( -2 ); #endif break; default: break; } } thread_sleep( 10 ); } return 0; }
// app event loop void check_events(void) { static event_t e; if( event_next(&e) ) { (app_event_handlers)[e.type](e.data); } }
DECLARE_TEST( fs, monitor ) { char* testpath = path_merge( environment_temporary_directory(), string_from_int_static( random64(), 0, 0 ) ); char* filetestpath = path_merge( testpath, string_from_int_static( random64(), 0, 0 ) ); stream_t* test_stream; event_stream_t* stream; event_block_t* block; event_t* event; stream = fs_event_stream(); if( fs_is_file( testpath ) ) fs_remove_file( testpath ); if( !fs_is_directory( testpath ) ) fs_make_directory( testpath ); if( fs_is_file( filetestpath ) ) fs_remove_file( filetestpath ); stream_deallocate( fs_open_file( filetestpath, STREAM_OUT ) ); fs_remove_file( filetestpath ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); fs_monitor( testpath ); thread_sleep( 1000 ); stream_deallocate( fs_open_file( filetestpath, STREAM_OUT ) ); thread_sleep( 100 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_NE( event, 0 ); EXPECT_EQ( event->system, SYSTEM_FOUNDATION ); EXPECT_EQ( event->id, FOUNDATIONEVENT_FILE_CREATED ); EXPECT_STREQ( event->payload, filetestpath ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); test_stream = fs_open_file( filetestpath, STREAM_IN | STREAM_OUT ); stream_write_string( test_stream, filetestpath ); stream_deallocate( test_stream ); thread_sleep( 100 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_NE( event, 0 ); EXPECT_EQ( event->system, SYSTEM_FOUNDATION ); EXPECT_EQ( event->id, FOUNDATIONEVENT_FILE_MODIFIED ); EXPECT_STREQ( event->payload, filetestpath ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); fs_remove_file( filetestpath ); thread_sleep( 100 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_NE( event, 0 ); EXPECT_EQ( event->system, SYSTEM_FOUNDATION ); EXPECT_EQ( event->id, FOUNDATIONEVENT_FILE_DELETED ); EXPECT_STREQ( event->payload, filetestpath ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); fs_unmonitor( testpath ); thread_sleep( 1000 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); stream_deallocate( fs_open_file( filetestpath, STREAM_OUT ) ); thread_sleep( 100 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); fs_remove_file( filetestpath ); thread_sleep( 100 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); fs_remove_directory( testpath ); string_deallocate( testpath ); string_deallocate( filetestpath ); return 0; }
DECLARE_TEST( event, empty ) { event_stream_t* stream; event_block_t* block; event_block_t* old_block; event_t* event; stream = event_stream_allocate( 0 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); old_block = block; block = event_stream_process( stream ); EXPECT_NE( old_block, block ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); block = event_stream_process( stream ); EXPECT_EQ( old_block, block ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); event_stream_deallocate( stream ); stream = event_stream_allocate( 4096 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); old_block = block; block = event_stream_process( stream ); EXPECT_NE( old_block, block ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); block = event_stream_process( stream ); EXPECT_EQ( old_block, block ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); event_stream_deallocate( stream ); return 0; }
DECLARE_TEST( event, delay_threaded ) { object_t thread[32]; producer_thread_arg_t args[32] = {0}; event_stream_t* stream; event_block_t* block; event_t* event; tick_t endtime, curtime, payloadtime, begintime, prevtime; unsigned int read[32]; int i; bool running = true; int num_threads = math_clamp( system_hardware_threads() * 4, 4, 32 ); stream = event_stream_allocate( 0 ); begintime = time_current(); for( i = 0; i < num_threads; ++i ) { args[i].stream = stream; args[i].end_time = time_current() + ( time_ticks_per_second() * 5 ); args[i].max_delay = time_ticks_per_second() * 5; args[i].sleep_time = 50; args[i].id = i; read[i] = 0; thread[i] = thread_create( producer_thread, "event_producer", THREAD_PRIORITY_NORMAL, 0 ); thread_start( thread[i], &args[i] ); } test_wait_for_threads_startup( thread, num_threads ); while( running ) { running = false; for( i = 0; i < num_threads; ++i ) { if( thread_is_running( thread[i] ) ) { running = true; break; } } thread_yield(); prevtime = begintime; begintime = time_current(); block = event_stream_process( stream ); event = event_next( block, 0 ); curtime = time_current(); while( event ) { running = true; ++read[ event->object ]; memcpy( &payloadtime, event->payload, sizeof( tick_t ) ); EXPECT_GE( event_payload_size( event ), 8 ); EXPECT_LE( event_payload_size( event ), 256 ); EXPECT_GE( payloadtime, prevtime ); EXPECT_GE( curtime, payloadtime ); event = event_next( block, event ); curtime = time_current(); } } endtime = time_current() + ( time_ticks_per_second() * 6 ); do { prevtime = begintime; begintime = time_current(); block = event_stream_process( stream ); event = event_next( block, 0 ); curtime = time_current(); while( event ) { ++read[ event->object ]; memcpy( &payloadtime, event->payload, sizeof( tick_t ) ); EXPECT_GE( event_payload_size( event ), 8 ); EXPECT_LE( event_payload_size( event ), 256 ); EXPECT_GE( payloadtime, prevtime ); EXPECT_GE( curtime, payloadtime ); event = event_next( block, event ); curtime = time_current(); } thread_sleep( 10 ); } while( time_current() < endtime ); for( i = 0; i < num_threads; ++i ) { unsigned int should_have_read = (unsigned int)((uintptr_t)thread_result( thread[i] )); EXPECT_EQ( read[i], should_have_read ); thread_terminate( thread[i] ); thread_destroy( thread[i] ); } test_wait_for_threads_exit( thread, num_threads ); event_stream_deallocate( stream ); return 0; }
DECLARE_TEST( event, delay ) { event_stream_t* stream; event_block_t* block; event_t* event; tick_t delivery = 0; tick_t limit = 0; tick_t current = 0; uint8_t expect_event = FOUNDATIONEVENT_TERMINATE; stream = event_stream_allocate( 0 ); current = time_current(); delivery = current + ( time_ticks_per_second() / 2 ); limit = current + ( time_ticks_per_second() * 20 ); event_post( stream, expect_event, 0, 0, 0, current + ( time_ticks_per_second() / 2 ) ); event_post( stream, expect_event + 1, 0, 0, 0, current + (tick_t)((real)time_ticks_per_second() * REAL_C( 0.51 )) ); do { block = event_stream_process( stream ); event = event_next( block, 0 ); current = time_current(); if( ( expect_event == FOUNDATIONEVENT_TERMINATE ) && event ) { EXPECT_EQ( event->id, expect_event ); EXPECT_EQ( event->size, sizeof( event_t ) + 8 ); //8 bytes for additional timestamp payload EXPECT_EQ( event->object, 0 ); EXPECT_EQ( event->flags, EVENTFLAG_DELAY ); EXPECT_EQ( event_payload_size( event ), 0 ); EXPECT_GE( current, delivery ); EXPECT_GE( current, delivery ); ++expect_event; event = event_next( block, event ); } if( ( expect_event == FOUNDATIONEVENT_TERMINATE + 1 ) && event ) { EXPECT_EQ( event->id, expect_event ); EXPECT_EQ( event->size, sizeof( event_t ) + 8 ); //8 bytes for additional timestamp payload EXPECT_EQ( event->object, 0 ); EXPECT_EQ( event->flags, EVENTFLAG_DELAY ); EXPECT_EQ( event_payload_size( event ), 0 ); EXPECT_GE( current, delivery ); EXPECT_GE( current, delivery ); ++expect_event; event = event_next( block, event ); EXPECT_EQ( event, 0 ); } if( ( expect_event > FOUNDATIONEVENT_TERMINATE + 1 ) && !event ) break; thread_yield(); } while( time_current() < limit ); EXPECT_EQ( event, 0 ); EXPECT_EQ( expect_event, FOUNDATIONEVENT_TERMINATE + 2 ); EXPECT_LE( time_current(), limit ); //Reverse order of delivery current = time_current(); delivery = current + ( time_ticks_per_second() / 2 ); limit = current + ( time_ticks_per_second() * 20 ); event_post( stream, expect_event, 0, 0, 0, current + ( time_ticks_per_second() / 2 ) ); event_post( stream, expect_event + 1, 0, 0, 0, current + (tick_t)((real)time_ticks_per_second() * REAL_C( 0.41 )) ); do { block = event_stream_process( stream ); event = event_next( block, 0 ); current = time_current(); if( ( expect_event == FOUNDATIONEVENT_TERMINATE ) && event ) { EXPECT_EQ( event->id, expect_event ); EXPECT_EQ( event->size, sizeof( event_t ) + 8 ); //8 bytes for additional timestamp payload EXPECT_EQ( event->object, 0 ); EXPECT_EQ( event->flags, EVENTFLAG_DELAY ); EXPECT_EQ( event_payload_size( event ), 0 ); EXPECT_GE( current, delivery ); EXPECT_GE( current, delivery ); ++expect_event; event = event_next( block, event ); } if( ( expect_event == FOUNDATIONEVENT_TERMINATE + 1 ) && event ) { EXPECT_EQ( event->id, expect_event ); EXPECT_EQ( event->size, sizeof( event_t ) + 8 ); //8 bytes for additional timestamp payload EXPECT_EQ( event->object, 0 ); EXPECT_EQ( event->flags, EVENTFLAG_DELAY ); EXPECT_EQ( event_payload_size( event ), 0 ); EXPECT_GE( current, delivery ); EXPECT_GE( current, delivery ); ++expect_event; event = event_next( block, event ); EXPECT_EQ( event, 0 ); } if( ( expect_event > FOUNDATIONEVENT_TERMINATE + 1 ) && !event ) break; thread_yield(); } while( time_current() < limit ); EXPECT_EQ( event, 0 ); EXPECT_EQ( expect_event, FOUNDATIONEVENT_TERMINATE + 2 ); EXPECT_LE( time_current(), limit ); event_stream_deallocate( stream ); return 0; }
DECLARE_TEST( event, immediate ) { event_stream_t* stream; event_block_t* block; event_t* event; uint16_t last_serial = 0; uint8_t buffer[128] = {0}; stream = event_stream_allocate( 0 ); event_post( stream, FOUNDATIONEVENT_TERMINATE, 0, 0, 0, 0 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_NE( event, 0 ); EXPECT_EQ( event->id, FOUNDATIONEVENT_TERMINATE ); EXPECT_EQ( event->size, sizeof( event_t ) ); EXPECT_GT( event->serial, last_serial ); EXPECT_EQ( event->object, 0 ); EXPECT_EQ( event->flags, 0 ); EXPECT_EQ( event_payload_size( event ), 0 ); last_serial = event->serial; event = event_next( block, event ); EXPECT_EQ( event, 0 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_EQ( event, 0 ); event = event_next( block, event ); EXPECT_EQ( event, 0 ); event_post( stream, FOUNDATIONEVENT_TERMINATE, 13, 0, buffer, 0 ); event_post( stream, FOUNDATIONEVENT_TERMINATE + 1, 37, 0, buffer, 0 ); block = event_stream_process( stream ); event = event_next( block, 0 ); EXPECT_NE( event, 0 ); EXPECT_EQ( event->id, FOUNDATIONEVENT_TERMINATE ); EXPECT_EQ( event->size, sizeof( event_t ) + 16 ); EXPECT_GT( event->serial, last_serial ); EXPECT_EQ( event->object, 0 ); EXPECT_EQ( event->flags, 0 ); EXPECT_EQ( event_payload_size( event ), 16 ); last_serial = event->serial; event = event_next( block, event ); EXPECT_NE( event, 0 ); EXPECT_EQ( event->id, FOUNDATIONEVENT_TERMINATE + 1 ); EXPECT_EQ( event->size, sizeof( event_t ) + 40 ); EXPECT_GT( event->serial, last_serial ); EXPECT_EQ( event->object, 0 ); EXPECT_EQ( event->flags, 0 ); EXPECT_EQ( event_payload_size( event ), 40 ); last_serial = event->serial; event_stream_deallocate( stream ); return 0; }