Пример #1
0
int
main(int argc, char *argv[])
{

    char *zooname;
    zoo_t test_zoo;
    char *test_tag = "unittest";
    int i,j;


    zooname = zoo_getname();

    if (!zooname) {
	zooname = strdup("test_zoo");
    }
    printf("Test zoo filename is %s\n", zooname);

    if ((test_zoo = zoo_open(zooname)) == NULL) {
	printf("Error opennning zoo\n");
	exit(-1);
    }


    zoo_mark_args(test_zoo, getpid(), test_tag, argc, argv);


    for (j = 0; j < 5; j++) {
	for (i = 0; i < 20; i++) {
	    zt_add(test_zoo, i);
	}

	for (; i >=0; i--) {
	    zoo_clear(test_zoo, i);
	}
    }

    zoo_clear(test_zoo, getpid());


    return 0;
}
Пример #2
0
int main(int argc, char **argv)
{
	extern char *optarg;
	extern int optind;
	char *zooname = NULL;	/* name of the zoo file to use */
	char *filename = "/dev/null";	/* filename to read test tags from */
	char *logfilename = NULL;
	char *failcmdfilename = NULL;
	char *tconfcmdfilename = NULL;
	char *outputfilename = NULL;
	struct collection *coll = NULL;
	struct tag_pgrp *running;
	struct orphan_pgrp *orphans, *orph;
	struct utsname unamebuf;
	FILE *logfile = NULL;
	FILE *failcmdfile = NULL;
	FILE *tconfcmdfile = NULL;
	int keep_active = 1;
	int num_active = 0;
	int failcnt = 0;  /* count of total testcases that failed. */
	int tconfcnt = 0; /* count of total testcases that return TCONF */
	int err, i;
	int starts = -1;
	int timed = 0;
	int run_time = -1;
	char modifier = 'm';
	int ret = 0;
	int stop;
	int go_idle;
	int has_brakes = 0;	/* stop everything if a test case fails */
	int sequential = 0;	/* run tests sequentially */
	int fork_in_road = 0;
	int exit_stat;
	int track_exit_stats = 0;	/* exit non-zero if any test exits non-zero */
	int fmt_print = 0;	/* enables formatted printing of logfiles. */
	int quiet_mode = 0;	/* supresses test start and test end tags. */
	int c;
	pid_t cpid;
	struct sigaction sa;

	while ((c =
		getopt(argc, argv, "AO:Sa:C:T:d:ef:hl:n:o:pqr:s:t:x:y"))
		       != -1) {
		switch (c) {
		case 'A':	/* all-stop flag */
			has_brakes = 1;
			track_exit_stats = 1;
			break;
		case 'O':	/* output buffering directory */
			test_out_dir = strdup(optarg);
			break;
		case 'S':	/* run tests sequentially */
			sequential = 1;
			break;
		case 'a':	/* name of the zoo file to use */
			zooname = strdup(optarg);
			break;
		case 'C':	/* name of the file where all failed commands will be */
			failcmdfilename = strdup(optarg);
			break;
		case 'T':
			/*
			 * test cases that are not fully tested will be recorded
			 * in this file
			 */
			tconfcmdfilename = strdup(optarg);
			break;
		case 'd':	/* debug options */
			sscanf(optarg, "%i", &Debug);
			break;
		case 'e':	/* exit non-zero if any test exists non-zero */
			track_exit_stats = 1;
			break;
		case 'f':	/* filename to read test tags from */
			filename = strdup(optarg);
			break;
		case 'h':	/* help */
			fprintf(stdout,
				"Usage: pan -n name [ -SyAehpq ] [ -s starts ]"
				" [-t time[s|m|h|d] [ -x nactive ] [ -l logfile ]\n\t"
				"[ -a active-file ] [ -f command-file ] "
				"[ -C fail-command-file ] "
				"[ -d debug-level ]\n\t[-o output-file] "
				"[-O output-buffer-directory] [cmd]\n");
			exit(0);
		case 'l':	/* log file */
			logfilename = strdup(optarg);
			break;
		case 'n':	/* tag given to pan */
			panname = strdup(optarg);
			break;
		case 'o':	/* send test output here */
			outputfilename = strdup(optarg);
			break;
		case 'p':	/* formatted printing. */
			fmt_print = 1;
			break;
		case 'q':	/* supress test start and test end messages */
			quiet_mode = 1;
			break;
		case 'r':	/* reporting type: none, rts */
			reporttype = strdup(optarg);
			break;
		case 's':	/* number of tags to run */
			starts = atoi(optarg);
			break;
		case 't':	/* run_time to run */
			ret = sscanf(optarg, "%d%c", &run_time, &modifier);
			if (ret == 0) {
				fprintf(stderr,
					"Need proper time input: ####x where"
					"x is one of s,m,h,d\n");
				break;
			} else if (ret == 1) {
				fprintf(stderr, "Only got a time value of %d "
					"modifiers need to come immediately after #"
					" assuming %c\n", run_time, modifier);
			} else {
				switch (modifier) {
				case 's':
					run_time = run_time;
					break;
				case 'm':
					run_time = run_time * 60;
					break;
				case 'h':
					run_time = run_time * 60 * 60;
					break;
				case 'd':
					run_time = run_time * 60 * 60 * 24;
					break;
				default:
					fprintf(stderr,
						"Invalid time modifier, try: s|h|m|d\n");
					exit(-1);
				}
				if (!quiet_mode)
					printf("PAN will run for %d seconds\n",
					       run_time);
			}
			timed = 1;	//-t implies run as many starts as possible, by default
			break;
		case 'x':	/* number of tags to keep running */
			keep_active = atoi(optarg);
			break;
		case 'y':	/* restart on failure or signal */
			fork_in_road = 1;
			break;
		}
	}

	if (panname == NULL) {
		fprintf(stderr, "pan: Must supply -n\n");
		exit(1);
	}
	if (zooname == NULL) {
		zooname = zoo_getname();
		if (zooname == NULL) {
			fprintf(stderr,
				"pan(%s): Must supply -a or set ZOO env variable\n",
				panname);
			exit(1);
		}
	}
	if (reporttype) {
		/* make sure we understand the report type */
		if (strcasecmp(reporttype, "rts")
		    && strcasecmp(reporttype, "none")
		    /* && strcasecmp(reporttype, "xml") */
		    )
			reporttype = "rts";
	} else {
		/* set the default */
		reporttype = "rts";
	}

	if (logfilename != NULL) {
		time_t startup;
		char *s;

		if (!strcmp(logfilename, "-")) {
			logfile = stdout;
		} else {
			if ((logfile = fopen(logfilename, "a+")) == NULL) {
				fprintf(stderr,
					"pan(%s): Error %s (%d) opening log file '%s'\n",
					panname, strerror(errno), errno,
					logfilename);
				exit(1);
			}
		}

		time(&startup);
		s = ctime(&startup);
		*(s + strlen(s) - 1) = '\0';
		if (!fmt_print)
			fprintf(logfile, "startup='%s'\n", s);
		else {
			fprintf(logfile, "Test Start Time: %s\n", s);
			fprintf(logfile,
				"-----------------------------------------\n");
			fprintf(logfile, "%-30.20s %-10.10s %-10.10s\n",
				"Testcase", "Result", "Exit Value");
			fprintf(logfile, "%-30.20s %-10.10s %-10.10s\n",
				"--------", "------", "------------");
		}
		fflush(logfile);
	}

	coll = get_collection(filename, optind, argc, argv);
	if (!coll)
		exit(1);
	if (coll->cnt == 0) {
		fprintf(stderr,
			"pan(%s): Must supply a file collection or a command\n",
			panname);
		exit(1);
	}

	if (Debug & Dsetup)
		dump_coll(coll);

	/* a place to store the pgrps we're watching */
	running =
		malloc((keep_active + 1) *
			sizeof(struct tag_pgrp));
	if (running == NULL) {
		fprintf(stderr, "pan(%s): Failed to allocate memory: %s\n",
			panname, strerror(errno));
		exit(2);
	}
	memset(running, 0, keep_active * sizeof(struct tag_pgrp));
	running[keep_active].pgrp = -1;	/* end sentinel */

	/* a head to the orphaned pgrp list */
	orphans = malloc(sizeof(struct orphan_pgrp));
	memset(orphans, 0, sizeof(struct orphan_pgrp));

	srand48(time(NULL) ^ (getpid() + (getpid() << 15)));

	/* Supply a default for starts.  If we are in sequential mode, use
	 * the number of commands available; otherwise 1.
	 */
	if (timed == 1 && starts == -1) {	/* timed, infinite by default */
		starts = -1;
	} else if (starts == -1) {
		if (sequential) {
			starts = coll->cnt;
		} else {
			starts = 1;
		}
	} else if (starts == 0) {	/* if the user specified infinite, set it */
		starts = -1;
	} else {		/* else, make sure we are starting at least keep_active processes */
		if (starts < keep_active)
			starts = keep_active;
	}

	/* if we're buffering output, but we're only running on process at a time,
	 * then essentially "turn off buffering"
	 */
	if (test_out_dir && (keep_active == 1)) {
		free(test_out_dir);
		test_out_dir = NULL;
	}

	if (test_out_dir) {
		struct stat sbuf;

		if (stat(test_out_dir, &sbuf) < 0) {
			fprintf(stderr,
				"pan(%s): stat of -O arg '%s' failed.  errno: %d  %s\n",
				panname, test_out_dir, errno, strerror(errno));
			exit(1);
		}
		if (!S_ISDIR(sbuf.st_mode)) {
			fprintf(stderr,
				"pan(%s): -O arg '%s' must be a directory.\n",
				panname, test_out_dir);
			exit(1);
		}
		if (access(test_out_dir, W_OK | R_OK | X_OK) < 0) {
			fprintf(stderr,
				"pan(%s): permission denied on -O arg '%s'.  errno: %d  %s\n",
				panname, test_out_dir, errno, strerror(errno));
			exit(1);
		}
	}

	if (outputfilename) {
		if (!freopen(outputfilename, "a+", stdout)) {
			fprintf(stderr,
				"pan(%s): Error %s (%d) opening output file '%s'\n",
				panname, strerror(errno), errno,
				outputfilename);
			exit(1);
		}
	}

	if (failcmdfilename) {
		if (!(failcmdfile = fopen(failcmdfilename, "a+"))) {
			fprintf(stderr,
				"pan(%s): Error %s (%d) opening fail cmd file '%s'\n",
				panname, strerror(errno), errno,
				failcmdfilename);
			exit(1);
		}
	}

	if (tconfcmdfilename) {
		tconfcmdfile = fopen(tconfcmdfilename, "a+");
		if (!tconfcmdfile) {
			fprintf(stderr, "pan(%s): Error %s (%d) opening "
				"tconf cmd file '%s'\n", panname,
				strerror(errno), errno, tconfcmdfilename);
			exit(1);
		}
	}

	if ((zoofile = zoo_open(zooname)) == NULL) {
		fprintf(stderr, "pan(%s): %s\n", panname, zoo_error);
		exit(1);
	}
	if (zoo_mark_args(zoofile, getpid(), panname, argc, argv)) {
		fprintf(stderr, "pan(%s): %s\n", panname, zoo_error);
		exit(1);
	}

	/* Allocate N spaces for max-arg commands.
	 * this is an "active file cleanliness" thing
	 */
	{
		for (c = 0; c < keep_active; c++) {
			if (zoo_mark_cmdline(zoofile, c, panname, "")) {
				fprintf(stderr, "pan(%s): %s\n", panname,
					zoo_error);
				exit(1);
			}
		}
		for (c = 0; c < keep_active; c++) {
			if (zoo_clear(zoofile, c)) {
				fprintf(stderr, "pan(%s): %s\n", panname,
					zoo_error);
				exit(1);
			}
		}
	}

	rec_signal = send_signal = 0;
	if (run_time != -1) {
		alarm(run_time);
	}

	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	sa.sa_handler = wait_handler;

	sigaction(SIGALRM, &sa, NULL);
	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGHUP, &sa, NULL);
	sigaction(SIGUSR1, &sa, NULL);	/* ignore fork_in_road */
	sigaction(SIGUSR2, &sa, NULL);	/* stop the scheduler */

	c = 0;			/* in this loop, c is the command index */
	stop = 0;
	exit_stat = 0;
	go_idle = 0;
	while (1) {

		while ((num_active < keep_active) && (starts != 0)) {
			if (stop || rec_signal || go_idle)
				break;

			if (!sequential)
				c = lrand48() % coll->cnt;

			/* find a slot for the child */
			for (i = 0; i < keep_active; ++i) {
				if (running[i].pgrp == 0)
					break;
			}
			if (i == keep_active) {
				fprintf(stderr,
					"pan(%s): Aborting: i == keep_active = %d\n",
					panname, i);
				wait_handler(SIGINT);
				exit_stat++;
				break;
			}

			cpid =
			    run_child(coll->ary[c], running + i, quiet_mode,
				      &failcnt, fmt_print, logfile);
			if (cpid != -1)
				++num_active;
			if ((cpid != -1 || sequential) && starts > 0)
				--starts;

			if (sequential)
				if (++c >= coll->cnt)
					c = 0;

		}		/* while ((num_active < keep_active) && (starts != 0)) */

		if (starts == 0) {
			if (!quiet_mode)
				printf("incrementing stop\n");
			++stop;
		} else if (starts == -1)	//wjh
		{
			FILE *f = (FILE *) - 1;
			if ((f = fopen(PAN_STOP_FILE, "r")) != 0) {
				printf("Got %s Stopping!\n", PAN_STOP_FILE);
				fclose(f);
				unlink(PAN_STOP_FILE);
				stop++;
			}
		}

		if (rec_signal) {
			/* propagate everything except sigusr2 */

			if (rec_signal == SIGUSR2) {
				if (fork_in_road)
					++go_idle;
				else
					++stop;
				rec_signal = send_signal = 0;
			} else {
				if (rec_signal == SIGUSR1)
					fork_in_road = 0;
				propagate_signal(running, keep_active, orphans);
				if (fork_in_road)
					++go_idle;
				else
					++stop;
			}
		}

		err = check_pids(running, &num_active, keep_active, logfile,
				 failcmdfile, tconfcmdfile, orphans, fmt_print,
				 &failcnt, &tconfcnt, quiet_mode);
		if (Debug & Drunning) {
			pids_running(running, keep_active);
			orphans_running(orphans);
		}
		if (err) {
			if (fork_in_road)
				++go_idle;
			if (track_exit_stats)
				exit_stat++;
			if (has_brakes) {
				fprintf(stderr, "pan(%s): All stop!%s\n",
					panname, go_idle ? " (idling)" : "");
				wait_handler(SIGINT);
			}
		}

		if (stop && (num_active == 0))
			break;

		if (go_idle && (num_active == 0)) {
			go_idle = 0;	/* It is idle, now resume scheduling. */
			wait_handler(0);	/* Reset the signal ratchet. */
		}
	}

	/* Wait for orphaned pgrps */
	while (1) {
		for (orph = orphans; orph != NULL; orph = orph->next) {
			if (orph->pgrp == 0)
				continue;
			/* Yes, we have orphaned pgrps */
			sleep(5);
			if (!rec_signal) {
				/* force an artificial signal, move us
				 * through the signal ratchet.
				 */
				wait_handler(SIGINT);
			}
			propagate_signal(running, keep_active, orphans);
			if (Debug & Drunning)
				orphans_running(orphans);
			break;
		}
		if (orph == NULL)
			break;
	}

	if (zoo_clear(zoofile, getpid())) {
		fprintf(stderr, "pan(%s): %s\n", panname, zoo_error);
		++exit_stat;
	}
	fclose(zoofile);
	if (logfile && fmt_print) {
		if (uname(&unamebuf) == -1)
			fprintf(stderr, "ERROR: uname(): %s\n",
				strerror(errno));
		fprintf(logfile,
			"\n-----------------------------------------------\n");
		fprintf(logfile, "Total Tests: %d\n", coll->cnt);
		fprintf(logfile, "Total Skipped Tests: %d\n", tconfcnt);
		fprintf(logfile, "Total Failures: %d\n", failcnt);
		fprintf(logfile, "Kernel Version: %s\n", unamebuf.release);
		fprintf(logfile, "Machine Architecture: %s\n",
			unamebuf.machine);
		fprintf(logfile, "Hostname: %s\n\n", unamebuf.nodename);
	}
	if (logfile && (logfile != stdout))
		fclose(logfile);

	if (failcmdfile)
		fclose(failcmdfile);

	if (tconfcmdfile)
		fclose(tconfcmdfile);
	exit(exit_stat);
}