/ tests / netbsd_getenv_thread.c
netbsd_getenv_thread.c
  1  /*	$NetBSD: t_getenv_thread.c,v 1.2 2012/03/15 02:02:23 joerg Exp $ */
  2  
  3  /*-
  4   * Copyright (c) 2010 The NetBSD Foundation, Inc.
  5   * All rights reserved.
  6   *
  7   * This code is derived from software contributed to The NetBSD Foundation
  8   * by Matthias Scheler.
  9   *
 10   * Redistribution and use in source and binary forms, with or without
 11   * modification, are permitted provided that the following conditions
 12   * are met:
 13   * 1. Redistributions of source code must retain the above copyright
 14   *    notice, this list of conditions and the following disclaimer.
 15   * 2. Redistributions in binary form must reproduce the above copyright
 16   *    notice, this list of conditions and the following disclaimer in the
 17   *    documentation and/or other materials provided with the distribution.
 18   *
 19   * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 20   * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 21   * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 22   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 23   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 24   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 25   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 26   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 27   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 28   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 29   * POSSIBILITY OF SUCH DAMAGE.
 30   */
 31  #include <sys/cdefs.h>
 32  __RCSID("$NetBSD: t_getenv_thread.c,v 1.2 2012/03/15 02:02:23 joerg Exp $");
 33  
 34  #include <darwintest.h>
 35  
 36  #include <errno.h>
 37  #include <pthread.h>
 38  #include <stdio.h>
 39  #include <stdlib.h>
 40  #include <string.h>
 41  #include <time.h>
 42  
 43  #define	THREADED_NUM_THREADS	8
 44  #define	THREADED_NUM_VARS	16
 45  #define	THREADED_VAR_NAME	"THREADED%zu"
 46  #define	THREADED_RUN_TIME	10
 47  
 48  static void	 *thread_putenv(void *);
 49  static void	 *thread_setenv(void *);
 50  static void	 *thread_unsetenv(void *);
 51  
 52  static void *
 53  thread_putenv(void *arg)
 54  {
 55  	time_t endtime;
 56  	size_t i;
 57  	static char vars[THREADED_NUM_VARS][128];
 58  
 59  	for (i = 0; i < THREADED_NUM_VARS; i++) {
 60  		(void)snprintf(vars[i], sizeof(vars[i]),
 61  		    THREADED_VAR_NAME "=putenv %ld", i, lrand48());
 62  	}
 63  
 64  	endtime = *(time_t *)arg;
 65  	do {
 66  		char name[128];
 67  
 68  		i = lrand48() % THREADED_NUM_VARS;
 69  		(void)strlcpy(name, vars[i], sizeof(name));
 70  		*strchr(name, '=') = '\0';
 71  
 72  		T_QUIET; T_ASSERT_POSIX_ZERO(unsetenv(name), NULL);
 73  		T_QUIET; T_ASSERT_POSIX_ZERO(putenv(vars[i]), NULL);
 74  	} while (time(NULL) < endtime);
 75  
 76  	return NULL;
 77  }
 78  
 79  static void *
 80  thread_setenv(void *arg)
 81  {
 82  	time_t endtime;
 83  
 84  	endtime = *(time_t *)arg;
 85  	do {
 86  		size_t i;
 87  		char name[32], value[64];
 88  
 89  		i = lrand48() % THREADED_NUM_VARS;
 90  		(void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i);
 91  		(void)snprintf(value, sizeof(value), "setenv %ld", lrand48());
 92  
 93  		T_QUIET; T_ASSERT_POSIX_ZERO(setenv(name, value, 1), NULL);
 94  	} while (time(NULL) < endtime);
 95  
 96  	return NULL;
 97  }
 98  
 99  static void *
100  thread_unsetenv(void *arg)
101  {
102  	time_t endtime;
103  
104  	endtime = *(time_t *)arg;
105  	do {
106  		size_t i;
107  		char name[32];
108  
109  		i = lrand48() % THREADED_NUM_VARS;
110  		(void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i);
111  
112  		T_QUIET; T_ASSERT_POSIX_ZERO(unsetenv(name), NULL);
113  	} while (time(NULL) < endtime);
114  
115  	return NULL;
116  }
117  
118  T_DECL(putenv_thread, "Test concurrent access by putenv(3)")
119  {
120  	pthread_t threads[THREADED_NUM_THREADS];
121  	time_t endtime = time(NULL) + THREADED_RUN_TIME;
122  
123  	for (int i = 0; i < THREADED_NUM_THREADS; i++) {
124  		T_QUIET; T_ASSERT_POSIX_ZERO(
125  				pthread_create(&threads[i], NULL, thread_putenv, &endtime),
126  				NULL);
127  	}
128  	for (int i = 0; i < THREADED_NUM_THREADS; i++) {
129  		T_QUIET; T_ASSERT_POSIX_ZERO(pthread_join(threads[i], NULL), NULL);
130  	}
131  	T_PASS("putenv_thread() completed successfully");
132  }
133  
134  T_DECL(setenv_thread, "Test concurrent access by setenv(3)")
135  {
136  	pthread_t threads[THREADED_NUM_THREADS];
137  	time_t endtime = time(NULL) + THREADED_RUN_TIME;
138  
139  	for (int i = 0; i < THREADED_NUM_THREADS; i++) {
140  		T_QUIET; T_ASSERT_POSIX_ZERO(
141  				pthread_create(&threads[i], NULL, thread_setenv, &endtime),
142  				NULL);
143  	}
144  	for (int i = 0; i < THREADED_NUM_THREADS; i++) {
145  		T_QUIET; T_ASSERT_POSIX_ZERO(pthread_join(threads[i], NULL), NULL);
146  	}
147  	T_PASS("setenv_thread() completed successfully");
148  }
149  
150  T_DECL(unsetenv_thread, "Test unsetenv(3) with threads",
151  		T_META_ENVVAR("MallocStackLogging=lite"))
152  {
153  	pthread_t threads[THREADED_NUM_THREADS];
154  	time_t endtime = time(NULL) + THREADED_RUN_TIME;
155  
156  	for (int i = 0; i < THREADED_NUM_THREADS; i++) {
157  		T_QUIET; T_ASSERT_POSIX_ZERO(
158  				pthread_create(&threads[i], NULL, thread_unsetenv, &endtime),
159  				NULL);
160  	}
161  	for (int i = 0; i < THREADED_NUM_THREADS; i++) {
162  		T_QUIET; T_ASSERT_POSIX_ZERO(pthread_join(threads[i], NULL), NULL);
163  	}
164  	T_PASS("unsetenv_thread() completed successfully");
165  }
166