[yocto] [ptest-runner][PATCHv2 2/2] Add xml output
Pascal Bach
pascal.bach at siemens.com
Wed Feb 1 07:42:41 PST 2017
The format follow the one defined in the Yocto wiki:
https://wiki.yoctoproject.org/wiki/QA/xUnit_XML_Template
It is only the minimum required but it can be extended in the future.
Signed-off-by: Schuler Christian <schuler.christian at siemens.com>
Signed-off-by: Pascal Bach <pascal.bach at siemens.com>
---
README.md | 1 +
main.c | 13 ++++++++++---
tests/data/reference.xml | 8 ++++++++
tests/utils.c | 46 ++++++++++++++++++++++++++++++++++++++++++++
utils.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++
utils.h | 10 ++++++++--
6 files changed, 123 insertions(+), 5 deletions(-)
create mode 100644 tests/data/reference.xml
diff --git a/README.md b/README.md
index ed7a589..fedab04 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,7 @@ Now the ptest-runner2 support the next features:
- List available ptests.
- Specify the timeout for avoid blocking indefinetly.
- Only run certain ptests.
+- XML-ouput
Proposed features:
diff --git a/main.c b/main.c
index 765d688..5f37541 100644
--- a/main.c
+++ b/main.c
@@ -41,7 +41,7 @@
static inline void
print_usage(FILE *stream, char *progname)
{
- fprintf(stream, "Usage: %s [-d directory] [-l list] [-t timeout] "
+ fprintf(stream, "Usage: %s [-d directory] [-l list] [-t timeout] [-x xml-filename]"
"[-h] [ptest1 ptest2 ...]\n", progname);
}
@@ -60,12 +60,14 @@ main(int argc, char *argv[])
struct ptest_list *head, *run;
struct options opts;
+
opts.directory = strdup(DEFAULT_DIRECTORY);
opts.list = 0;
opts.timeout = DEFAULT_TIMEOUT;
opts.ptests = NULL;
+ opts.xml_filename = NULL;
- while ((opt = getopt(argc, argv, "d:lt:h")) != -1) {
+ while ((opt = getopt(argc, argv, "d:ltx:h")) != -1) {
switch (opt) {
case 'd':
free(opts.directory);
@@ -82,6 +84,11 @@ main(int argc, char *argv[])
print_usage(stdout, argv[0]);
exit(0);
break;
+ case 'x':
+ free(opts.xml_filename);
+ opts.xml_filename = strdup(optarg);
+ CHECK_ALLOCATION(opts.xml_filename, 1, 1);
+ break;
default:
print_usage(stdout, argv[0]);
exit(1);
@@ -125,7 +132,7 @@ main(int argc, char *argv[])
run = filter_ptests(head, opts.ptests, ptest_num);
CHECK_ALLOCATION(run, ptest_num, 1);
ptest_list_free_all(head);
- }
+ }
rc = run_ptests(run, opts, argv[0], stdout, stderr);
diff --git a/tests/data/reference.xml b/tests/data/reference.xml
new file mode 100644
index 0000000..0d858e1
--- /dev/null
+++ b/tests/data/reference.xml
@@ -0,0 +1,8 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<testsuite name='ptest' tests='2'>
+<testcase classname='test1' name='run-ptest'>
+</testcase>
+<testcase classname='test2' name='run-ptest'>
+<failure type='exit_code' message='run-ptest exited with code: 1'></failure>
+</testcase>
+</testsuite>
diff --git a/tests/utils.c b/tests/utils.c
index 6b70c2e..f5d3b62 100644
--- a/tests/utils.c
+++ b/tests/utils.c
@@ -237,6 +237,50 @@ START_TEST(test_run_fail_ptest)
ptest_list_free_all(head);
END_TEST
+int filecmp(FILE *fp1, FILE *fp2)
+{
+ char f1, f2;
+ while (1) {
+ int end = 0;
+ if ((f1 = getc(fp1)) == EOF) end++;
+ if ((f2 = getc(fp2)) == EOF) end++;
+
+ if (end == 2) return 0;
+ if (end == 1) return 1;
+ if (f1 != f2) return 2;
+ }
+}
+
+START_TEST(test_xml_pass)
+
+
+
+ XML *xp;
+ xp = xml_create(2, "./test.xml");
+ ck_assert(xp != NULL);
+ xml_add_case(xp, 0,"test1");
+ xml_add_case(xp, 1,"test2");
+ xml_finish(xp);
+
+ FILE *fp, *fr;
+ fr = fopen("./tests/data/reference.xml", "r");
+ ck_assert(fr != NULL);
+ fp = fopen("./test.xml", "r");
+ ck_assert(fp != NULL);
+
+ ck_assert(filecmp(fr, fp) == 0);
+
+ fclose(fr);
+ fclose(fp);
+ unlink("./test.xml");
+
+END_TEST
+
+START_TEST(test_xml_fail)
+ ck_assert(xml_create(2, "./") == NULL);
+
+END_TEST
+
Suite *
utils_suite()
{
@@ -252,6 +296,8 @@ utils_suite()
tcase_add_test(tc_core, test_run_ptests);
tcase_add_test(tc_core, test_run_timeout_ptest);
tcase_add_test(tc_core, test_run_fail_ptest);
+ tcase_add_test(tc_core, test_xml_pass);
+ tcase_add_test(tc_core, test_xml_fail);
suite_add_tcase(s, tc_core);
diff --git a/utils.c b/utils.c
index 48c1990..0fb6ff8 100644
--- a/utils.c
+++ b/utils.c
@@ -306,6 +306,7 @@ run_ptests(struct ptest_list *head, const struct options opts, const char *progn
FILE *fp, FILE *fp_stderr)
{
int rc = 0;
+ XML *xh;
struct ptest_list *p;
char stime[GET_STIME_BUF_SIZE];
@@ -314,6 +315,12 @@ run_ptests(struct ptest_list *head, const struct options opts, const char *progn
int pipefd_stdout[2];
int pipefd_stderr[2];
+ if(opts.xml_filename) {
+ xh = xml_create(ptest_list_length(head), opts.xml_filename);
+ if(!xh)
+ exit(EXIT_FAILURE);
+ }
+
do
{
if ((rc = pipe2(pipefd_stdout, O_NONBLOCK)) == -1)
@@ -355,6 +362,9 @@ run_ptests(struct ptest_list *head, const struct options opts, const char *progn
fprintf(fp, "ERROR: Exit status is %d\n", status);
rc += 1;
}
+ if (opts.xml_filename)
+ xml_add_case(xh, status, ptest_dir);
+
fprintf(fp, "END: %s\n", ptest_dir);
fprintf(fp, "%s\n", get_stime(stime, GET_STIME_BUF_SIZE));
}
@@ -368,5 +378,45 @@ run_ptests(struct ptest_list *head, const struct options opts, const char *progn
if (rc == -1)
fprintf(fp_stderr, "run_ptests fails: %s", strerror(errno));
+ if (opts.xml_filename)
+ xml_finish(xh);
+
return rc;
}
+
+FILE *
+xml_create(int test_count, char *xml_filename)
+{
+ FILE *xh;
+
+ if ((xh = fopen(xml_filename, "w"))) {
+ fprintf(xh, "<?xml version='1.0' encoding='UTF-8'?>\n");
+ fprintf(xh, "<testsuite name='ptest' tests='%d'>\n", test_count);
+ }
+ else {
+ fprintf(stderr, "File could not be created. Make sure the path is correct and you have the right permissions.");
+ return NULL;
+ }
+
+ return xh;
+}
+
+void
+xml_add_case(FILE *xh, int status, const char *ptest_dir)
+{
+ fprintf(xh, "<testcase classname='%s' name='run-ptest'>\n", ptest_dir);
+
+ if(status != 0){
+ fprintf(xh, "<failure type='exit_code'");
+ fprintf(xh, " message='run-ptest exited with code: %d'>", status);
+ fprintf(xh, "</failure>\n");
+ }
+ fprintf(xh, "</testcase>\n");
+}
+
+void
+xml_finish(FILE *xh)
+{
+ fprintf(xh, "</testsuite>\n");
+ fclose(xh);
+}
diff --git a/utils.h b/utils.h
index d7f5268..7a8956a 100644
--- a/utils.h
+++ b/utils.h
@@ -33,14 +33,20 @@
struct options {
char *directory;
int list;
- int timeout;
- char **ptests;
+ int timeout;
+ char **ptests;
+ char * xml_filename;
};
+typedef FILE XML;
+
extern void check_allocation1(void *, size_t, char *, int, int);
extern struct ptest_list *get_available_ptests(const char *);
extern int print_ptests(struct ptest_list *, FILE *);
extern struct ptest_list *filter_ptests(struct ptest_list *, char **, int);
extern int run_ptests(struct ptest_list *, const struct options, const char *progname, FILE *, FILE *);
+extern XML * xml_create(int test_count, char *filename);
+extern void xml_add_case(XML *, int status, const char *ptest_dir);
+extern void xml_finish(XML *);
#endif
--
2.1.4
More information about the yocto
mailing list