Пример #1
0
DECLARE_TEST(objectmap, thread) {
	objectmap_t* map;
	thread_t thread[32];
	size_t ith;
	size_t num_threads = math_clamp(system_hardware_threads() * 4, 4, 32);

	map = objectmap_allocate((num_threads + 1) * 512);

	for (ith = 0; ith < num_threads; ++ith)
		thread_initialize(&thread[ith], objectmap_thread, map, STRING_CONST("objectmap_thread"),
		                  THREAD_PRIORITY_NORMAL, 0);
	for (ith = 0; ith < num_threads; ++ith)
		thread_start(&thread[ith]);

	test_wait_for_threads_startup(thread, num_threads);
	test_wait_for_threads_finish(thread, num_threads);

	for (ith = 0; ith < num_threads; ++ith)
		EXPECT_EQ(thread[ith].result, 0);

	for (ith = 0; ith < num_threads; ++ith)
		thread_finalize(&thread[ith]);

	objectmap_deallocate(map);

	return 0;
}
Пример #2
0
DECLARE_TEST( error, thread )
{
	//Launch 32 threads
	object_t thread[32];
	int i;

	for( i = 0; i < 32; ++i )
	{
		thread[i] = thread_create( error_thread, "error", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[i], 0 );
	}

	test_wait_for_threads_startup( thread, 32 );

	test_wait_for_threads_finish( thread, 32 );

	for( i = 0; i < 32; ++i )
	{
		EXPECT_EQ( thread_result( thread[i] ), 0 );
		thread_destroy( thread[i] );
	}

	test_wait_for_threads_exit( thread, 32 );

	return 0;
}
Пример #3
0
DECLARE_TEST(mutex, sync) {
	mutex_t* mutex;
	thread_t thread[32];
	size_t ith;

	mutex = mutex_allocate(STRING_CONST("test"));
	mutex_lock(mutex);

	for (ith = 0; ith < 32; ++ith)
		thread_initialize(&thread[ith], mutex_thread, mutex, STRING_CONST("mutex_thread"),
		                  THREAD_PRIORITY_NORMAL, 0);
	for (ith = 0; ith < 32; ++ith)
		thread_start(&thread[ith]);

	test_wait_for_threads_startup(thread, 32);

	mutex_unlock(mutex);

	test_wait_for_threads_finish(thread, 32);

	for (ith = 0; ith < 32; ++ith)
		thread_finalize(&thread[ith]);

	mutex_deallocate(mutex);

	EXPECT_EQ(thread_counter, 32 * 128);

	return 0;
}
Пример #4
0
DECLARE_TEST(atomic, cas) {
	size_t num_threads = math_clamp(system_hardware_threads() * 4, 4, 32);
	size_t ithread;
	thread_t threads[32];
	cas_value_t cas_values[32];

	for (ithread = 0; ithread < num_threads; ++ithread) {
		cas_values[ithread].val_32 = (int32_t)ithread;
		cas_values[ithread].val_64 = (int64_t)ithread;
		cas_values[ithread].val_ptr = (void*)(uintptr_t)ithread;
		thread_initialize(&threads[ithread], cas_thread, &cas_values[ithread],
		                  STRING_CONST("cas"), THREAD_PRIORITY_NORMAL, 0);
	}
	for (ithread = 0; ithread < num_threads; ++ithread)
		thread_start(&threads[ithread]);

	test_wait_for_threads_startup(threads, num_threads);
	test_wait_for_threads_finish(threads, num_threads);

	for (ithread = 0; ithread < num_threads; ++ithread)
		thread_finalize(&threads[ithread]);

	EXPECT_EQ(atomic_load32(&val_32), 0);
	EXPECT_EQ(atomic_load64(&val_64), 0);
	EXPECT_EQ(atomic_loadptr(&val_ptr), 0);

	return 0;
}
Пример #5
0
DECLARE_TEST( atomic, cas )
{
    int num_threads = 32;
    int ithread;
    object_t threads[32];
    cas_value_t cas_values[32];

    for( ithread = 0; ithread < num_threads; ++ithread )
    {
        threads[ithread] = thread_create( cas_thread, "cas", THREAD_PRIORITY_NORMAL, 0 );
        cas_values[ithread].val_32 = ithread;
        cas_values[ithread].val_64 = ithread;
        cas_values[ithread].val_ptr = (void*)(uintptr_t)ithread;
    }
    for( ithread = 0; ithread < num_threads; ++ithread )
        thread_start( threads[ithread], &cas_values[ithread] );

    test_wait_for_threads_startup( threads, num_threads );

    for( ithread = 0; ithread < num_threads; ++ithread )
        thread_destroy( threads[ithread] );

    test_wait_for_threads_exit( threads, num_threads );

    EXPECT_EQ( val_32, 0 );
    EXPECT_EQ( val_64, 0 );
    EXPECT_EQ( val_ptr, 0 );

    return 0;
}
Пример #6
0
DECLARE_TEST( mutex, sync )
{
	mutex_t* mutex;
	object_t thread[32];
	int ith;

	mutex = mutex_allocate( "test" );
	mutex_lock( mutex );

	for( ith = 0; ith < 32; ++ith )
	{
		thread[ith] = thread_create( mutex_thread, "mutex_thread", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], mutex );
	}

	test_wait_for_threads_startup( thread, 32 );

	for( ith = 0; ith < 32; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
	}

	mutex_unlock( mutex );

	test_wait_for_threads_exit( thread, 32 );

	mutex_deallocate( mutex );

	EXPECT_EQ( thread_counter, 32 * 128 );

	return 0;
}
Пример #7
0
DECLARE_TEST( profile, thread )
{
	object_t thread[32];
	int ith;
	int frame;
	error_t err = error();

	_test_profile_offset = 0;
	atomic_store32( &_test_profile_output_counter, 0 );

	profile_initialize( "test_profile", _test_profile_buffer, 30000/*_test_profile_buffer_size*/ );
	profile_enable( true );
	profile_set_output_wait( 1 );

	log_info( HASH_TEST, "This test will intentionally run out of memory in profiling system" );
	for( ith = 0; ith < 32; ++ith )
	{
		thread[ith] = thread_create( _profile_fail_thread, "profile_thread", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], 0 );
	}

	test_wait_for_threads_startup( thread, 32 );

	for( frame = 0; frame < 1000; ++frame )
	{
		thread_sleep( 16 );
		profile_end_frame( frame );
	}

	for( ith = 0; ith < 32; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
		thread_yield();
	}

	test_wait_for_threads_exit( thread, 32 );

	thread_sleep( 1000 );

	profile_enable( false );
	profile_shutdown();

	err = error();

