t_getenv_thread.c revision 272343
190075Sobrien/*	$NetBSD: t_getenv_thread.c,v 1.2 2012/03/15 02:02:23 joerg Exp $ */
290075Sobrien
390075Sobrien/*-
490075Sobrien * Copyright (c) 2010 The NetBSD Foundation, Inc.
590075Sobrien * All rights reserved.
690075Sobrien *
790075Sobrien * This code is derived from software contributed to The NetBSD Foundation
890075Sobrien * by Matthias Scheler.
990075Sobrien *
1090075Sobrien * Redistribution and use in source and binary forms, with or without
1190075Sobrien * modification, are permitted provided that the following conditions
1290075Sobrien * are met:
1390075Sobrien * 1. Redistributions of source code must retain the above copyright
1490075Sobrien *    notice, this list of conditions and the following disclaimer.
1590075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1690075Sobrien *    notice, this list of conditions and the following disclaimer in the
1790075Sobrien *    documentation and/or other materials provided with the distribution.
1890075Sobrien *
1990075Sobrien * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2090075Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2190075Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2290075Sobrien * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2390075Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2490075Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2590075Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2690075Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2790075Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2890075Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2990075Sobrien * POSSIBILITY OF SUCH DAMAGE.
3090075Sobrien */
3190075Sobrien#include <sys/cdefs.h>
3290075Sobrien__RCSID("$NetBSD: t_getenv_thread.c,v 1.2 2012/03/15 02:02:23 joerg Exp $");
3390075Sobrien
3490075Sobrien#include <atf-c.h>
3590075Sobrien#include <errno.h>
3690075Sobrien#include <pthread.h>
3790075Sobrien#include <stdio.h>
3890075Sobrien#include <stdlib.h>
3990075Sobrien#include <string.h>
4090075Sobrien#include <time.h>
4190075Sobrien
4290075Sobrien#define	THREADED_NUM_THREADS	8
4390075Sobrien#define	THREADED_NUM_VARS	16
4490075Sobrien#define	THREADED_VAR_NAME	"THREADED%zu"
4590075Sobrien#define	THREADED_RUN_TIME	10
4690075Sobrien
4790075Sobrienstatic void	 *thread_getenv_r(void *);
4890075Sobrienstatic void	 *thread_putenv(void *);
4990075Sobrienstatic void	 *thread_setenv(void *);
5090075Sobrienstatic void	 *thread_unsetenv(void *);
5190075Sobrien
5290075Sobrienstatic void *
5390075Sobrienthread_getenv_r(void *arg)
5490075Sobrien{
5590075Sobrien	time_t endtime;
5690075Sobrien
5790075Sobrien	endtime = *(time_t *)arg;
5890075Sobrien	do {
5990075Sobrien		size_t i;
6090075Sobrien		char name[32], value[128];
6190075Sobrien
6290075Sobrien		i = lrand48() % THREADED_NUM_VARS;
6390075Sobrien		(void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i);
6490075Sobrien
6590075Sobrien		if (getenv_r(name, value, sizeof(value)) == -1) {
6690075Sobrien			ATF_CHECK(errno == ENOENT);
6790075Sobrien		}
6890075Sobrien	} while (time(NULL) < endtime);
6990075Sobrien
7090075Sobrien	return NULL;
7190075Sobrien}
7290075Sobrien
7390075Sobrien
7490075Sobrienstatic void *
7590075Sobrienthread_putenv(void *arg)
7690075Sobrien{
7790075Sobrien	time_t endtime;
7890075Sobrien	size_t i;
7990075Sobrien	static char vars[THREADED_NUM_VARS][128];
8090075Sobrien
8190075Sobrien	for (i = 0; i < THREADED_NUM_VARS; i++) {
8290075Sobrien		(void)snprintf(vars[i], sizeof(vars[i]),
8390075Sobrien		    THREADED_VAR_NAME "=putenv %ld", i, lrand48());
8490075Sobrien	}
8590075Sobrien
8690075Sobrien	endtime = *(time_t *)arg;
8790075Sobrien	do {
8890075Sobrien		char name[128];
8990075Sobrien
9090075Sobrien		i = lrand48() % THREADED_NUM_VARS;
9190075Sobrien		(void)strlcpy(name, vars[i], sizeof(name));
9290075Sobrien		*strchr(name, '=') = '\0';
9390075Sobrien
9490075Sobrien		ATF_CHECK(unsetenv(name) != -1);
9590075Sobrien		ATF_CHECK(putenv(vars[i]) != -1);
9690075Sobrien	} while (time(NULL) < endtime);
9790075Sobrien
9890075Sobrien	return NULL;
9990075Sobrien}
10090075Sobrien
10190075Sobrienstatic void *
10290075Sobrienthread_setenv(void *arg)
10390075Sobrien{
10490075Sobrien	time_t endtime;
10590075Sobrien
10690075Sobrien	endtime = *(time_t *)arg;
10790075Sobrien	do {
10890075Sobrien		size_t i;
10990075Sobrien		char name[32], value[64];
11090075Sobrien
11190075Sobrien		i = lrand48() % THREADED_NUM_VARS;
11290075Sobrien		(void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i);
11390075Sobrien		(void)snprintf(value, sizeof(value), "setenv %ld", lrand48());
11490075Sobrien
11590075Sobrien		ATF_CHECK(setenv(name, value, 1) != -1);
11690075Sobrien	} while (time(NULL) < endtime);
11790075Sobrien
11890075Sobrien	return NULL;
11990075Sobrien}
12090075Sobrien
12190075Sobrienstatic void *
12290075Sobrienthread_unsetenv(void *arg)
12390075Sobrien{
12490075Sobrien	time_t endtime;
12590075Sobrien
12690075Sobrien	endtime = *(time_t *)arg;
12790075Sobrien	do {
12890075Sobrien		size_t i;
12990075Sobrien		char name[32];
13090075Sobrien
13190075Sobrien		i = lrand48() % THREADED_NUM_VARS;
13290075Sobrien		(void)snprintf(name, sizeof(name), THREADED_VAR_NAME, i);
13390075Sobrien
13490075Sobrien		ATF_CHECK(unsetenv(name) != -1);
13590075Sobrien	} while (time(NULL) < endtime);
13690075Sobrien
13790075Sobrien	return NULL;
13890075Sobrien}
13990075Sobrien
14090075SobrienATF_TC(getenv_r_thread);
14190075SobrienATF_TC_HEAD(getenv_r_thread, tc)
14290075Sobrien{
14390075Sobrien
14490075Sobrien	atf_tc_set_md_var(tc, "descr", "Test getenv_r(3) with threads");
14590075Sobrien	atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5);
14690075Sobrien}
14790075Sobrien
14890075SobrienATF_TC_BODY(getenv_r_thread, tc)
14990075Sobrien{
15090075Sobrien	pthread_t threads[THREADED_NUM_THREADS];
15190075Sobrien	time_t endtime;
15290075Sobrien	size_t i, j;
15390075Sobrien
15490075Sobrien	endtime = time(NULL) + THREADED_RUN_TIME;
15590075Sobrien
15690075Sobrien	for (i = j = 0; j < 2; j++) {
15790075Sobrien
15890075Sobrien		ATF_CHECK(pthread_create(&threads[i++], NULL, thread_getenv_r,
15990075Sobrien		    &endtime) == 0);
16090075Sobrien	}
16190075Sobrien
16290075Sobrien	for (j = 0; j < i; j++)
16390075Sobrien		ATF_CHECK(pthread_join(threads[j], NULL) == 0);
16490075Sobrien}
16590075Sobrien
16690075SobrienATF_TC(putenv_thread);
16790075SobrienATF_TC_HEAD(putenv_thread, tc)
16890075Sobrien{
16990075Sobrien	atf_tc_set_md_var(tc, "descr", "Test concurrent access by putenv(3)");
17090075Sobrien	atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5);
17190075Sobrien}
17290075Sobrien
17390075SobrienATF_TC_BODY(putenv_thread, tc)
17490075Sobrien{
17590075Sobrien	pthread_t threads[THREADED_NUM_THREADS];
17690075Sobrien	time_t endtime;
17790075Sobrien	size_t i, j;
17890075Sobrien
17990075Sobrien	endtime = time(NULL) + THREADED_RUN_TIME;
18090075Sobrien
18190075Sobrien	for (i = j = 0; j < 2; j++) {
18290075Sobrien
18390075Sobrien		ATF_CHECK(pthread_create(&threads[i++], NULL, thread_putenv,
18490075Sobrien		    &endtime) == 0);
18590075Sobrien	}
18690075Sobrien
18790075Sobrien	for (j = 0; j < i; j++)
18890075Sobrien		ATF_CHECK(pthread_join(threads[j], NULL) == 0);
18990075Sobrien}
19090075Sobrien
19190075SobrienATF_TC(setenv_thread);
19290075SobrienATF_TC_HEAD(setenv_thread, tc)
19390075Sobrien{
19490075Sobrien	atf_tc_set_md_var(tc, "descr", "Test concurrent access by setenv(3)");
19590075Sobrien	atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5);
19690075Sobrien}
19790075Sobrien
19890075SobrienATF_TC_BODY(setenv_thread, tc)
19990075Sobrien{
20090075Sobrien	pthread_t threads[THREADED_NUM_THREADS];
20190075Sobrien	time_t endtime;
20290075Sobrien	size_t i, j;
20390075Sobrien
20490075Sobrien	endtime = time(NULL) + THREADED_RUN_TIME;
20590075Sobrien
20690075Sobrien	for (i = j = 0; j < 2; j++) {
20790075Sobrien
20890075Sobrien		ATF_CHECK(pthread_create(&threads[i++], NULL, thread_setenv,
20990075Sobrien		    &endtime) == 0);
21090075Sobrien	}
21190075Sobrien
21290075Sobrien	for (j = 0; j < i; j++)
21390075Sobrien		ATF_CHECK(pthread_join(threads[j], NULL) == 0);
21490075Sobrien}
21590075Sobrien
21690075SobrienATF_TC(unsetenv_thread);
21790075SobrienATF_TC_HEAD(unsetenv_thread, tc)
21890075Sobrien{
21990075Sobrien	atf_tc_set_md_var(tc, "descr", "Test unsetenv(3) with threads");
22090075Sobrien	atf_tc_set_md_var(tc, "timeout", "%d", THREADED_RUN_TIME + 5);
22190075Sobrien}
22290075Sobrien
22390075SobrienATF_TC_BODY(unsetenv_thread, tc)
22490075Sobrien{
22590075Sobrien	pthread_t threads[THREADED_NUM_THREADS];
22690075Sobrien	time_t endtime;
22790075Sobrien	size_t i, j;
22890075Sobrien
22990075Sobrien	endtime = time(NULL) + THREADED_RUN_TIME;
23090075Sobrien
23190075Sobrien	for (i = j = 0; j < 2; j++) {
23290075Sobrien
23390075Sobrien		ATF_CHECK(pthread_create(&threads[i++], NULL, thread_unsetenv,
23490075Sobrien		    &endtime) == 0);
23590075Sobrien	}
23690075Sobrien
23790075Sobrien	for (j = 0; j < i; j++)
23890075Sobrien		ATF_CHECK(pthread_join(threads[j], NULL) == 0);
23990075Sobrien}
24090075Sobrien
24190075SobrienATF_TP_ADD_TCS(tp)
24290075Sobrien{
24390075Sobrien
24490075Sobrien	ATF_TP_ADD_TC(tp, getenv_r_thread);
24590075Sobrien	ATF_TP_ADD_TC(tp, putenv_thread);
24690075Sobrien	ATF_TP_ADD_TC(tp, setenv_thread);
24790075Sobrien	ATF_TP_ADD_TC(tp, unsetenv_thread);
24890075Sobrien
24990075Sobrien	return atf_no_error();
25090075Sobrien}
25190075Sobrien