diff options
| -rw-r--r-- | tests/ChangeLog | 5 | ||||
| -rw-r--r-- | tests/Makefile | 46 | ||||
| -rw-r--r-- | tests/count1.c | 42 | ||||
| -rw-r--r-- | tests/create1.c | 26 | ||||
| -rw-r--r-- | tests/exit2.c | 24 | ||||
| -rw-r--r-- | tests/exit3.c | 12 | ||||
| -rw-r--r-- | tests/eyal1.c | 182 | ||||
| -rw-r--r-- | tests/join1.c | 41 | ||||
| -rw-r--r-- | tests/mutex1.c | 25 | ||||
| -rw-r--r-- | tests/mutex2.c | 27 | ||||
| -rw-r--r-- | tests/mutex3.c | 42 | ||||
| -rw-r--r-- | tests/once1.c | 32 | ||||
| -rw-r--r-- | tests/self1.c | 23 | ||||
| -rw-r--r-- | tests/self2.c | 41 | ||||
| -rw-r--r-- | tests/self3.c | 32 | ||||
| -rw-r--r-- | tests/tsd1.c | 156 | 
16 files changed, 407 insertions, 349 deletions
| diff --git a/tests/ChangeLog b/tests/ChangeLog index 2d57206..ecbaa2a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,5 +1,10 @@  1999-02-23  Ross Johnson  <rpj@ise.canberra.edu.au> +	* Makefile: Some refinement. + +	* *.c: More exhaustive checking through assertions; clean up; +	add some more tests. +  	* Makefile: Now actually runs the tests.  	* tests.h: Define our own assert macro. The Mingw32 diff --git a/tests/Makefile b/tests/Makefile index 56968e5..4fef3c3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,52 +4,66 @@  CP	= copy  RM	= erase +MKDIR	= mkdir  TOUCH	= echo Passed > +ECHO	= @echo  #  # Mingw32  #  CC	= gcc  CFLAGS	= -g -O2 -UNDEBUG -Wall -o $@ $^ -BUILD_DIR	= ../build -RELEASE_DIR	= ../release -INCLUDES	= -I$(BUILD_DIR)/include -LIBS	= $(BUILD_DIR)/lib/libpthread32.a +BUILD_DIR	= ..\build +INCLUDES	= -I./include +LIBS	= ./lib/libpthread32.a  ##  ## MSVC  ##  #CC	= cl  #CFLAGS	= /W3 /MT /nologo /Yd /Zi /Fe$@ $^ -#BUILD_DIR	= ..\build -#RELEASE_DIR	= ..\release -#INCLUDES	= -I$(BUILD_DIR)\include -#LIBS	= $(BUILD_DIR)\lib\pthread.lib +#BUILD_DIR	= .. +#INCLUDES	= -I.\include +#LIBS	= .\lib\pthread.lib +HDR	= .\include\pthread.h +LIB	= .\lib\libpthread32.a  DLL	= pthread.dll  # If a test case returns a non-zero exit code to the shell, make will  # stop. -TESTS	= count1 create1 equal1 exit1 exit2 \ -	 exit3 eyal1 mutex1 mutex2 mutex3 \ -	 once1 self1 self2 self3 tsd1 +TESTS	= count1 create1 equal1 exit1 exit2 exit3 \ +	 join1 eyal1 mutex1 mutex2 mutex3 \ +	 once1 self1 self2 tsd1  PASSES	= $(TESTS:%=%.pass)  all:	$(PASSES) +	@ $(ECHO) ALL TESTS PASSED! Congratulations! -%.pass: %.exe $(DLL) +%.pass: %.exe $(LIB) $(DLL) $(HDR)  	$* -	$(TOUCH) $@ +	@$(ECHO) Passed +	@ $(TOUCH) $@  %.exe: %.c -	$(CC) $(CFLAGS) $(INCLUDES) $(LIBS) +	@ $(CC) $(CFLAGS) $(INCLUDES) $(LIBS) + +$(LIB): +	@- $(MKDIR) .\lib +	@ $(CP) $(BUILD_DIR)\$@ .\$@ + +$(HDR): +	@- $(MKDIR) .\include +	@ $(CP) $(BUILD_DIR)\$@ .\$@  $(DLL): -	$(CP) ..\build\bin\$@ . +	@ $(CP) $(BUILD_DIR)\$@ .\$@  clean: +	- $(RM) *.dll +	- $(RM) $(LIB) +	- $(RM) $(HDR)  	- $(RM) *.exe  	- $(RM) *.pass - diff --git a/tests/count1.c b/tests/count1.c index c4e0c4e..61e82e0 100644 --- a/tests/count1.c +++ b/tests/count1.c @@ -7,8 +7,7 @@   * Test some basic assertions about the number of threads at runtime.   */ -#include <windows.h> -#include <pthread.h> +#include "test.h"  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;  static pthread_t threads[10]; @@ -27,36 +26,37 @@ myfunc(void *arg)  int  main()  { -  int i, result; +  int i;    int maxThreads = sizeof(threads) / sizeof(pthread_t); -  /* Spawn ten threads. Each thread should increment the numThreads -     variable, sleep for one second, decrement the variable and then -     exit. The final result of numThreads should be 1 again. */ +  /* +   * Spawn ten threads. Each thread should increment the numThreads +   * variable, sleep for one second, decrement the variable and then +   * exit. The final result of numThreads should be 1 again. +   */    for (i = 0; i < maxThreads; i++)      { -      result = pthread_create(&threads[i], NULL, myfunc, 0); -      if (result != 0) -	{ -	  return 1; -	} +      assert(pthread_create(&threads[i], NULL, myfunc, 0) == 0);      } -  /* Wait for all the threads to exit. */ +  /* +   * Wait for all the threads to exit. +   */    for (i = 0; i < maxThreads; i++)      { -      pthread_join(threads[i], NULL); -      pthread_mutex_lock(&lock); +      assert(pthread_join(threads[i], NULL) == 0); +      assert(pthread_mutex_lock(&lock) == 0);        numThreads--; -      pthread_mutex_unlock(&lock); +      assert(pthread_mutex_unlock(&lock) == 0);      } -  /* Check the number of live threads. */ -  if (numThreads != 1) -    { -      return 1; -    } +  /*  +   * Check the number of live threads. +   */ +  assert(numThreads == 1); -  /* Success. */ +  /* +   * Success. +   */    return 0;  } diff --git a/tests/create1.c b/tests/create1.c index 2741401..192e52d 100644 --- a/tests/create1.c +++ b/tests/create1.c @@ -1,9 +1,19 @@ -#include <pthread.h> -#include <stdio.h> -#include <windows.h> +/* + * create1.c + * + * Description: + * Create a thread and check that it ran. + * + * Depends on API functions: None. + */ + +#include "test.h" + +static int washere = 0;  void * func(void * arg)  { +  washere = 1;    return 0;   } @@ -11,14 +21,14 @@ int  main()  {    pthread_t t; -  if (pthread_create(&t, NULL, func, NULL) != 0) -    { -      return 1; -    } + +  assert(pthread_create(&t, NULL, func, NULL) == 0);    /* A dirty hack, but we cannot rely on pthread_join in this       primitive test. */ -  Sleep(5000); +  Sleep(2000); + +  assert(washere == 1);    return 0;  } diff --git a/tests/exit2.c b/tests/exit2.c index 48ad5d0..786e4aa 100644 --- a/tests/exit2.c +++ b/tests/exit2.c @@ -1,12 +1,30 @@  /*   * Test for pthread_exit(). + * + * Depends on API functions: + *	pthread_create() + *	pthread_exit()   */ -#include <pthread.h> +#include "test.h" + +void * +func(void * arg) +{ +	pthread_exit(arg); + +	/* Never reached. */ +	exit(1); +}  int  main(int argc, char * argv[])  { -  /* Should be the same as return 0; */ -  pthread_exit(0); +  pthread_t t; + +  assert(pthread_create(&t, NULL, func, (void *) NULL) == 0); + +  Sleep(2000); + +  return 0;  } diff --git a/tests/exit3.c b/tests/exit3.c index f15b39d..b666624 100644 --- a/tests/exit3.c +++ b/tests/exit3.c @@ -4,8 +4,7 @@   * Depends on API functions: pthread_create().   */ -#include <pthread.h> -#include <stdio.h> +#include "test.h"  void *  func(void * arg) @@ -13,7 +12,7 @@ func(void * arg)  	pthread_exit(arg);  	/* Never reached. */ -	return 0; +	exit(1);  }  int @@ -25,11 +24,8 @@ main(int argc, char * argv[])  	/* Create a few threads and then exit. */  	for (i = 0; i < 4; i++)  	  { -	  if (pthread_create(&id[i], NULL, func, (void *) i) != 0) -	    { -	      return 1; -	    } -	} +	    assert(pthread_create(&id[i], NULL, func, (void *) i) == 0); +	  }  	/* Success. */  	return 0; diff --git a/tests/eyal1.c b/tests/eyal1.c index f51bc9c..4345452 100644 --- a/tests/eyal1.c +++ b/tests/eyal1.c @@ -43,13 +43,11 @@   * the threads knows its 'id' and also filles in the 'work' done).  */ -#include <stdio.h> +#include "test.h" +  #include <stdlib.h>  #include <math.h> -#include <pthread.h> - -  struct thread_control {  	int		id;  	pthread_t	thread;		/* thread id */ @@ -63,8 +61,8 @@ struct thread_control {  typedef struct thread_control	TC;  static TC		*tcs = NULL; -static int		nthreads = 2; -static int		nwork = 0; +static int		nthreads = 7; +static int		nwork = 50;  static int		quiet = 0;  static int		todo = -1; @@ -112,8 +110,7 @@ do_work_unit (int who, int n)  	else {  /* get lock on stdout  */ -		if (pthread_mutex_lock (&mutex_stdout)) -			return (-1); +		assert(pthread_mutex_lock (&mutex_stdout) == 0);  /* do our job  */ @@ -125,8 +122,7 @@ do_work_unit (int who, int n)  /* release lock on stdout  */ -		if (pthread_mutex_unlock (&mutex_stdout)) -			return (-2); +		assert(pthread_mutex_unlock (&mutex_stdout) == 0);  	}  	n = rand () % 10000;	/* ignore incoming 'n' */ @@ -142,25 +138,19 @@ print_server (void *ptr)  	int		n;  	TC		*tc = (TC *)ptr; -	if (pthread_mutex_lock (&tc->mutex_started)) -		return (-1); +	assert(pthread_mutex_lock (&tc->mutex_started) == 0);  	for (;;) { -		if (pthread_mutex_lock (&tc->mutex_start)) -			return (-2); -		if (pthread_mutex_unlock (&tc->mutex_start)) -			return (-3); -		if (pthread_mutex_lock (&tc->mutex_ended)) -			return (-4); -		if (pthread_mutex_unlock (&tc->mutex_started)) -			return (-5); +		assert(pthread_mutex_lock (&tc->mutex_start) == 0); +		assert(pthread_mutex_unlock (&tc->mutex_start) == 0); +		assert(pthread_mutex_lock (&tc->mutex_ended) == 0); +		assert(pthread_mutex_unlock (&tc->mutex_started) == 0);  		for (;;) {  /* get lock on todo list  */ -			if (pthread_mutex_lock (&mutex_todo)) -				return (-6); +			assert(pthread_mutex_lock (&mutex_todo) == 0);  			mywork = todo;  			if (todo >= 0) { @@ -168,140 +158,102 @@ print_server (void *ptr)  				if (todo >= nwork)  					todo = -1;  			} -			if (pthread_mutex_unlock (&mutex_todo)) -				return (-7); +			assert(pthread_mutex_unlock (&mutex_todo) == 0);  			if (mywork < 0)  				break; -			if ((n = do_work_unit (tc->id, mywork)) < 0) -				return (-8); +			assert((n = do_work_unit (tc->id, mywork)) >= 0);  			tc->work += n;  		} -		if (pthread_mutex_lock (&tc->mutex_end)) -			return (-9); -		if (pthread_mutex_unlock (&tc->mutex_end)) -			return (-10); -		if (pthread_mutex_lock (&tc->mutex_started)) -			return (-11); -		if (pthread_mutex_unlock (&tc->mutex_ended)) -			return (-12); +		assert(pthread_mutex_lock (&tc->mutex_end) == 0); +		assert(pthread_mutex_unlock (&tc->mutex_end) == 0); +		assert(pthread_mutex_lock (&tc->mutex_started) == 0); +		assert(pthread_mutex_unlock (&tc->mutex_ended) == 0);  		if (-2 == mywork)  			break;  	} -	if (pthread_mutex_unlock (&tc->mutex_started)) -		return (-13); +	assert(pthread_mutex_unlock (&tc->mutex_started) == 0);  	return (0);  } -static int +static void  dosync (void)  {  	int		i;  	for (i = 0; i < nthreads; ++i) { -		if (pthread_mutex_lock (&tcs[i].mutex_end)) -			return (-1); -		if (pthread_mutex_unlock (&tcs[i].mutex_start)) -			return (-2); -		if (pthread_mutex_lock (&tcs[i].mutex_started)) -			return (-3); -		if (pthread_mutex_unlock (&tcs[i].mutex_started)) -			return (-4); +		assert(pthread_mutex_lock (&tcs[i].mutex_end) == 0); +		assert(pthread_mutex_unlock (&tcs[i].mutex_start) == 0); +		assert(pthread_mutex_lock (&tcs[i].mutex_started) == 0); +		assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0);  	}  /* Now threads do their work  */  	for (i = 0; i < nthreads; ++i) { -		if (pthread_mutex_lock (&tcs[i].mutex_start)) -			return (-5); -		if (pthread_mutex_unlock (&tcs[i].mutex_end)) -			return (-6); -		if (pthread_mutex_lock (&tcs[i].mutex_ended)) -			return (-7); -		if (pthread_mutex_unlock (&tcs[i].mutex_ended)) -			return (-8); +		assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0); +		assert(pthread_mutex_unlock (&tcs[i].mutex_end) == 0); +		assert(pthread_mutex_lock (&tcs[i].mutex_ended) == 0); +		assert(pthread_mutex_unlock (&tcs[i].mutex_ended) == 0);  	} - -	return (0);  } -static int +static void  dowork (void)  {  	todo = 0; -	if (dosync () < 0) -		return (-1); +	dosync();  	todo = 0; -	if (dosync () < 0) -		return (-2); - -	return (0); +	dosync();  }  int  main (int argc, char *argv[])  {  	int		i; -	int		nargs; - -	nthreads  = 1; -	nwork = 100; -	nargs = 0; -	for (i = 1; i < argc; ++i) { -		if (!strcmp ("-q", argv[i])) { -			quiet = 1; -			continue; -		} -		if (!strcmp ("-h", argv[i])) { -			printf ("usage: pthreads [nthreads] [nwork] [-q]\n"); -			exit (0); -		} -		switch (++nargs) { -		case 1: -			nthreads  = atoi (argv[i]); -			if (nthreads > 36) { -				printf ("max 36 threads allowed\n"); -				die (1); -			} -			break; -		case 2: -			nwork = atoi (argv[i]); -			break; -		default: -			printf ("bad argument '%s'\n", argv[i]); -			die (1); -			break; -		} -	} -	if (NULL == (tcs = calloc (nthreads, sizeof (*tcs)))) -		die (1); +	assert(NULL != (tcs = calloc (nthreads, sizeof (*tcs))));  /* Launch threads  */  	for (i = 0; i < nthreads; ++i) {  		tcs[i].id = i; -		pthread_mutex_init (&tcs[i].mutex_start, NULL); -		pthread_mutex_init (&tcs[i].mutex_started, NULL); -		pthread_mutex_init (&tcs[i].mutex_end, NULL); -		pthread_mutex_init (&tcs[i].mutex_ended, NULL); + +		assert(pthread_mutex_init (&tcs[i].mutex_start, NULL) == 0); +		assert(pthread_mutex_init (&tcs[i].mutex_started, NULL) == 0); +		assert(pthread_mutex_init (&tcs[i].mutex_end, NULL) == 0); +		assert(pthread_mutex_init (&tcs[i].mutex_ended, NULL) == 0); +  		tcs[i].work = 0; -		if (pthread_mutex_lock (&tcs[i].mutex_start)) -			{} -		tcs[i].stat = pthread_create (&tcs[i].thread, -			NULL /*&pthread_attr_default*/, -			(void*)&print_server, (void *)&tcs[i]); + +		assert(pthread_mutex_lock (&tcs[i].mutex_start) == 0); +		assert((tcs[i].stat =  +                    pthread_create (&tcs[i].thread, +			                  NULL, +			                  (void*)&print_server, (void *)&tcs[i]) +                    ) == 0);  /* Wait for thread initialisation  */ -		while (!pthread_mutex_trylock (&tcs[i].mutex_started)) -			pthread_mutex_unlock (&tcs[i].mutex_started); +		while (1) +              { +                int trylock; + +                trylock = pthread_mutex_trylock(&tcs[i].mutex_started); +                assert(trylock == 0 || trylock == EBUSY); + +                if (trylock == 0) +                  { +			  assert(pthread_mutex_unlock (&tcs[i].mutex_started) == 0); +                    break; +                  } +               }  	}  	dowork (); @@ -309,18 +261,17 @@ main (int argc, char *argv[])  /* Terminate threads  */  	todo = -2;	/* please terminate */ -	if (dosync () < 0) -		die (2); +	dosync();  	for (i = 0; i < nthreads; ++i) {  		if (0 == tcs[i].stat) -			pthread_join (tcs[i].thread, NULL); +			assert(pthread_join (tcs[i].thread, NULL) == 0);  	}  /* destroy locks  */ -	pthread_mutex_destroy (&mutex_stdout); -	pthread_mutex_destroy (&mutex_todo); +	assert(pthread_mutex_destroy (&mutex_stdout) == 0); +	assert(pthread_mutex_destroy (&mutex_todo) == 0);  /* Cleanup  */ @@ -334,10 +285,11 @@ main (int argc, char *argv[])  			printf ("%10ld\n", tcs[i].work);  		else  			printf ("failed %d\n", tcs[i].stat); -		pthread_mutex_destroy (&tcs[i].mutex_start); -		pthread_mutex_destroy (&tcs[i].mutex_started); -		pthread_mutex_destroy (&tcs[i].mutex_end); -		pthread_mutex_destroy (&tcs[i].mutex_ended); + +		assert(pthread_mutex_destroy (&tcs[i].mutex_start) == 0); +		assert(pthread_mutex_destroy (&tcs[i].mutex_started) == 0); +		assert(pthread_mutex_destroy (&tcs[i].mutex_end) == 0); +		assert(pthread_mutex_destroy (&tcs[i].mutex_ended) == 0);  	}  	die (0); diff --git a/tests/join1.c b/tests/join1.c new file mode 100644 index 0000000..f6240de --- /dev/null +++ b/tests/join1.c @@ -0,0 +1,41 @@ +/* + * Test for pthread_join(). + * + * Depends on API functions: pthread_create(), pthread_exit(). + */ + +#include "test.h" + +void * +func(void * arg) +{ +	Sleep(1000); + +	pthread_exit(arg); + +	/* Never reached. */ +	exit(1); +} + +int +main(int argc, char * argv[]) +{ +	pthread_t id[4]; +	int i; +	int result; + +	/* Create a few threads and then exit. */ +	for (i = 0; i < 4; i++) +	  { +	    assert(pthread_create(&id[i], NULL, func, (void *) i) == 0); +	  } + +	for (i = 0; i < 4; i++) +	  { +	    assert(pthread_join(id[i], (void *) &result) == 0); +	    assert(result == i); +	  } + +	/* Success. */ +	return 0; +} diff --git a/tests/mutex1.c b/tests/mutex1.c index f1c9240..60bb4e7 100644 --- a/tests/mutex1.c +++ b/tests/mutex1.c @@ -3,29 +3,28 @@   *   * Create a simple mutex object, lock it, and then unlock it again.   * This is the simplest test of the pthread mutex family that we can do. + * + * Depends on API functions: + * 	pthread_mutex_init() + *	pthread_mutex_lock() + *	pthread_mutex_unlock() + *	pthread_mutex_destroy()   */ -#include <pthread.h> +#include "test.h"  pthread_mutex_t mutex1;  int  main()  { -  if (pthread_mutex_init(&mutex1, NULL) != 0) -    { -      return 1; -    } +  assert(pthread_mutex_init(&mutex1, NULL) == 0); + +  assert(pthread_mutex_lock(&mutex1) == 0); -  if (pthread_mutex_lock(&mutex1) != 0) -    { -      return 1; -    } +  assert(pthread_mutex_unlock(&mutex1) == 0); -  if (pthread_mutex_unlock(&mutex1) != 0) -    { -      return 1; -    } +  assert(pthread_mutex_destroy(&mutex1) == 0);    return 0;  } diff --git a/tests/mutex2.c b/tests/mutex2.c index cfbebdc..7956f14 100644 --- a/tests/mutex2.c +++ b/tests/mutex2.c @@ -1,29 +1,24 @@  /*  - * mutex1.c + * mutex2.c   * - * Declare a static mutex object, lock it, and then unlock it again. + * Declare a static mutex object, lock it,  + * and then unlock it again. + * + * Depends on API functions:  + *	pthread_mutex_lock() + *	pthread_mutex_unlock()   */ -#include <pthread.h>  #include "test.h" -pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +int  main()  { -  int result; - -  result = pthread_mutex_trylock(&mutex1); -  printf("pthread_mutex_trylock returned %s\n", error_string[result]); -  if (result != 0) -    { -      return 1; -    } +  assert(pthread_mutex_lock(&mutex) == 0); -  if (pthread_mutex_unlock(&mutex1) != 0) -    { -      return 1; -    } +  assert(pthread_mutex_unlock(&mutex) == 0);    return 0;  } diff --git a/tests/mutex3.c b/tests/mutex3.c index 2bb6106..26cb070 100644 --- a/tests/mutex3.c +++ b/tests/mutex3.c @@ -1,12 +1,44 @@ -#include <pthread.h> +/*  + * mutex3.c + * + * Declare a static mutex object, lock it, trylock it,  + * and then unlock it again. + * + * Depends on API functions:  + *	pthread_mutex_lock() + *	pthread_mutex_trylock() + *	pthread_mutex_unlock() + */ -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +#include "test.h" +  +pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; +static int washere = 0; + +void * func(void * arg) +{ +  assert(pthread_mutex_trylock(&mutex1) == EBUSY); + +  washere = 1; + +  return 0;  +} +   int  main()  { -  pthread_mutex_lock(&mutex); -  /* do stuff */ -  pthread_mutex_unlock(&mutex); +  pthread_t t; + +  assert(pthread_mutex_lock(&mutex1) == 0); + +  assert(pthread_create(&t, NULL, func, NULL) == 0); + +  Sleep(2000); + +  assert(pthread_mutex_unlock(&mutex1) == 0); + +  assert(washere == 1); +    return 0;  } diff --git a/tests/once1.c b/tests/once1.c index 661d322..91dc038 100644 --- a/tests/once1.c +++ b/tests/once1.c @@ -1,25 +1,29 @@  /* - * Test for pthread_once(). + * once1.c   * - * Depends on functions: pthread_create. + * Create a static pthread_once and test that it calls myfunc once. + * + * Depends on API functions: + *	pthread_once() + *	pthread_create()   */ -#include <pthread.h> -#include <stdio.h> +#include "test.h"  pthread_once_t once = PTHREAD_ONCE_INIT; +static int washere = 0; +  void  myfunc(void)  { -	printf("only see this once\n"); +  washere++;  }  void *  mythread(void * arg)  { -   int rc = pthread_once(&once, myfunc); -   printf("returned %d\n", rc);  +   assert(pthread_once(&once, myfunc) == 0);     return 0;  } @@ -27,19 +31,15 @@ mythread(void * arg)  int  main()  { -  int rc;    pthread_t t1, t2; -  if (pthread_create(&t1, NULL, mythread, NULL) != 0) -    { -      return 1; -    } +  assert(pthread_create(&t1, NULL, mythread, NULL) == 0); -  if (pthread_create(&t2, NULL, mythread, NULL) != 0) -    { -      return 1; -    } +  assert(pthread_create(&t2, NULL, mythread, NULL) == 0);    Sleep(2000); + +  assert(washere == 1); +    return 0;  } diff --git a/tests/self1.c b/tests/self1.c index 0addfc8..d460818 100644 --- a/tests/self1.c +++ b/tests/self1.c @@ -1,21 +1,26 @@  /* + * self1.c + *   * Test for pthread_self().   * - * Depends on API functions: None. + * Depends on API functions: + *	pthread_self() + * + * Implicitly depends on: + *	pthread_getspecific() + *	pthread_setspecific()   */ -#include <pthread.h> +#include "test.h"  int  main(int argc, char * argv[])  { -	pthread_t id; - -	/* We can't do anything with this, though, because it is not -	   safe to assume anything about the internal structure of -	   a `pthread_t'. */ - -	id = pthread_self(); +	/* +	 * This should always succeed unless the system has no +	 * resources (memory) left. +	 */ +	assert(pthread_self() != NULL);  	return 0;  } diff --git a/tests/self2.c b/tests/self2.c index 461e5f9..83339f1 100644 --- a/tests/self2.c +++ b/tests/self2.c @@ -1,33 +1,46 @@ -#include <pthread.h> -#include <assert.h> -#include <stdio.h> +/* + * self2.c + * + * Test for pthread_self(). + * + * Depends on API functions: + *	pthread_create() + *	pthread_self() + * + * Implicitly depends on: + *	pthread_getspecific() + *	pthread_setspecific() + */ + +#include "test.h" +#include <string.h> + +static pthread_t me;  void *  entry(void * arg)  { -  /* Like systems such as HP-UX, we can't print the value of the thread ID -     because it's not an integral type. Instead, we'll poke our noses into -     the pthread_t structure and dump a useful internal value. This is -     ordinarily bad, m'kay? */ +  me = pthread_self(); -  pthread_t t = pthread_self(); -  printf("my thread is %lx\n", t->threadH);     return arg;  }  int  main()  { -  int rc;    pthread_t t; -  if (pthread_create(&t, NULL, entry, NULL) != 0) -    { -      return 1; -    } +  assert(pthread_create(&t, NULL, entry, NULL) == 0);    Sleep(2000); +  /* +   * Not much more we can do here but bytewise compare t with +   * what pthread_self returned. +   */ +  assert(t == me); +  assert(memcmp((const void *) t, (const void *) me, sizeof t) == 0); +    /* Success. */    return 0;  } diff --git a/tests/self3.c b/tests/self3.c deleted file mode 100644 index dc220b7..0000000 --- a/tests/self3.c +++ /dev/null @@ -1,32 +0,0 @@ -#include <pthread.h> -#include <assert.h> -#include <stdio.h> - -void * -entry(void * arg) -{ -  /* Like systems such as HP-UX, we can't print the value of the thread ID -     because it's not an integral type. Instead, we'll poke our noses into -     the pthread_t structure and dump a useful internal value. This is -     ordinarily bad, m'kay? */ - -  pthread_t t = pthread_self(); -  printf("thread no. %d has id %lx\n", (int) arg, t->threadH);  -  return 0;  -} - -int -main() -{ -  int rc; -  pthread_t t[2]; - -  rc = pthread_create(&t[0], NULL, entry, (void *) 1); -  assert(rc == 0); - -  rc = pthread_create(&t[1], NULL, entry, (void *) 2); -  assert(rc == 0); - -  Sleep(2000); -  return 0; -} diff --git a/tests/tsd1.c b/tests/tsd1.c index 8137a64..93403b1 100644 --- a/tests/tsd1.c +++ b/tests/tsd1.c @@ -1,8 +1,7 @@  /* - * File: tsd1.c + * tsd1.c   * - * Test Synopsis: - * - Thread Specific Data (TSD) key creation and destruction. + * Test Thread Specific Data (TSD) key creation and destruction.   *   * Description:   * -  @@ -44,74 +43,53 @@   * - output identifies failed component   */ -#include <pthread.h> -#include <stdio.h> +#include "test.h" -pthread_key_t key = NULL; -pthread_once_t key_once = PTHREAD_ONCE_INIT; +static pthread_key_t key = NULL; +static int accesscount[10]; +static int thread_set[10]; +static int thread_destroyed[10]; -void +static void  destroy_key(void * arg)  { -  /* arg is not NULL if we get to here. */ -  printf("SUCCESS: %s: destroying key.\n", (char *) arg); +  int * j = (int *) arg; -  free((char *) arg); -} +  (*j)++; -void -make_key(void) -{ -  if (pthread_key_create(&key, destroy_key) != 0) -    { -      printf("Key create failed\n"); -      exit(1); -    } +  assert(*j == 2); + +  thread_destroyed[j - accesscount] = 1;  } -void +static void  setkey(void * arg)  { -  void * ptr; +  int * j = (int *) arg; -  if ((ptr = pthread_getspecific(key)) != NULL) -    { -      printf("ERROR: Thread %d, Key not initialised to NULL\n", -	     (int) arg); -      exit(1); -    } -  else -    { -      ptr = (void *) malloc(80); -      sprintf((char *) ptr, "Thread %d Key", -	      (int) arg); -      (void) pthread_setspecific(key, ptr); -    } +  thread_set[j - accesscount] = 1; -  if ((ptr = pthread_getspecific(key)) == NULL) -    { -      printf("FAILED: Thread %d Key value set or get failed.\n", -	     (int) arg); -      exit(1); -    } -  else -    { -      printf("SUCCESS: Thread %d Key value set and get succeeded.\n", -	     (int) arg); +  assert(*j == 0); -      printf("SUCCESS: %s: exiting thread.\n", (char *) ptr); -    } +  assert(pthread_getspecific(key) == NULL); + +  assert(pthread_setspecific(key, arg) == 0); + +  assert(pthread_getspecific(key) == arg); + +  (*j)++; + +  assert(*j == 1);  } -void * +static void *  mythread(void * arg)  {    while (key == NULL)      { +	Sleep(0);      } -  printf("Thread %d, Key created\n", (int) arg); -    setkey(arg);    return 0; @@ -122,38 +100,70 @@ mythread(void * arg)  int  main()  { -  int rc; -  int t; +  int i; +  int fail = 0;    pthread_t thread[10]; -  for (t = 0; t < 5; t++) +  for (i = 1; i < 5; i++) +    { +	accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; +      assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0); +    } + +  Sleep(2000); + +  /* +   * Here we test that existing threads will get a key created +   * for them. +   */ +  assert(pthread_key_create(&key, destroy_key) == 0); + +  /* +   * Test main thread key. +   */ +  accesscount[0] = 0; +  setkey((void *) &accesscount[0]); + +  /* +   * Here we test that new threads will get a key created +   * for them. +   */ +  for (i = 5; i < 10; i++)      { -      rc = pthread_create(&thread[t], NULL, mythread, (void *) (t + 1)); -      printf("pthread_create returned %d\n", rc); -      if (rc != 0) -	{ -	  return 1; -	} +	accesscount[i] = thread_set[i] = thread_destroyed[i] = 0; +      assert(pthread_create(&thread[i], NULL, mythread, (void *)&accesscount[i]) == 0);      } -  (void) pthread_once(&key_once, make_key); +  /* +   * Wait for all threads to complete. +   */ +  for (i = 1; i < 10; i++) +    { +	int result = 0; -  /* Test main thread key. */ -  setkey((void *) 0); +	assert(pthread_join(thread[i], (void *) &result) == 0); +    } -  Sleep(500); +  assert(pthread_key_delete(key) == 0); -  for (t = 5; t < 10; t++) +  for (i = 0; i < 10; i++)      { -      rc = pthread_create(&thread[t], NULL, mythread, (void *) (t + 1)); -      printf("pthread_create returned %d\n", rc); -      if (rc != 0) -	{ -	  return 1; -	} +	/* +	 * The counter is incremented once when the key is set to +	 * a value, and again when the key is destroyed. If the key +	 * doesn't get set for some reason then it will still be +	 * NULL and the destroy function will not be called, and +	 * hence accesscount will not equal 2. +	 */ +	if (accesscount[i] != 2) +	  { +	    fail++; +	    fprintf(stderr, "Thread %d key, set = %d, destroyed = %d\n", +			i, thread_set[i], thread_destroyed[i]); +	  }      } -  Sleep(2000); -  return 0; -} +  fflush(stderr); +  return (fail) ? 1 : 0; +} | 
