summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/helpers/Makemodule.am6
-rw-r--r--tests/helpers/test_uuidd.c356
2 files changed, 362 insertions, 0 deletions
diff --git a/tests/helpers/Makemodule.am b/tests/helpers/Makemodule.am
index 6ac5b7f01..8d91caadd 100644
--- a/tests/helpers/Makemodule.am
+++ b/tests/helpers/Makemodule.am
@@ -14,3 +14,9 @@ test_sysinfo_SOURCES = tests/helpers/test_sysinfo.c
check_PROGRAMS += test_sigreceive
test_sigreceive_SOURCES = tests/helpers/test_sigreceive.c
test_sigreceive_LDADD = $(LDADD) libcommon.la
+
+check_PROGRAMS += test_uuidd
+test_uuidd_SOURCES = tests/helpers/test_uuidd.c
+test_uuidd_LDADD = libuuid.la -lpthread
+test_uuidd_CFLAGS = $(AM_CFLAGS) -I$(ul_libuuid_incdir)
+
diff --git a/tests/helpers/test_uuidd.c b/tests/helpers/test_uuidd.c
new file mode 100644
index 000000000..ea7544265
--- /dev/null
+++ b/tests/helpers/test_uuidd.c
@@ -0,0 +1,356 @@
+/* (C) 2006 Hewlett-Packard Development Company, L.P. */
+/* Huschaam Hussain, TSG Solution Alliances Engineering, SAP Technology Group */
+/* eMail: Huschaam.Hussain@hp.com */
+
+#include <errno.h>
+#include <libgen.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <uuid/uuid.h>
+
+#define LOG(level,args) if (logging >= level) { fprintf args; }
+
+char *program;
+pid_t pid;
+
+int processes = 4;
+int threads = 4;
+int objects = 4096;
+int logging = 0;
+int help = 0;
+
+struct threadentry {
+ pthread_t thread;
+ pthread_attr_t thread_attr;
+ long arg; /* index in object[] */
+ long value; /* thread retval */
+};
+typedef struct threadentry thread_t;
+
+struct processentry {
+ pid_t pid;
+ int status;
+};
+typedef struct processentry process_t;
+
+struct objectentry {
+ uuid_t uuid;
+ pid_t pid;
+ pthread_t tid;
+ int pos;
+};
+typedef struct objectentry object_t;
+
+int objectid;
+object_t *object;
+
+void
+error(int line, char *text)
+{
+ LOG(0,
+ (stderr, "%s %d: line %d: %s: errno %d: %s\n", program, pid, line,
+ text, errno, strerror(errno)));
+ exit(errno);
+} /* of error */
+
+void
+uuid_error(int line, char *text, int status)
+{
+ LOG(0,
+ (stderr, "%s %d: line %d: %s: status %d\n", program, pid, line,
+ text, status));
+ exit(1);
+} /* of uuid error */
+
+void
+pthread_error(int line, char *text, int value)
+{
+ LOG(0,
+ (stderr, "%s %d: line %d: %s: errno %d: %s\n", program, pid, line,
+ text, value, strerror(value)));
+ exit(value);
+} /* of pthread error */
+
+void
+read_arguments(int argc, char *argv[])
+{
+ int status, i;
+ unsigned long parameter;
+
+ status = 0;
+ while (!status && ((i = getopt(argc, argv, "p:t:o:l:h")) != -1)) {
+ switch (i) {
+ case 'p':
+ processes = strtol(optarg, (char **)NULL, 10);
+ status = errno != 0 || processes < 1
+ || processes > 1024;
+ if (status)
+ LOG(0,
+ (stderr,
+ "error: bad value for <number of processes>\n"));
+ break;
+ case 't':
+ threads = strtol(optarg, (char **)NULL, 10);
+ status = errno != 0 || threads < 1 || threads > 8192;
+ if (status)
+ LOG(0,
+ (stderr,
+ "error: bad value for <number of threads>\n"));
+ break;
+ case 'o':
+ objects = strtol(optarg, (char **)NULL, 10);
+ status = errno != 0 || objects < 1 || objects > 1048576;
+ if (status)
+ LOG(0,
+ (stderr,
+ "error: bad value for <number of objects>\n"));
+ break;
+ case 'l':
+ logging = strtol(optarg, (char **)NULL, 10);
+ if (errno != 0 || logging < 0 || logging > 3) {
+ status = 1;
+ fprintf(stderr,
+ "error: bad value for <logging level>\n");
+ } /* of if */
+ break;
+ case 'h':
+ help = 1;
+ break;
+ default:
+ status = 1;
+ } /* of switch */
+ } /* of while */
+ if (optind != argc)
+ status = 1;
+ if (status != 0 || help != 0) {
+ LOG(0, (stderr, "usage: %s [options]\n", program));
+ LOG(0,
+ (stderr,
+ " -p <number of processes> [1-1024] default:%d\n",
+ processes));
+ LOG(0,
+ (stderr,
+ " -t <number of threads> [1-8192] default:%d\n",
+ threads));
+ LOG(0,
+ (stderr,
+ " -o <number of objects> [1-1048576] default:%d\n",
+ objects));
+ LOG(0,
+ (stderr, " -l <logging level> [0|1|2|3] default:%d\n",
+ logging));
+ LOG(0, (stderr, " -h display help\n"));
+ exit(status);
+ } /* of if */
+ LOG(1, (stderr, "%s %d: processes=%d\n", program, pid, processes));
+ LOG(1, (stderr, "%s %d: threads=%d\n", program, pid, threads));
+ LOG(1, (stderr, "%s %d: objects=%d\n", program, pid, objects));
+ LOG(1, (stderr, "%s %d: logging=%d\n", program, pid, logging));
+ LOG(1, (stderr, "%s %d: help=%d\n", program, pid, help));
+} /* of read arguments */
+
+void
+allocate_segment(int *id, void **address, size_t number, size_t size)
+{
+ *id = shmget(IPC_PRIVATE, number * size, IPC_CREAT | 0600);
+ if (*id == -1)
+ error(__LINE__ - 2, "shmget()");
+ *address = shmat(*id, NULL, 0);
+ if (*address == (void *)-1)
+ error(__LINE__ - 2, "shmat()");
+ LOG(2,
+ (stderr,
+ "%s %d: allocate shared memory segment [id=%d,address=0x%p]\n",
+ program, pid, *id, *address));
+} /* of allocate segment */
+
+void
+remove_segment(int id, void *address)
+{
+ if (shmdt(address) == -1)
+ error(__LINE__ - 1, "shmdt()");
+ if (shmctl(id, IPC_RMID, NULL) == -1)
+ error(__LINE__ - 1, "shmctl()");
+ LOG(2,
+ (stderr,
+ "%s %d: remove shared memory segment [id=%d,address=0x%p]\n",
+ program, pid, id, address));
+} /* of remove segment */
+
+void
+object_uuid_create(object_t * object)
+{
+ uuid_generate_time(object->uuid);
+} /* of object uuid create */
+
+void
+object_uuid_to_string(object_t * object, unsigned char **string_uuid)
+{
+ uuid_unparse(object->uuid, *string_uuid);
+} /* of object uuid to string */
+
+int
+object_uuid_compare(const void *object1, const void *object2)
+{
+ uuid_t *uuid1, *uuid2;
+ int result;
+
+ uuid1 = &((object_t *) object1)->uuid;
+ uuid2 = &((object_t *) object2)->uuid;
+ result = uuid_compare(*uuid1, *uuid2);
+ return (result);
+} /* of object uuid compare */
+
+void *
+create_uuids(void *p)
+{
+ long index, i;
+
+ index = *((long *)p);
+ for (i = index; i < index + objects; i++) {
+ object_uuid_create(&object[i]);
+ object[i].pid = pid;
+ object[i].tid = pthread_self();
+ object[i].pos = i - index;
+ } /* of for */
+ return (0);
+} /* of create uuids */
+
+void
+create_threads(int index)
+{
+ thread_t *thread;
+ int i, result;
+
+ pid = getpid();
+ thread = (thread_t *) calloc(threads, sizeof(thread_t));
+ if (thread == NULL)
+ error(__LINE__ - 2, "calloc");
+ for (i = 0; i < threads; i++) {
+ result = pthread_attr_init(&thread[i].thread_attr);
+ if (result != 0)
+ pthread_error(__LINE__, "pthread_attr_init", result);
+ thread[i].arg = index;
+ result =
+ pthread_create(&thread[i].thread, &thread[i].thread_attr,
+ &create_uuids, &thread[i].arg);
+ if (result != 0)
+ pthread_error(__LINE__, "pthread_create", result);
+ LOG(2,
+ (stderr, "%s %d: started thread [tid=%d,arg=%d]\n", program,
+ pid, thread[i].thread, thread[i].arg));
+ index = index + objects;
+ } /* of for */
+ for (i = 0; i < threads; i++) {
+ result =
+ pthread_join(thread[i].thread, (void *)&thread[i].value);
+ if (result != 0)
+ pthread_error(__LINE__, "pthread_join", result);
+ LOG(2,
+ (stderr, "%s %d: thread exited [tid=%d,value=%d]\n",
+ program, pid, thread[i].thread, thread[i].value));
+ } /* of for */
+ free(thread);
+} /* of create threads */
+
+void
+create_processes()
+{
+ process_t *process;
+ int i;
+
+ process = (process_t *) calloc(processes, sizeof(process_t));
+ if (process == NULL)
+ error(__LINE__ - 2, "calloc");
+ for (i = 0; i < processes; i++) {
+ process[i].pid = fork();
+ switch (process[i].pid) {
+ case -1:
+ error(__LINE__ - 3, "fork()");
+ break;
+ case 0:
+ create_threads(i * threads * objects);
+ exit(0);
+ break;
+ default:
+ LOG(2,
+ (stderr, "%s %d: started process [pid=%d]\n",
+ program, pid, process[i].pid));
+ break;
+ } /* of switch */
+ } /* of for */
+ for (i = 0; i < processes; i++) {
+ if (waitpid(process[i].pid, &process[i].status, 0) ==
+ (pid_t) - 1)
+ error(__LINE__ - 1, "waitpid()");
+ LOG(2,
+ (stderr, "%s %d: process exited [pid=%d,status=%d]\n",
+ program, pid, process[i].pid, process[i].status));
+ } /* of for */
+ free(process);
+} /* of create processes */
+
+void
+object_dump(int i)
+{
+ unsigned char uuid_string[37], *p;
+
+ p = uuid_string;
+ object_uuid_to_string(&object[i], &p);
+ LOG(0,
+ (stderr, "%s %d: object[%d]=[uuid=<%s>,pid=%d,tid=%d,pos=%d]\n",
+ program, pid, i, p, object[i].pid, object[i].tid, object[i].pos));
+} /* of object dump */
+
+int
+main(int argc, char *argv[])
+{
+ int i, count;
+
+ errno = 0;
+ program = strdup(basename(argv[0]));
+ pid = getpid();
+ read_arguments(argc, argv);
+ allocate_segment(&objectid, (void **)&object,
+ processes * threads * objects, sizeof(object_t));
+ create_processes();
+ if (logging >= 3) {
+ for (i = 0; i < processes * threads * objects; i++) {
+ object_dump(i);
+ } /* of for */
+ } /* of if */
+ qsort(object, processes * threads * objects, sizeof(object_t),
+ object_uuid_compare);
+ LOG(2, (stdout, "%s %d: qsort() done\n", program, pid));
+ count = 0;
+ for (i = 0; i < processes * threads * objects - 1; i++) {
+ if (object_uuid_compare(&object[i], &object[i + 1]) == 0) {
+ if (logging >= 1) {
+ LOG(0,
+ (stdout,
+ "%s %d: objects #%d and #%d have duplicate UUIDs\n",
+ program, pid, i, i + 1));
+ object_dump(i);
+ object_dump(i + 1);
+ } /* of if */
+ count = count + 1;
+ } /* of if */
+ } /* of for */
+ remove_segment(objectid, object);
+ if (count == 0) {
+ LOG(0,
+ (stdout, "test successful (no duplicate UUIDs found)\n"));
+ } /* of if */
+ else {
+ LOG(0,
+ (stdout, "test failed (found %d duplicate UUIDs)\n",
+ count));
+ } /* of else */
+} /* of main */