#if BUILD_ENABLE_PROFILE
	EXPECT_GT( atomic_load32( &_test_profile_output_counter ), 0 );
	//TODO: Implement parsing output results
#else
	EXPECT_EQ( atomic_load32( &_test_profile_output_counter ), 0 );
#endif
	EXPECT_EQ( err, ERROR_NONE );

	return 0;
}
Пример #8
0
DECLARE_TEST(profile, thread) {
	thread_t thread[32];
	int ith;
	uint64_t frame;
	error_t err = error();

	_test_profile_offset = 0;
	atomic_store32(&_test_profile_output_counter, 0);

	profile_initialize(STRING_CONST("test_profile"), _test_profile_buffer, 30000);
	profile_enable(true);
	profile_set_output_wait(1);

	log_enable_stdout(false);
	for (ith = 0; ith < 32; ++ith)
		thread_initialize(&thread[ith], _profile_fail_thread, 0, STRING_CONST("profile_thread"),
		                  THREAD_PRIORITY_NORMAL, 0);
	for (ith = 0; ith < 32; ++ith)
		thread_start(&thread[ith]);

	test_wait_for_threads_startup(thread, 32);

	for (frame = 0; frame < 1000; ++frame) {
		thread_sleep(16);
		profile_end_frame(frame);
	}

	for (ith = 0; ith < 32; ++ith)
		thread_signal(&thread[ith]);

	test_wait_for_threads_finish(thread, 32);

	for (ith = 0; ith < 32; ++ith)
		thread_finalize(&thread[ith]);
	log_enable_stdout(true);

	err = error();
	thread_sleep(1000);

	profile_enable(false);
	profile_finalize();

#if BUILD_ENABLE_PROFILE
	EXPECT_INTGT(atomic_load32(&_test_profile_output_counter), 0);
	//TODO: Implement parsing output results
#else
	EXPECT_INTEQ(atomic_load32(&_test_profile_output_counter), 0);
#endif
	EXPECT_INTEQ(err, ERROR_NONE);

	return 0;
}
Пример #9
0
DECLARE_TEST( semaphore, threaded )
{
	object_t thread[32];
	int ith;
	int failed_waits;

	semaphore_test_t test;
	semaphore_initialize( &test.read, 0 );
	semaphore_initialize( &test.write, 0 );
	test.loopcount = 128;
	test.counter = 0;
	
	for( ith = 0; ith < 32; ++ith )
	{
		thread[ith] = thread_create( semaphore_waiter, "semaphore_waiter", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], &test );
	}

	test_wait_for_threads_startup( thread, 32 );

	failed_waits = 0;
	for( ith = 0; ith < test.loopcount * 32; ++ith )
	{
		semaphore_post( &test.read );
		thread_yield();
		if( !semaphore_try_wait( &test.write, 200 ) )
		{
			failed_waits++;
			EXPECT_TRUE( semaphore_wait( &test.write ) );
		}
	}

	for( ith = 0; ith < 32; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
		thread_yield();
	}

	test_wait_for_threads_exit( thread, 32 );

	EXPECT_EQ( test.counter, test.loopcount * 32 );
	EXPECT_EQ( failed_waits, 0 );

	semaphore_destroy( &test.read );
	semaphore_destroy( &test.write );
	
	return 0;
}
Пример #10
0
DECLARE_TEST( uuid, threaded )
{
	object_t thread[32];
	int ith, i, jth, j;
	int num_threads = math_clamp( system_hardware_threads() + 1, 3, 32 );

	for( ith = 0; ith < num_threads; ++ith )
	{
		thread[ith] = thread_create( uuid_thread_time, "uuid_thread", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], (void*)(uintptr_t)ith );
	}

	test_wait_for_threads_startup( thread, num_threads );
	
	for( ith = 0; ith < num_threads; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
	}

	test_wait_for_threads_exit( thread, num_threads );

	for( ith = 0; ith < num_threads; ++ith )
	{
		for( i = 0; i < 8192; ++i )
		{
			for( jth = ith + 1; jth < num_threads; ++jth )
			{
				for( j = 0; j < 8192; ++j )
				{
					EXPECT_FALSE( uuid_equal( uuid_thread_store[ith][i], uuid_thread_store[jth][j] ) );
				}
			}
			for( j = i + 1; j < 8192; ++j )
			{
				EXPECT_FALSE( uuid_equal( uuid_thread_store[ith][i], uuid_thread_store[ith][j] ) );
			}
		}
	}
	
	return 0;
}
Пример #11
0
DECLARE_TEST(error, thread) {
	//Launch 32 threads
	thread_t thread[32];
	int i;

	for (i = 0; i < 32; ++i)
		thread_initialize(&thread[i], error_thread, 0, STRING_CONST("error"), THREAD_PRIORITY_NORMAL, 0);
	for (i = 0; i < 32; ++i)
		thread_start(&thread[i]);

	test_wait_for_threads_startup(thread, 32);
	test_wait_for_threads_finish(thread, 32);

	for (i = 0; i < 32; ++i) {
		EXPECT_EQ(thread[i].result, 0);
		thread_finalize(&thread[i]);
	}

	return 0;
}
Пример #12
0
DECLARE_TEST( mutex, signal )
{
	mutex_t* mutex;
	object_t thread[32];
	int ith;

	mutex = mutex_allocate( "test" );
	mutex_lock( mutex );

	for( ith = 0; ith < 32; ++ith )
	{
		thread[ith] = thread_create( thread_wait, "thread_wait", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], mutex );
	}

	mutex_unlock( mutex );

	test_wait_for_threads_startup( thread, 32 );

	while( atomic_load32( &thread_waiting ) < 32 )
		thread_yield();
	thread_sleep( 1000 ); //Hack wait to give threads time to progress from atomic_incr to mutex_wait

	mutex_signal( mutex );

	for( ith = 0; ith < 32; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
	}

	test_wait_for_threads_exit( thread, 32 );

	EXPECT_EQ( atomic_load32( &thread_waited ), 32 );

	EXPECT_FALSE( mutex_wait( mutex, 500 ) );

	mutex_deallocate( mutex );

	return 0;
}
Пример #13
0
DECLARE_TEST(atomic, add) {
	size_t num_threads = math_clamp(system_hardware_threads() * 4, 4, 32);
	size_t ithread;
	thread_t threads[32];

	for (ithread = 0; ithread < num_threads; ++ithread)
		thread_initialize(&threads[ithread], add_thread, 0,
		                  STRING_CONST("add"), THREAD_PRIORITY_NORMAL, 0);
	for (ithread = 0; ithread < num_threads; ++ithread)
		thread_start(&threads[ithread]);

	test_wait_for_threads_startup(threads, num_threads);
	test_wait_for_threads_finish(threads, num_threads);

	for (ithread = 0; ithread < num_threads; ++ithread)
		thread_finalize(&threads[ithread]);

	EXPECT_EQ(atomic_load32(&val_32), 0);
	EXPECT_EQ(atomic_load64(&val_64), 0);

	return 0;
}
Пример #14
0
DECLARE_TEST( atomic, add )
{
    int num_threads = 32;
    int ithread;
    object_t threads[32];

    for( ithread = 0; ithread < num_threads; ++ithread )
        threads[ithread] = thread_create( add_thread, "add", THREAD_PRIORITY_NORMAL, 0 );
    for( ithread = 0; ithread < num_threads; ++ithread )
        thread_start( threads[ithread], 0 );

    test_wait_for_threads_startup( threads, num_threads );

    for( ithread = 0; ithread < num_threads; ++ithread )
        thread_destroy( threads[ithread] );

    test_wait_for_threads_exit( threads, num_threads );

    EXPECT_EQ( val_32, 0 );
    EXPECT_EQ( val_64, 0 );

    return 0;
}
Пример #15
0
DECLARE_TEST(mutex, signal) {
	mutex_t* mutex;
	thread_t thread[32];
	size_t ith;

	mutex = mutex_allocate(STRING_CONST("test"));
	mutex_lock(mutex);

	for (ith = 0; ith < 32; ++ith)
		thread_initialize(&thread[ith], thread_waiter, mutex, STRING_CONST("thread_wait"),
		                  THREAD_PRIORITY_NORMAL, 0);
	for (ith = 0; ith < 32; ++ith)
		thread_start(&thread[ith]);

	mutex_unlock(mutex);

	test_wait_for_threads_startup(thread, 32);

	while (atomic_load32(&thread_waiting) < 32)
		thread_yield();
	thread_sleep(1000);   //Hack wait to give threads time to progress from atomic_incr to mutex_wait

	mutex_signal(mutex);

	test_wait_for_threads_finish(thread, 32);

	for (ith = 0; ith < 32; ++ith)
		thread_finalize(&thread[ith]);

	EXPECT_EQ(atomic_load32(&thread_waited), 32);

	EXPECT_FALSE(mutex_try_wait(mutex, 500));

	mutex_deallocate(mutex);

	return 0;
}
Пример #16
0
DECLARE_TEST( profile, stream )
{
	object_t thread[32];
	int ith;
	int frame;
	char* filename;

	error();

	filename = path_merge( environment_temporary_directory(), "test.profile" );
	log_infof( HASH_TEST, "Output to profile file: %s", filename );
	fs_make_directory( environment_temporary_directory() );
	_profile_stream = fs_open_file( filename, STREAM_OUT | STREAM_BINARY );
	string_deallocate( filename );

	profile_initialize( "test_profile", _test_profile_buffer, _test_profile_buffer_size );
	profile_set_output( _profile_file_writer );
	profile_set_output_wait( 10 );
	profile_enable( true );

	for( ith = 0; ith < 32; ++ith )
	{
		thread[ith] = thread_create( _profile_stream_thread, "profile_thread", THREAD_PRIORITY_NORMAL, 0 );
		thread_start( thread[ith], 0 );
	}

	test_wait_for_threads_startup( thread, 32 );

	for( frame = 0; frame < 1000; ++frame )
	{
		thread_sleep( 16 );
		profile_log( "This is a really long profile log line that should break into multiple profile blocks automatically without causing any issues whatsoever if everything works as expected which it should or the code needs to be fixed" );
		profile_end_frame( frame++ );
		if( ( frame % 30 ) == 0 )
		{
			profile_enable( false );
			thread_sleep( 10 );
			profile_enable( true );
		}
	}

	for( ith = 0; ith < 32; ++ith )
	{
		thread_terminate( thread[ith] );
		thread_destroy( thread[ith] );
		thread_yield();
	}

	test_wait_for_threads_exit( thread, 32 );

	profile_end_frame( frame++ );
	profile_set_output_wait( 100 );

	thread_sleep( 1000 );

	profile_enable( false );
	profile_shutdown();

	error();

	stream_deallocate( _profile_stream );

	//TODO: Validate that output is sane
	log_debugf( HASH_TEST, "Generated %lld blocks", atomic_load64( &_profile_generated_blocks ) );

	return 0;
}
Пример #17
0
DECLARE_TEST(profile, stream) {
	thread_t thread[32];
	int ith;
	uint64_t frame;
	string_t filename;

	error(); //Clear error

	filename = path_allocate_concat(STRING_ARGS(environment_temporary_directory()),
	                                STRING_CONST("test.profile"));
	//log_infof(HASH_TEST, STRING_CONST("Output to profile file: %.*s"), STRING_FORMAT(filename));
	fs_make_directory(STRING_ARGS(environment_temporary_directory()));
	_profile_stream = fs_open_file(STRING_ARGS(filename), STREAM_OUT | STREAM_BINARY);
	string_deallocate(filename.str);

	profile_initialize(STRING_CONST("test_profile"), _test_profile_buffer, TEST_PROFILE_BUFFER_SIZE);
	profile_set_output(_profile_file_writer);
	profile_set_output_wait(10);
	profile_enable(true);

	for (ith = 0; ith < 32; ++ith)
		thread_initialize(&thread[ith], _profile_stream_thread, 0, STRING_CONST("profile_thread"),
		                  THREAD_PRIORITY_NORMAL, 0);
	for (ith = 0; ith < 32; ++ith)
		thread_start(&thread[ith]);

	test_wait_for_threads_startup(thread, 32);

	for (frame = 0; frame < 1000; ++frame) {
		thread_sleep(16);
		profile_log(
		    STRING_CONST("This is a really long profile log line that should break into multiple profile blocks automatically without causing any issues whatsoever if everything works as expected which it should or the code needs to be fixed"));
		profile_end_frame(frame++);
		if ((frame % 30) == 0) {
			profile_enable(false);
			thread_sleep(10);
			profile_enable(true);
		}
	}

	for (ith = 0; ith < 32; ++ith)
		thread_signal(&thread[ith]);

	test_wait_for_threads_finish(thread, 32);

	for (ith = 0; ith < 32; ++ith)
		thread_finalize(&thread[ith]);

	profile_end_frame(frame++);
	profile_set_output_wait(10000);

	thread_sleep(1000);

	profile_begin_block(STRING_CONST("Should be cleaned up"));
	profile_end_block();

	profile_enable(false);
	profile_finalize();

	error();

	stream_deallocate(_profile_stream);

//TODO: Validate that output is sane
	log_debugf(HASH_TEST, STRING_CONST("Generated %" PRId64 " blocks"),
	           atomic_load64(&_profile_generated_blocks));

	return 0;
}
Пример #18
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;
}
Пример #19
0
DECLARE_TEST(udp, datagram_ipv6) {
	network_address_t** address_local = 0;
	network_address_t* address = 0;
	network_address_t* address_server = 0;
	test_datagram_arg_t client_arg[4];

	int server_port;
	int state, iaddr, asize;
	thread_t threads[5];

	socket_t* sock_server;
	socket_t* sock_client[4];

	if (!network_supports_ipv6())
		return 0;

	sock_server = udp_socket_allocate();
	sock_client[0] = udp_socket_allocate();
	sock_client[1] = udp_socket_allocate();
	sock_client[2] = udp_socket_allocate();
	sock_client[3] = udp_socket_allocate();

	address_local = network_address_local();
	for (iaddr = 0, asize = array_size(address_local); iaddr < asize; ++iaddr) {
		if (network_address_family(address_local[iaddr]) == NETWORK_ADDRESSFAMILY_IPV6) {
			address = address_local[iaddr];
			break;
		}
	}
	EXPECT_NE(address, 0);

	do {
		server_port = random32_range(1024, 35535);
		network_address_ip_set_port(address, server_port);
		if (socket_bind(sock_server, address))
			break;
	}
	while (true);

	address_server = network_address_clone(address);
	network_address_ip_set_port(address_server, server_port);

	network_address_array_deallocate(address_local);

	state = socket_state(sock_server);
	EXPECT_TRUE(state == SOCKETSTATE_NOTCONNECTED);

	state = socket_state(sock_client[0]);
	EXPECT_TRUE(state == SOCKETSTATE_NOTCONNECTED);

	state = socket_state(sock_client[1]);
	EXPECT_TRUE(state == SOCKETSTATE_NOTCONNECTED);

	state = socket_state(sock_client[2]);
	EXPECT_TRUE(state == SOCKETSTATE_NOTCONNECTED);

	state = socket_state(sock_client[3]);
	EXPECT_TRUE(state == SOCKETSTATE_NOTCONNECTED);

	socket_set_blocking(sock_server, true);
	socket_set_blocking(sock_client[0], true);
	socket_set_blocking(sock_client[1], true);
	socket_set_blocking(sock_client[2], true);
	socket_set_blocking(sock_client[3], true);

	client_arg[0].sock = sock_client[0]; client_arg[0].target = address_server;
	client_arg[1].sock = sock_client[1]; client_arg[1].target = address_server;
	client_arg[2].sock = sock_client[2]; client_arg[2].target = address_server;
	client_arg[3].sock = sock_client[3]; client_arg[3].target = address_server;

	thread_initialize(&threads[0], datagram_server_blocking_thread, sock_server,
	                  STRING_CONST("server_thread"), THREAD_PRIORITY_NORMAL, 0);
	thread_initialize(&threads[1], datagram_client_blocking_thread, &client_arg[0],
	                  STRING_CONST("client_thread"), THREAD_PRIORITY_NORMAL, 0);
	thread_initialize(&threads[2], datagram_client_blocking_thread, &client_arg[1],
	                  STRING_CONST("client_thread"), THREAD_PRIORITY_NORMAL, 0);
	thread_initialize(&threads[3], datagram_client_blocking_thread, &client_arg[2],
	                  STRING_CONST("client_thread"), THREAD_PRIORITY_NORMAL, 0);
	thread_initialize(&threads[4], datagram_client_blocking_thread, &client_arg[3],
	                  STRING_CONST("client_thread"), THREAD_PRIORITY_NORMAL, 0);

	thread_start(&threads[0]);
	thread_start(&threads[1]);
	thread_start(&threads[2]);
	thread_start(&threads[3]);
	thread_start(&threads[4]);

	test_wait_for_threads_startup(threads, 5);

	thread_finalize(&threads[0]);
	thread_finalize(&threads[1]);
	thread_finalize(&threads[2]);
	thread_finalize(&threads[3]);
	thread_finalize(&threads[4]);

	socket_deallocate(sock_server);
	socket_deallocate(sock_client[0]);
	socket_deallocate(sock_client[1]);
	socket_deallocate(sock_client[2]);
	socket_deallocate(sock_client[3]);

	memory_deallocate(address_server);

	return 0;
}
Пример #20
0
DECLARE_TEST(udp, stream_ipv6) {
	network_address_t** address_local = 0;
	network_address_t* address = 0;

	int server_port, client_port;
	int state, iaddr, asize;
	thread_t threads[2];

	socket_t* sock_server;
	socket_t* sock_client;

	if (!network_supports_ipv6())
		return 0;

	sock_server = udp_socket_allocate();
	sock_client = udp_socket_allocate();

	address_local = network_address_local();
	for (iaddr = 0, asize = array_size(address_local); iaddr < asize; ++iaddr) {
		if (network_address_family(address_local[iaddr]) == NETWORK_ADDRESSFAMILY_IPV6) {
			address = address_local[iaddr];
			break;
		}
	}
	EXPECT_NE(address, 0);

	do {
		server_port = random32_range(1024, 35535);
		network_address_ip_set_port(address, server_port);
		if (socket_bind(sock_server, address))
			break;
	}
	while (true);

	do {
		client_port = random32_range(1024, 35535);
		network_address_ip_set_port(address, client_port);
		if (socket_bind(sock_client, address))
			break;
	}
	while (true);

	socket_set_blocking(sock_server, false);
	socket_set_blocking(sock_client, false);

	network_address_ip_set_port(address, client_port);
	socket_connect(sock_server, address, 0);

	network_address_ip_set_port(address, server_port);
	socket_connect(sock_client, address, 0);

	network_address_array_deallocate(address_local);

	state = socket_state(sock_server);
	EXPECT_TRUE(state == SOCKETSTATE_CONNECTED);

	state = socket_state(sock_client);
	EXPECT_TRUE(state == SOCKETSTATE_CONNECTED);

	socket_set_blocking(sock_server, true);
	socket_set_blocking(sock_client, true);

	thread_initialize(&threads[0], stream_blocking_thread, sock_server, STRING_CONST("io_thread"),
	                  THREAD_PRIORITY_NORMAL, 0);
	thread_initialize(&threads[1], stream_blocking_thread, sock_client, STRING_CONST("io_thread"),
	                  THREAD_PRIORITY_NORMAL, 0);

	thread_start(&threads[0]);
	thread_start(&threads[1]);

	test_wait_for_threads_startup(threads, 2);

	thread_finalize(&threads[0]);
	thread_finalize(&threads[1]);

	socket_deallocate(sock_server);
	socket_deallocate(sock_client);

	return 0;
}