]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
tests: add uuidd test program
authorHuschaam Hussain <Huschaam.Hussain@hp.com>
Fri, 24 Apr 2015 09:28:47 +0000 (11:28 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 24 Apr 2015 09:30:49 +0000 (11:30 +0200)
References: https://bugzilla.redhat.com/show_bug.cgi?id=678306
Signed-off-by: Karel Zak <kzak@redhat.com>
tests/helpers/Makemodule.am
tests/helpers/test_uuidd.c [new file with mode: 0644]

index 6ac5b7f01d752acf5aaf681c26376772a90a29af..8d91caadd0e5e6a97f57697f581958048affd014 100644 (file)
@@ -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 (file)
index 0000000..ea75442
--- /dev/null
@@ -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 */