[libxml2] Expand the limit test program



commit 3f0c613f28396c2b1acf90ad08382f0c9620d035
Author: Daniel Veillard <veillard redhat com>
Date:   Fri Aug 3 12:04:09 2012 +0800

    Expand the limit test program

 testlimits.c |  313 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 307 insertions(+), 6 deletions(-)
---
diff --git a/testlimits.c b/testlimits.c
index 1cebd3e..72392a0 100644
--- a/testlimits.c
+++ b/testlimits.c
@@ -23,6 +23,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <sys/time.h>
 
 #include <libxml/parser.h>
 #include <libxml/parserInternals.h>
@@ -37,6 +38,47 @@ static int tests_quiet = 0;
 
 /************************************************************************
  *									*
+ *		time handling                                           *
+ *									*
+ ************************************************************************/
+
+/* maximum time for one parsing befor declaring a timeout */
+#define MAX_TIME 2 /* seconds */
+
+struct timeval t0;
+struct timeval tnow;
+int timeout = 0;
+
+static void reset_timout(void) {
+    timeout = 0;
+    gettimeofday(&t0, NULL);
+}
+
+static unsigned long delta_timeval(void) {
+    unsigned long ret;
+
+    if (tnow.tv_usec < t0.tv_usec) {
+        ret = 1000000 + tnow.tv_usec;
+        ret -= t0.tv_usec;
+        ret += (tnow.tv_sec - t0.tv_sec -1) * 1000000;
+    } else {
+        ret = tnow.tv_usec - t0.tv_usec;
+        ret += (tnow.tv_sec - t0.tv_sec) * 1000000;
+    }
+    return(ret);
+}
+
+static int check_time(void) {
+    gettimeofday(&tnow, NULL);
+    if (delta_timeval() > MAX_TIME * 1000000) {
+        timeout = 1;
+        return(0);
+    }
+    return(1);
+}
+
+/************************************************************************
+ *									*
  *		Huge document generator					*
  *									*
  ************************************************************************/
@@ -122,6 +164,7 @@ found:
 static int
 hugeClose(void * context) {
     if (context == NULL) return(-1);
+    fprintf(stderr, "\n");
     return(0);
 }
 
@@ -204,6 +247,146 @@ hugeRead(void *context, char *buffer, int len)
 
 /************************************************************************
  *									*
+ *		Crazy document generator				*
+ *									*
+ ************************************************************************/
+
+unsigned int crazy_indx = 0;
+
+const char *crazy = "<?xml version='1.0' encoding='UTF-8'?>\
+<?tst ?>\
+<!-- tst -->\
+<!DOCTYPE foo [\
+<?tst ?>\
+<!-- tst -->\
+<!ELEMENT foo (#PCDATA)>\
+<!ELEMENT p (#PCDATA|emph)* >\
+]>\
+<?tst ?>\
+<!-- tst -->\
+<foo bar='foo'>\
+<?tst ?>\
+<!-- tst -->\
+foo\
+<![CDATA[ ]]>\
+</foo>\
+<?tst ?>\
+<!-- tst -->";
+
+/**
+ * crazyMatch:
+ * @URI: an URI to test
+ *
+ * Check for a crazy: query
+ *
+ * Returns 1 if yes and 0 if another Input module should be used
+ */
+static int
+crazyMatch(const char * URI) {
+    if ((URI != NULL) && (!strncmp(URI, "crazy:", 6)))
+        return(1);
+    return(0);
+}
+
+/**
+ * crazyOpen:
+ * @URI: an URI to test
+ *
+ * Return a pointer to the crazy: query handler, in this example simply
+ * the current pointer...
+ *
+ * Returns an Input context or NULL in case or error
+ */
+static void *
+crazyOpen(const char * URI) {
+    if ((URI == NULL) || (strncmp(URI, "crazy:", 6)))
+        return(NULL);
+
+    if (crazy_indx > strlen(crazy))
+        return(NULL);
+    reset_timout();
+    rlen = crazy_indx;
+    current = &crazy[0];
+    instate = 0;
+    return((void *) current);
+}
+
+/**
+ * crazyClose:
+ * @context: the read context
+ *
+ * Close the crazy: query handler
+ *
+ * Returns 0 or -1 in case of error
+ */
+static int
+crazyClose(void * context) {
+    if (context == NULL) return(-1);
+    return(0);
+}
+
+
+/**
+ * crazyRead:
+ * @context: the read context
+ * @buffer: where to store data
+ * @len: number of bytes to read
+ *
+ * Implement an crazy: query read.
+ *
+ * Returns the number of bytes read or -1 in case of error
+ */
+static int
+crazyRead(void *context, char *buffer, int len)
+{
+    if ((context == NULL) || (buffer == NULL) || (len < 0))
+        return (-1);
+
+    if ((check_time() <= 0) && (instate == 1)) {
+        fprintf(stderr, "\ntimeout in crazy(%d)\n", crazy_indx);
+        rlen = strlen(crazy) - crazy_indx;
+        current = &crazy[crazy_indx];
+        instate = 2;
+    }
+    if (instate == 0) {
+        if (len >= rlen) {
+            len = rlen;
+            rlen = 0;
+            memcpy(buffer, current, len);
+            instate = 1;
+            curlen = 0;
+        } else {
+            memcpy(buffer, current, len);
+            rlen -= len;
+            current += len;
+        }
+    } else if (instate == 2) {
+        if (len >= rlen) {
+            len = rlen;
+            rlen = 0;
+            memcpy(buffer, current, len);
+            instate = 3;
+            curlen = 0;
+        } else {
+            memcpy(buffer, current, len);
+            rlen -= len;
+            current += len;
+        }
+    } else if (instate == 1) {
+        if (len > CHUNK) len = CHUNK;
+        memcpy(buffer, &filling[0], len);
+        curlen += len;
+        if (curlen >= maxlen) {
+            rlen = strlen(crazy) - crazy_indx;
+            current = &crazy[crazy_indx];
+            instate = 2;
+        }
+    } else
+      len = 0;
+    return (len);
+}
+/************************************************************************
+ *									*
  *		Libxml2 specific routines				*
  *									*
  ************************************************************************/
