avoid name glob in agruments as it matches the glob() routine. first steps
* include/libxml/valid.h valid.c: avoid name glob in agruments as
it matches the glob() routine.
* runtest.c Makefile.am: first steps toward a C regression test
framework.
Daniel
diff --git a/ChangeLog b/ChangeLog
index fbcda72..8108688 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Sun Jun 26 20:08:24 CEST 2005 Daniel Veillard <daniel@veillard.com>
+
+ * include/libxml/valid.h valid.c: avoid name glob in agruments as
+ it matches the glob() routine.
+ * runtest.c Makefile.am: first steps toward a C regression test
+ framework.
+
Sat Jun 25 01:37:22 PDT 2005 William Brack <wbrack@mmm.com.hk>
* configure.in: fixed a problem with the detection of
diff --git a/Makefile.am b/Makefile.am
index 8c0fdfe..447a59b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,7 +8,7 @@
noinst_PROGRAMS=testSchemas testRelax testSAX testHTML testXPath testURI \
testThreads testC14N testAutomata testRegexp \
- testReader testapi testModule
+ testReader testapi testModule runtest
bin_PROGRAMS = xmllint xmlcatalog
@@ -49,6 +49,11 @@
m4datadir = $(datadir)/aclocal
m4data_DATA = libxml.m4
+runtest_SOURCES=runtest.c
+runtest_LDFLAGS =
+runtest_DEPENDENCIES = $(DEPS)
+runtest_LDADD= @RDL_LIBS@ $(LDADDS)
+
xmllint_SOURCES=xmllint.c
xmllint_LDFLAGS =
xmllint_DEPENDENCIES = $(DEPS)
diff --git a/include/libxml/valid.h b/include/libxml/valid.h
index 2e0ec3d..86e3fce 100644
--- a/include/libxml/valid.h
+++ b/include/libxml/valid.h
@@ -195,13 +195,13 @@
xmlSnprintfElementContent(char *buf,
int size,
xmlElementContentPtr content,
- int glob);
+ int englob);
#ifdef LIBXML_OUTPUT_ENABLED
/* DEPRECATED */
XMLPUBFUN void XMLCALL
xmlSprintfElementContent(char *buf,
xmlElementContentPtr content,
- int glob);
+ int englob);
#endif /* LIBXML_OUTPUT_ENABLED */
/* DEPRECATED */
diff --git a/runtest.c b/runtest.c
new file mode 100644
index 0000000..ef40f37
--- /dev/null
+++ b/runtest.c
@@ -0,0 +1,451 @@
+/*
+ * runtest.c: C program to run libxml2 regression tests without
+ * requiring make or Python, and reducing platform dependancies
+ * to a strict minimum.
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <glob.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+typedef int (*functest) (const char *filename, const char *result);
+
+typedef struct testDesc testDesc;
+typedef testDesc *testDescPtr;
+struct testDesc {
+ const char *desc; /* descripton of the test */
+ functest func; /* function implementing the test */
+ const char *in; /* glob to path for input files */
+ const char *out; /* output directory */
+ const char *suffix;/* suffix for output files */
+};
+
+static int checkTestFile(const char *filename);
+/************************************************************************
+ * *
+ * Libxml2 specific routines *
+ * *
+ ************************************************************************/
+
+static long libxmlMemoryAllocatedBase = 0;
+static int extraMemoryFromResolver = 0;
+
+static int
+fatalError(void) {
+ fprintf(stderr, "Exitting tests on fatal error\n");
+ exit(1);
+}
+
+/*
+ * We need to trap calls to the resolver to not account memory for the catalog
+ * which is shared to the current running test. We also don't want to have
+ * network downloads modifying tests.
+ */
+static xmlParserInputPtr
+testExternalEntityLoader(const char *URL, const char *ID,
+ xmlParserCtxtPtr ctxt) {
+ xmlParserInputPtr ret;
+
+ if (checkTestFile(URL)) {
+ ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+ } else {
+ int memused = xmlMemUsed();
+ ret = xmlNoNetExternalEntityLoader(URL, ID, ctxt);
+ extraMemoryFromResolver += xmlMemUsed() - memused;
+ }
+
+ return(ret);
+}
+
+static void
+initializeLibxml2(void) {
+ xmlGetWarningsDefaultValue = 0;
+ xmlPedanticParserDefault(0);
+
+ xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup);
+ xmlInitParser();
+ xmlSetExternalEntityLoader(testExternalEntityLoader);
+ libxmlMemoryAllocatedBase = xmlMemUsed();
+}
+
+
+/************************************************************************
+ * *
+ * File name and path utilities *
+ * *
+ ************************************************************************/
+
+static const char *baseFilename(const char *filename) {
+ const char *cur;
+ if (filename == NULL)
+ return(NULL);
+ cur = &filename[strlen(filename)];
+ while ((cur > filename) && (*cur != '/'))
+ cur--;
+ if (*cur == '/')
+ return(cur + 1);
+ return(cur);
+}
+
+static char *resultFilename(const char *filename, const char *out,
+ const char *suffix) {
+ const char *base;
+ char res[500];
+
+/*************
+ if ((filename[0] == 't') && (filename[1] == 'e') &&
+ (filename[2] == 's') && (filename[3] == 't') &&
+ (filename[4] == '/'))
+ filename = &filename[5];
+ *************/
+
+ base = baseFilename(filename);
+ if (suffix == NULL)
+ suffix = ".tmp";
+ if (out == NULL)
+ out = "";
+ snprintf(res, 499, "%s%s%s", out, base, suffix);
+ res[499] = 0;
+ return(strdup(res));
+}
+
+static int checkTestFile(const char *filename) {
+ struct stat buf;
+
+ if (stat(filename, &buf) == -1)
+ return(0);
+
+ if (!S_ISREG(buf.st_mode))
+ return(0);
+
+ return(1);
+}
+
+static int compareFiles(const char *r1, const char *r2) {
+ int res1, res2;
+ int fd1, fd2;
+ char bytes1[4096];
+ char bytes2[4096];
+
+ fd1 = open(r1, O_RDONLY);
+ if (fd1 < 0)
+ return(-1);
+ fd2 = open(r2, O_RDONLY);
+ if (fd2 < 0) {
+ close(fd1);
+ return(-1);
+ }
+ while (1) {
+ res1 = read(fd1, bytes1, 4096);
+ res2 = read(fd2, bytes2, 4096);
+ if (res1 != res2) {
+ close(fd1);
+ close(fd2);
+ return(1);
+ }
+ if (res1 == 0)
+ break;
+ if (memcmp(bytes1, bytes2, res1) != 0) {
+ close(fd1);
+ close(fd2);
+ return(1);
+ }
+ }
+ close(fd1);
+ close(fd2);
+ return(0);
+}
+
+static int loadMem(const char *filename, const char **mem, int *size) {
+ int fd, res;
+ struct stat info;
+ char *base;
+ int siz = 0;
+ if (stat(filename, &info) < 0)
+ return(-1);
+ base = malloc(info.st_size + 1);
+ if (base == NULL)
+ return(-1);
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+ free(base);
+ return(-1);
+ }
+ while ((res = read(fd, &base[siz], info.st_size - siz)) > 0) {
+ siz += res;
+ }
+ close(fd);
+ if (siz != info.st_size) {
+ free(base);
+ return(-1);
+ }
+ base[siz] = 0;
+ *mem = base;
+ *size = siz;
+ return(0);
+}
+
+static int unloadMem(const char *mem) {
+ free((char *)mem);
+ return(0);
+}
+
+/************************************************************************
+ * *
+ * Tests implementations *
+ * *
+ ************************************************************************/
+
+/**
+ * oldParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ *
+ * Parse a file using the old xmlParseFile API, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+oldParseTest(const char *filename, const char *result) {
+ xmlDocPtr doc;
+ char *temp;
+ int res = 0;
+
+ /*
+ * base of the test, parse with the old API
+ */
+ doc = xmlParseFile(filename);
+ if (doc == NULL)
+ return(1);
+ temp = resultFilename(filename, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ fatalError();
+ }
+ xmlSaveFile(temp, doc);
+ if (compareFiles(temp, result)) {
+ res = 1;
+ }
+ xmlFreeDoc(doc);
+
+ /*
+ * Parse the saved result to make sure the round trip is okay
+ */
+ doc = xmlParseFile(temp);
+ if (doc == NULL)
+ return(1);
+ xmlSaveFile(temp, doc);
+ if (compareFiles(temp, result)) {
+ res = 1;
+ }
+ xmlFreeDoc(doc);
+
+ unlink(temp);
+ free(temp);
+ return(res);
+}
+
+/**
+ * memParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ *
+ * Parse a file using the old xmlReadMemory API, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+memParseTest(const char *filename, const char *result) {
+ xmlDocPtr doc;
+ const char *base;
+ int size;
+ const char *base2;
+ int size2;
+
+ /*
+ * load and parse the memory
+ */
+ if (loadMem(filename, &base, &size) != 0) {
+ fprintf(stderr, "Failed to load %s\n", filename);
+ return(-1);
+ }
+
+ doc = xmlReadMemory(base, size, filename, NULL, 0);
+ unloadMem(base);
+ if (doc == NULL) {
+ return(1);
+ }
+ if (loadMem(result, &base, &size) != 0) {
+ fprintf(stderr, "Failed to load %s\n", result);
+ return(-1);
+ }
+ xmlDocDumpMemory(doc, (xmlChar **) &base2, &size2);
+ xmlFreeDoc(doc);
+ if ((base2 == NULL) || (size != size2) ||
+ (memcmp(base, base2, size) != 0)) {
+ unloadMem(base);
+ if (base2 != NULL)
+ xmlFree((char *)base2);
+ fprintf(stderr, "Result for %s failed\n", filename);
+ return(-1);
+ }
+ unloadMem(base);
+ xmlFree((char *)base2);
+ return(0);
+}
+
+/**
+ * noentParseTest:
+ * @filename: the file to parse
+ * @result: the file with expected result
+ *
+ * Parse a file with entity resolution, then serialize back
+ * reparse the result and serialize again, then check for deviation
+ * in serialization.
+ *
+ * Returns 0 in case of success, an error code otherwise
+ */
+static int
+noentParseTest(const char *filename, const char *result) {
+ xmlDocPtr doc;
+ char *temp;
+ int res = 0;
+
+ /*
+ * base of the test, parse with the old API
+ */
+ doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT);
+ if (doc == NULL)
+ return(1);
+ temp = resultFilename(filename, "", ".res");
+ if (temp == NULL) {
+ fprintf(stderr, "Out of memory\n");
+ fatalError();
+ }
+ xmlSaveFile(temp, doc);
+ if (compareFiles(temp, result)) {
+ res = 1;
+ }
+ xmlFreeDoc(doc);
+
+ /*
+ * Parse the saved result to make sure the round trip is okay
+ */
+ doc = xmlReadFile(filename, NULL, XML_PARSE_NOENT);
+ if (doc == NULL)
+ return(1);
+ xmlSaveFile(temp, doc);
+ if (compareFiles(temp, result)) {
+ res = 1;
+ }
+ xmlFreeDoc(doc);
+
+ unlink(temp);
+ free(temp);
+ return(res);
+}
+
+/************************************************************************
+ * *
+ * Tests Descriptions *
+ * *
+ ************************************************************************/
+
+static
+testDesc testDescriptions[] = {
+ { "XML regression tests" , oldParseTest, "test/*", "result/", "" },
+ { "XML regression tests on memory" , memParseTest, "test/*", "result/", "" },
+ { "XML entity subst regression tests" , noentParseTest, "test/*", "result/noent/", "" },
+ {NULL, NULL, NULL, NULL, NULL}
+};
+
+/************************************************************************
+ * *
+ * The main driving the tests *
+ * *
+ ************************************************************************/
+
+static int
+launchTests(testDescPtr tst) {
+ int res = 0, err = 0;
+ size_t i;
+ char *result;
+ int mem, leak;
+
+ if (tst == NULL) return(-1);
+ if (tst->in != NULL) {
+ glob_t globbuf;
+
+ globbuf.gl_offs = 0;
+ glob(tst->in, GLOB_DOOFFS, NULL, &globbuf);
+ for (i = 0;i < globbuf.gl_pathc;i++) {
+ if (!checkTestFile(globbuf.gl_pathv[i]))
+ continue;
+ result = resultFilename(globbuf.gl_pathv[i], tst->out, tst->suffix);
+ if (result == NULL) {
+ fprintf(stderr, "Out of memory !\n");
+ fatalError();
+ }
+ if (!checkTestFile(result)) {
+ fprintf(stderr, "Missing result file %s\n", result);
+ } else {
+ mem = xmlMemUsed();
+ extraMemoryFromResolver = 0;
+ res = tst->func(globbuf.gl_pathv[i], result);
+ if (res != 0) {
+ fprintf(stderr, "File %s generated an error\n",
+ globbuf.gl_pathv[i]);
+ err++;
+ }
+ else if (xmlMemUsed() != mem) {
+ if (extraMemoryFromResolver == 0) {
+ fprintf(stderr, "File %s leaked %d bytes\n",
+ globbuf.gl_pathv[i], xmlMemUsed() - mem);
+ leak++;
+ err++;
+ }
+ }
+ }
+ free(result);
+ }
+ } else {
+ res = tst->func(NULL, NULL);
+ if (res != 0)
+ err++;
+ }
+ return(err);
+}
+
+int
+main(int argc, char **argv) {
+ int i = 0, res, ret = 0;
+
+ initializeLibxml2();
+
+ for (i = 0; testDescriptions[i].func != NULL; i++) {
+ if (testDescriptions[i].desc != NULL)
+ printf("## %s\n", testDescriptions[i].desc);
+ res = launchTests(&testDescriptions[i]);
+ if (res != 0)
+ ret++;
+ }
+ xmlCleanupParser();
+ xmlMemoryDump();
+
+ return(ret);
+}
diff --git a/valid.c b/valid.c
index f9daada..f1d0db4 100644
--- a/valid.c
+++ b/valid.c
@@ -1212,14 +1212,14 @@
* xmlSprintfElementContent:
* @buf: an output buffer
* @content: An element table
- * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
+ * @englob: 1 if one must print the englobing parenthesis, 0 otherwise
*
* Deprecated, unsafe, use xmlSnprintfElementContent
*/
void
xmlSprintfElementContent(char *buf ATTRIBUTE_UNUSED,
xmlElementContentPtr content ATTRIBUTE_UNUSED,
- int glob ATTRIBUTE_UNUSED) {
+ int englob ATTRIBUTE_UNUSED) {
}
#endif /* LIBXML_OUTPUT_ENABLED */
@@ -1228,13 +1228,13 @@
* @buf: an output buffer
* @size: the buffer size
* @content: An element table
- * @glob: 1 if one must print the englobing parenthesis, 0 otherwise
+ * @englob: 1 if one must print the englobing parenthesis, 0 otherwise
*
* This will dump the content of the element content definition
* Intended just for the debug routine
*/
void
-xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int glob) {
+xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int englob) {
int len;
if (content == NULL) return;
@@ -1244,7 +1244,7 @@
strcat(buf, " ...");
return;
}
- if (glob) strcat(buf, "(");
+ if (englob) strcat(buf, "(");
switch (content->type) {
case XML_ELEMENT_CONTENT_PCDATA:
strcat(buf, "#PCDATA");
@@ -1306,7 +1306,7 @@
xmlSnprintfElementContent(buf, size, content->c2, 0);
break;
}
- if (glob)
+ if (englob)
strcat(buf, ")");
switch (content->ocur) {
case XML_ELEMENT_CONTENT_ONCE: