* Introduce a maximum number of concurrent ptests, since
we are dealing with embedded targets.

* Add stdout || stderr output from ptests into XML.
For testcases running in parallel, cluttering stdout won't
help anyone.

Signed-off-by: Jiwei Sun <[email protected]>
---
 main.c                   |  2 +
 tests/data/reference.xml |  1 +
 tests/utils.c            |  4 +-
 utils.c                  | 99 +++++++++++++++++++++++++++++-------------------
 utils.h                  |  3 +-
 5 files changed, 67 insertions(+), 42 deletions(-)

diff --git a/main.c b/main.c
index d524200..a201e87 100644
--- a/main.c
+++ b/main.c
@@ -37,6 +37,7 @@
 
 #define DEFAULT_DIRECTORY "/usr/lib"
 #define DEFAULT_TIMEOUT 300
+#define DEFAULT_MAX_PARALLEL 64
 
 static inline void
 print_usage(FILE *stream, char *progname)
@@ -69,6 +70,7 @@ main(int argc, char *argv[])
        opts.directory = strdup(DEFAULT_DIRECTORY);
        opts.list = 0;
        opts.timeout = DEFAULT_TIMEOUT;
+       opts.max_parallel = DEFAULT_MAX_PARALLEL;
        opts.ptests = NULL;
        opts.xml_filename = NULL;
 
diff --git a/tests/data/reference.xml b/tests/data/reference.xml
index 91522c7..a23b44b 100644
--- a/tests/data/reference.xml
+++ b/tests/data/reference.xml
@@ -4,5 +4,6 @@
        </testcase>
        <testcase classname='test2' name='run-ptest'>
                <failure type='exit_code' message='run-ptest exited with code: 
1'></failure>
+               <system-out>ERROR</system-out>
        </testcase>
 </testsuite>
diff --git a/tests/utils.c b/tests/utils.c
index 9b1f442..bb799f4 100644
--- a/tests/utils.c
+++ b/tests/utils.c
@@ -262,9 +262,9 @@ START_TEST(test_xml_pass)
        ck_assert(xp != NULL);
         entry.ptest = "test1";
         entry.run_ptest = "run-ptest";
-       xml_add_case(xp, 0, &entry);
+        xml_add_case(xp, 0, &entry, "");
         entry.ptest = "test2";
-        xml_add_case(xp, 1, &entry);
+        xml_add_case(xp, 1, &entry, "ERROR");
        xml_finish(xp);
 
        FILE *fp, *fr;
diff --git a/utils.c b/utils.c
index 056d7b7..0e97ac4 100644
--- a/utils.c
+++ b/utils.c
@@ -289,8 +289,13 @@ run_child(char *run_ptest, int fd_stdout, int fd_stderr)
 }
 
 static inline int
-wait_child(const char *ptest_dir, const char *run_ptest, pid_t pid,
-               int timeout, int *fds, FILE **fps)
+wait_child(const char *ptest_dir,
+          const char *run_ptest,
+          pid_t pid,
+          int timeout,
+          int *fds,
+          FILE **fps,
+          char *buf)
 {
        struct pollfd pfds[2];
        time_t sentinel;
@@ -311,7 +316,6 @@ wait_child(const char *ptest_dir, const char *run_ptest, 
pid_t pid,
 
                r = poll(pfds, 2, WAIT_CHILD_POLL_TIMEOUT_MS);
                if (r > 0) {
-                       char buf[WAIT_CHILD_BUF_MAX_SIZE];
                        ssize_t n;
 
                        if (pfds[0].revents != 0) {
@@ -354,6 +358,35 @@ wait_child(const char *ptest_dir, const char *run_ptest, 
pid_t pid,
        return status;
 }
 
+static void reap_all_children(FILE *fp) {
+       /* Reap all children before continuing */
+       while (1) {
+               int status;
+               pid_t pid;
+               pid = waitpid((pid_t)(-1), &status, WNOHANG);
+
+               /* Child reaped */
+               if (pid > 0) {
+                       if (WIFEXITED(status)) {
+                               if (WEXITSTATUS(status) == 0)
+                                       continue;
+                       }
+                       fprintf(fp, "One child failed to do its job pid:%u", 
pid);
+                       exit(-1);
+               }
+
+               /* Still children alive */
+               if (pid == 0) {
+                       usleep(100000); /* 100ms */
+                       continue;
+               }
+
+               /* No more children to reap */
+               if (pid < 0)
+                       break;
+       }
+}
+
 int
 run_ptests(struct ptest_list *head, const struct ptest_options opts,
                const char *progname, FILE *fp, FILE *fp_stderr)
@@ -363,8 +396,8 @@ run_ptests(struct ptest_list *head, const struct 
ptest_options opts,
 
        struct ptest_list *p;
        char stime[GET_STIME_BUF_SIZE];
-
-       pid_t child, pid;
+       int nr_children = 0;
+       pid_t child;
        int pipefd_stdout[2];
        int pipefd_stderr[2];
 
@@ -395,8 +428,13 @@ run_ptests(struct ptest_list *head, const struct 
ptest_options opts,
                                continue;
 
                        master = fork();
-                       if (master)
+                       if (master) {
+                               if (++nr_children >= opts.max_parallel) {
+                                       reap_all_children(fp);
+                                       nr_children = 0;
+                               }
                                continue;
+                       }
 
                        ptest_dir = strdup(p->run_ptest);
                        if (ptest_dir == NULL) {
@@ -416,53 +454,30 @@ run_ptests(struct ptest_list *head, const struct 
ptest_options opts,
                                int status;
                                int fds[2]; fds[0] = pipefd_stdout[0]; fds[1] = 
pipefd_stderr[0];
                                FILE *fps[2]; fps[0] = fp; fps[1] = fp_stderr;
+                               char buf[WAIT_CHILD_BUF_MAX_SIZE];
 
 //                             fprintf(fp, "%s\n", get_stime(stime, 
GET_STIME_BUF_SIZE));
                                fprintf(fp, "BEGIN: %s\n", ptest_dir);
 
                                status = wait_child(ptest_dir, p->run_ptest, 
child,
-                                               opts.timeout, fds, fps);
+                                                   opts.timeout, fds, fps, 
buf);
                                if (status)
                                        rc += 1;
 
                                if (opts.xml_filename)
                                        xml_add_case(xh,
                                                     status,
-                                                    (struct ptest_entry *)p);
+                                                    (struct ptest_entry *)p,
+                                                    buf);
 
-//                             fprintf(fp, "END: %s\n", ptest_dir);
 //                             fprintf(fp, "%s\n", get_stime(stime, 
GET_STIME_BUF_SIZE));
                                /* Let non-master gracefully terminate */
                                exit(0);
                        }
                PTEST_LIST_ITERATE_END;
 
-               /* Reap all children before continuing */
-               while (1) {
-                       int status;
-                       pid = waitpid((pid_t)(-1), &status, WNOHANG);
-
-                       /* Child reaped */
-                       if (pid > 0) {
-                               if (WIFEXITED(status)) {
-                                       if (WEXITSTATUS(status) == 0)
-                                               continue;
-                               }
-                               fprintf(fp, "One child failed to do its job 
pid:%u", pid);
-                               exit(-1);
-                       }
-
-                       /* Still children alive */
-                       if (pid == 0) {
-                               usleep(100000); /* 100ms */
-                               continue;
-                       }
-
-                       /* No more children to reap */
-                       if (pid < 0)
-                               break;
-               }
-
+               reap_all_children(fp);
+               
                fprintf(fp, "START: %s\n", progname);
                PTEST_LIST_ITERATE_START(head, p);
                        char *ptest_dir;
@@ -487,19 +502,22 @@ run_ptests(struct ptest_list *head, const struct 
ptest_options opts,
                                int status;
                                int fds[2]; fds[0] = pipefd_stdout[0]; fds[1] = 
pipefd_stderr[0];
                                FILE *fps[2]; fps[0] = fp; fps[1] = fp_stderr;
+                               char buf[WAIT_CHILD_BUF_MAX_SIZE];
 
+                               memset(buf, 0, sizeof(buf));
                                fprintf(fp, "%s\n", get_stime(stime, 
GET_STIME_BUF_SIZE));
                                fprintf(fp, "BEGIN: %s\n", ptest_dir);
 
                                status = wait_child(ptest_dir, p->run_ptest, 
child,
-                                               opts.timeout, fds, fps);
+                                                   opts.timeout, fds, fps, 
buf);
                                if (status)
                                        rc += 1;
 
                                if (opts.xml_filename)
                                        xml_add_case(xh,
                                                     status,
-                                                    (struct ptest_entry *)p);
+                                                    (struct ptest_entry *)p,
+                                                    buf);
 
                                fprintf(fp, "END: %s\n", ptest_dir);
                                fprintf(fp, "%s\n", get_stime(stime, 
GET_STIME_BUF_SIZE));
@@ -538,7 +556,7 @@ xml_create(int test_count, char *xml_filename)
 }
 
 void
-xml_add_case(FILE *xh, int status, struct ptest_entry *ptest)
+xml_add_case(FILE *xh, int status, struct ptest_entry *ptest, char *buf)
 {
        struct flock lock;
        int fd;
@@ -556,10 +574,13 @@ xml_add_case(FILE *xh, int status, struct ptest_entry 
*ptest)
                        "\t\t<failure type='exit_code'" \
                        " message='run-ptest exited with code: %d'>" \
                        "</failure>\n" \
+                       "\t\t<system-out>%s" \
+                       "</system-out>\n" \
                        "\t</testcase>\n",
                        ptest->ptest,
                        basename(bname),
-                       status);
+                       status,
+                       buf);
        }
        else {
                fprintf(xh, "\t<testcase classname='%s' name='%s'>\n" \
diff --git a/utils.h b/utils.h
index d0ef735..70e2abe 100644
--- a/utils.h
+++ b/utils.h
@@ -34,6 +34,7 @@ struct ptest_options {
        char *directory;
        int list;
        int timeout;
+       int max_parallel;
        char **ptests;
        char *xml_filename;
 };
@@ -47,7 +48,7 @@ extern int run_ptests(struct ptest_list *, const struct 
ptest_options,
                const char *, FILE *, FILE *);
 
 extern FILE *xml_create(int, char *);
-extern void xml_add_case(FILE *, int, struct ptest_entry *);
+extern void xml_add_case(FILE *, int, struct ptest_entry *, char *);
 extern void xml_finish(FILE *);
 
 #endif
-- 
1.8.3.1

-- 
_______________________________________________
yocto mailing list
[email protected]
https://lists.yoctoproject.org/listinfo/yocto

Reply via email to