@@ -514,6 +697,11 @@ initializeLibxml2(void) {
         fprintf(stderr, "failed to register Huge handlers\n");
 	exit(1);
     }
+    if (xmlRegisterInputCallbacks(crazyMatch, crazyOpen,
+                                  crazyRead, crazyClose) < 0) {
+        fprintf(stderr, "failed to register Crazy handlers\n");
+	exit(1);
+    }
 }
 
 /************************************************************************
@@ -1082,7 +1270,7 @@ static xmlSAXHandlerPtr callbackSAX2Handler = &callbackSAX2HandlerStruct;
  * @options: parsing options
  * @fail: should a failure be reported
  *
- * Parse a memory generated file using the xmlReader
+ * Parse a memory generated file using SAX
  *
  * Returns 0 in case of success, an error code otherwise
  */
@@ -1105,7 +1293,6 @@ saxTest(const char *filename, size_t limit, int options, int fail) {
     ctxt->sax = callbackSAX2Handler;
     ctxt->userData = NULL;
     doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
-    fprintf(stderr, "\n");
 
     if (doc != NULL) {
         fprintf(stderr, "SAX parsing generated a document !\n");
@@ -1161,22 +1348,32 @@ readerTest(const char *filename, size_t limit, int options, int fail) {
     while (ret == 1) {
         ret = xmlTextReaderRead(reader);
     }
-    fprintf(stderr, "\n");
     if (ret != 0) {
         if (fail)
             res = 0;
         else {
-            fprintf(stderr, "Failed to parse '%s' %lu\n", filename, limit);
+            if (strncmp(filename, "crazy:", 6) == 0) 
+                fprintf(stderr, "Failed to parse '%s' %u\n",
+                        filename, crazy_indx);
+            else
+                fprintf(stderr, "Failed to parse '%s' %lu\n",
+                        filename, limit);
             res = 1;
         }
     } else {
         if (fail) {
-            fprintf(stderr, "Failed to get failure for '%s' %lu\n",
-                    filename, limit);
+            if (strncmp(filename, "crazy:", 6) == 0) 
+                fprintf(stderr, "Failed to get failure for '%s' %u\n",
+                        filename, crazy_indx);
+            else
+                fprintf(stderr, "Failed to get failure for '%s' %lu\n",
+                        filename, limit);
             res = 1;
         } else
             res = 0;
     }
+    if (timeout)
+        res = 1;
     xmlFreeTextReader(reader);
 
     return(res);
@@ -1313,6 +1510,107 @@ runtest(unsigned int i) {
     return(ret);
 }
 
+static int
+launchCrazySAX(unsigned int test, int fail) {
+    int res = 0, err = 0;
+
+    crazy_indx = test;
+
+    res = saxTest("crazy::test", XML_MAX_LOOKUP_LIMIT - CHUNK, 0, fail);
+    if (res != 0) {
+        nb_errors++;
+        err++;
+    }
+    if (tests_quiet == 0)
+        fprintf(stderr, "%c", crazy[test]);
+
+    return(err);
+}
+
+static int
+launchCrazy(unsigned int test, int fail) {
+    int res = 0, err = 0;
+
+    crazy_indx = test;
+
+    res = readerTest("crazy::test", XML_MAX_LOOKUP_LIMIT - CHUNK, 0, fail);
+    if (res != 0) {
+        nb_errors++;
+        err++;
+    }
+    if (tests_quiet == 0)
+        fprintf(stderr, "%c", crazy[test]);
+
+    return(err);
+}
+
+static int get_crazy_fail(int test) {
+    /*
+     * adding 1000000 of character 'a' leads to parser failure mostly
+     * everywhere except in those special spots. Need to be updated
+     * each time crazy is updated
+     */
+    int fail = 1;
+    if ((test == 44) || /* PI in Misc */
+        ((test >= 50) && (test <= 55)) || /* Comment in Misc */
+        (test == 79) || /* PI in DTD */
+        ((test >= 85) && (test <= 90)) || /* Comment in DTD */
+        (test == 154) || /* PI in Misc */
+        ((test >= 160) && (test <= 165)) || /* Comment in Misc */
+        ((test >= 178) && (test <= 181)) || /* attribute value */
+        (test == 183) || /* Text */
+        (test == 189) || /* PI in Content */
+        (test == 191) || /* Text */
+        ((test >= 195) && (test <= 200)) || /* Comment in Content */
+        ((test >= 203) && (test <= 206)) || /* Text */
+        (test == 215) || (test == 216) || /* in CDATA */
+        (test == 219) || /* Text */
+        (test == 231) || /* PI in Misc */
+        ((test >= 237) && (test <= 242))) /* Comment in Misc */
+        fail = 0;
+    return(fail);
+}
+
+static int
+runcrazy(void) {
+    int ret = 0, res;
+    int old_errors, old_tests, old_leaks;
+    unsigned int i;
+
+    old_errors = nb_errors;
+    old_tests = nb_tests;
+    old_leaks = nb_leaks;
+    if (tests_quiet == 0) {
+	printf("## Crazy tests on reader\n");
+    }
+    for (i = 0;i < strlen(crazy);i++) {
+        res += launchCrazy(i, get_crazy_fail(i));
+        if (res != 0)
+            ret++;
+    }
+    if (tests_quiet == 0) {
+	printf("\n## Crazy tests on SAX\n");
+    }
+    for (i = 0;i < strlen(crazy);i++) {
+        res += launchCrazySAX(i, get_crazy_fail(i));
+        if (res != 0)
+            ret++;
+    }
+    if (tests_quiet == 0)
+        fprintf(stderr, "\n");
+    if (verbose) {
+	if ((nb_errors == old_errors) && (nb_leaks == old_leaks))
+	    printf("Ran %d tests, no errors\n", nb_tests - old_tests);
+	else
+	    printf("Ran %d tests, %d errors, %d leaks\n",
+		   nb_tests - old_tests,
+		   nb_errors - old_errors,
+		   nb_leaks - old_leaks);
+    }
+    return(ret);
+}
+
+
 int
 main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
     int i, a, ret = 0;
@@ -1326,12 +1624,15 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
 	    verbose = 1;
         else if (!strcmp(argv[a], "-quiet"))
 	    tests_quiet = 1;
+        else if (!strcmp(argv[a], "-crazy"))
+	    subset = 1;
     }
     if (subset == 0) {
 	for (i = 0; testDescriptions[i].func != NULL; i++) {
 	    ret += runtest(i);
 	}
     }
+    ret += runcrazy();
     if ((nb_errors == 0) && (nb_leaks == 0)) {
         ret = 0;
 	printf("Total %d tests, no errors\n",



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]