From: gilles.carry <[EMAIL PROTECTED]>

This patch is to allow user to have results and statistics dumped
as XML files.
This patch does not alter the LTP/RT traditional data dump.
A new global command line option is used: -x <id>
Using this option makes results to be dumped as XML files if the test
implements it.
Combining '-s -x' dumps stats both in traditionnal format and XML format
(into separate files).
The main goal here is to have the ability to store and compare results
and stats of testruns for different configurations and architectures.
The XML files created, not only store stats data but also system information
and timestamps, useful to identify how the test was run.
The choice of XML allows future format modifications while still being
able to compare old and new dumps.
---
 testcases/realtime/include/librttest.h |    1 +
 testcases/realtime/include/libstats.h  |   20 +++
 testcases/realtime/lib/librttest.c     |   33 +++++-
 testcases/realtime/lib/libstats.c      |  210 +++++++++++++++++++++++---------
 4 files changed, 208 insertions(+), 56 deletions(-)

diff --git a/testcases/realtime/include/librttest.h 
b/testcases/realtime/include/librttest.h
index bb30ee7..3c41046 100644
--- a/testcases/realtime/include/librttest.h
+++ b/testcases/realtime/include/librttest.h
@@ -131,6 +131,7 @@ extern char * _print_buffer;
 extern int _print_buffer_offset;
 extern int _dbg_lvl;
 extern double pass_criteria;
+extern char testrun_start_time[200];
 
 /* function prototypes */
 
diff --git a/testcases/realtime/include/libstats.h 
b/testcases/realtime/include/libstats.h
index 05c26d8..abf9882 100644
--- a/testcases/realtime/include/libstats.h
+++ b/testcases/realtime/include/libstats.h
@@ -72,6 +72,9 @@ typedef struct stats_quantiles {
 } stats_quantiles_t;
 
 extern int save_stats;
+extern int xml_dump;
+extern char *test_name;
+extern char *kernel_dev_id;
 
 /* function prototypes */
 
@@ -162,4 +165,21 @@ void stats_hist_print(stats_container_t *hist);
  */
 int stats_container_save(char *filename, char *title, char *labelx, char 
*labely, stats_container_t *data, char *mode);
 
+/* xml_dump_init - create an xml dump file and add all necessary headers
+ * or xml markups (start time, uname...) to identify the test
+ * filename: the filename to save the data. File will actually be named:
+ *     <filename>.<timestamp>.xml
+ * root_mrkup: the name of the root xml markup
+ * title: the test title
+ * Returns: the descriptor of the file to write into
+ */
+FILE * xml_dump_init(char *filename, char *root_mrkup, char *title);
+
+/* xml_dump_close - add all necessary footer xml markups and close
+ * the file.
+ * dat_fd: the descriptor of the file to close
+ * root_mrkup: the name of the root xml markup
+ */
+void xml_dump_close(FILE *dat_fd, char *root_mrkup);
+
 #endif /* LIBSTAT_H */
diff --git a/testcases/realtime/lib/librttest.c 
b/testcases/realtime/lib/librttest.c
index c82fb95..61cb983 100644
--- a/testcases/realtime/lib/librttest.c
+++ b/testcases/realtime/lib/librttest.c
@@ -68,6 +68,7 @@ char * _print_buffer = NULL;
 int _print_buffer_offset = 0;
 int _dbg_lvl = 0;
 double pass_criteria;
+char testrun_start_time[200];
 
 static int _use_pi = 1;
 
@@ -79,9 +80,30 @@ void rt_help(void)
        printf("  -p(0,1)       0:don't use pi mutexes, 1:use pi mutexes\n");
        printf("  -v[0-4]       0:no debug, 1:DBG_ERR, 2:DBG_WARN, 3:DBG_INFO, 
4:DBG_DEBUG\n");
        printf("  -s            Enable saving stats data (default disabled)\n");
+       printf("  -x <kernel_dev_id>    Enable saving of stats as xml data 
(default disabled)\n");
+       printf("                kernel_dev_id (mandatory arg) string inserted 
into xml dump\n");
        printf("  -c            Set pass criteria\n");
 }
 
+void set_start_time(void) {
+       time_t t;
+       struct tm *tmp;
+
+       t = time(NULL);
+       tmp = localtime(&t);
+       if (tmp == NULL) {
+               perror("localtime");
+               exit(EXIT_FAILURE);
+       }
+
+       if (strftime(testrun_start_time, sizeof(testrun_start_time), 
"%Y-%m-%d-%H-%M-%S", tmp) == 0) {
+               fprintf(stderr, "strftime returned 0");
+               exit(EXIT_FAILURE);
+       }
+
+       printf("Test start time:\"%s\"\n", testrun_start_time);
+}
+
 int rt_init(const char *options, int (*parse_arg)(int option, char *value), 
int argc, char *argv[])
 {
        int use_buffer = 1;
@@ -89,7 +111,7 @@ int rt_init(const char *options, int (*parse_arg)(int 
option, char *value), int
        int c;
        opterr = 0;
        char *all_options, *opt_ptr;
-       static const char my_options[] = "b:p:v:sc:";
+       static const char my_options[] = "b:p:v:sx:c:";
 
        if (options) {
                opt_ptr = all_options = (char *)malloc(sizeof(my_options) + 
strlen(options) + 1);
@@ -127,6 +149,12 @@ int rt_init(const char *options, int (*parse_arg)(int 
option, char *value), int
                        case 's':
                                save_stats = 1;
                                break;
+                       case 'x':
+                               xml_dump = 1;
+                               kernel_dev_id = optarg;
+                               if (!strcmp("", kernel_dev_id))
+                                       return -1;
+                               break;
                        default:
                                if (parse_arg) {
                                        if (!parse_arg(c, optarg)) {
@@ -140,6 +168,9 @@ int rt_init(const char *options, int (*parse_arg)(int 
option, char *value), int
        if (use_buffer)
                buffer_init();
 
+       /* Time stamp for stat files */
+       set_start_time();
+
        /*
         * atexit() order matters here - buffer_print() will be called before
         * buffer_fini().
diff --git a/testcases/realtime/lib/libstats.c 
b/testcases/realtime/lib/libstats.c
index 29e7ea7..1cfad54 100644
--- a/testcases/realtime/lib/libstats.c
+++ b/testcases/realtime/lib/libstats.c
@@ -42,9 +42,14 @@
 #include <errno.h>
 #include <unistd.h>
 #include <math.h>
+#include <sys/utsname.h>
 #include <libstats.h>
+#include <librttest.h>
 
 int save_stats = 0;
+int xml_dump = 0;
+char *test_name = "";
+char *kernel_dev_id = "";
 
 /* static helper functions */
 static int stats_record_compare(const void * a, const void * b) {
@@ -291,67 +296,162 @@ void stats_hist_print(stats_container_t *hist)
        }
 }
 
-int stats_container_save(char *filename, char *title, char *xlabel, char 
*ylabel, stats_container_t *data, char *mode)
+static int _stats_container_save(int xml, char *filename, char *title, char 
*xlabel, char *ylabel, stats_container_t *data, char *mode)
 {
-    int i;
-    int minx = 0, maxx = 0, miny = 0, maxy = 0;
-    FILE *dat_fd;
-    FILE *plt_fd;
-    char *datfile;
-    char *pltfile;
-    stats_record_t *rec;
-
-    if (!save_stats)
-           return 0;
-
-    /* generate the filenames */
-    if (asprintf(&datfile, "%s.dat", filename) == -1) {
+       int i;
+       long minx = 0, maxx = 0, miny = 0, maxy = 0;
+       FILE *dat_fd;
+       FILE *plt_fd;
+       char *datfile;
+       char *pltfile;
+       stats_record_t *rec;
+       int rc;
+
+       /* generate the filenames */
+       if (xml)
+               rc = asprintf(&datfile, "%s.%s.xml", filename, 
testrun_start_time);
+       else
+               rc = asprintf(&datfile, "%s.dat", filename);
+       
+       if (rc == -1) {
                fprintf(stderr, "Failed to allocate string for data 
filename\n");
                return -1;
        }
-    if (asprintf(&pltfile, "%s.plt", filename) == -1) {
+
+       if (!xml && asprintf(&pltfile, "%s.plt", filename) == -1) {
                fprintf(stderr, "Failed to allocate string for plot 
filename\n");
                return -1;
        }
 
-    /* generate the data file */
-    if (!(dat_fd = fopen(datfile, "w"))) {
-        perror("Failed to open dat file");
-        return -1;
-    } else {
-        minx = maxx = data->records[0].x;
-        miny = maxy = data->records[0].y;
-        for (i = 0; i < data->size; i++) {
-            rec = &data->records[i];
-            minx = MIN(minx, rec->x);
-            maxx = MAX(maxx, rec->x);
-            miny = MIN(miny, rec->y);
-            maxy = MAX(maxy, rec->y);
-            fprintf(dat_fd, "%ld %ld\n", rec->x, rec->y);
-        }
-        fclose(dat_fd);
-    }
-
-    /* generate the plt file */
-    if (!(plt_fd = fopen(pltfile, "w"))) {
-        perror("Failed to open plt file");
-        return -1;
-    } else {
-        fprintf(plt_fd, "set terminal png\n");
-        fprintf(plt_fd, "set output \"%s.png\"\n", pltfile);
-        fprintf(plt_fd, "set title \"%s\"\n", title);
-        fprintf(plt_fd, "set xlabel \"%s\"\n", xlabel);
-        fprintf(plt_fd, "set ylabel \"%s\"\n", ylabel);
-
-        // exact range mode
-        //fprintf(plt_fd, "plot [%d:%d] [%d:%d] \"%s\" with %s\n",
-        //        minx, maxx, miny, maxy, datfile, mode);
-
-        // expanded range mode - slightly more intuitive I think...
-        fprintf(plt_fd, "plot [0:%d] [0:%d] \"%s\" with %s\n",
-                maxx+1, maxy+1, datfile, mode);
-        fclose(plt_fd);
-    }
-
-    return 0;
+       /* generate the data file */
+       if (xml)
+               dat_fd = xml_dump_init(datfile, "ltp-sample", title);
+       else
+               dat_fd = fopen(datfile, "w");
+
+       if (!dat_fd) {
+               perror("Failed to open data file");
+               return -1;
+       }
+
+       minx = maxx = data->records[0].x;
+       miny = maxy = data->records[0].y;
+       if (xml) {
+               struct utsname u;
+
+               uname(&u);
+       
+               fprintf(dat_fd, "<xlabel>%s</xlabel>\n",xlabel);
+               fprintf(dat_fd, "<ylabel>%s</ylabel>\n",xlabel);
+               fprintf(dat_fd, "<mode>%s</mode>\n",mode);
+               fprintf(dat_fd, "<data>\n");
+       }
+       for (i = 0; i < data->size; i++) {
+               rec = &data->records[i];
+               minx = MIN(minx, rec->x);
+               maxx = MAX(maxx, rec->x);
+               miny = MIN(miny, rec->y);
+               maxy = MAX(maxy, rec->y);
+               if (xml)
+                       fprintf(dat_fd, 
"\t<e><r>%d</r><x>%ld</x><y>%ld</y></e>\n", i, rec->x, rec->y);
+               else
+                       fprintf(dat_fd, "%ld %ld\n", rec->x, rec->y);
+       }
+       if (xml) {
+               fprintf(dat_fd, "</data>\n");
+               fprintf(dat_fd, "<sample-size>%ld</sample-size>\n", data->size);
+               fprintf(dat_fd, "<minx>%ld</minx>\n<maxx>%ld</maxx>\n", minx, 
maxx);
+               fprintf(dat_fd, "<miny>%ld</miny>\n<maxy>%ld</maxy>\n", miny, 
maxy);
+               xml_dump_close(dat_fd, "ltp-sample");
+               return 0;
+       }
+
+
+       fclose(dat_fd);
+
+
+       /* generate the plt file */
+       if (!(plt_fd = fopen(pltfile, "w"))) {
+               perror("Failed to open plt file");
+               return -1;
+       }
+
+       fprintf(plt_fd, "set terminal png\n");
+       fprintf(plt_fd, "set output \"%s.png\"\n", pltfile);
+       fprintf(plt_fd, "set title \"%s\"\n", title);
+       fprintf(plt_fd, "set xlabel \"%s\"\n", xlabel);
+       fprintf(plt_fd, "set ylabel \"%s\"\n", ylabel);
+
+       // exact range mode
+       //fprintf(plt_fd, "plot [%d:%d] [%d:%d] \"%s\" with %s\n",
+       //        minx, maxx, miny, maxy, datfile, mode);
+
+       // expanded range mode - slightly more intuitive I think...
+       fprintf(plt_fd, "plot [0:%ld] [0:%ld] \"%s\" with %s\n",
+               maxx+1, maxy+1, datfile, mode);
+       fclose(plt_fd);
+
+       return 0;
+}
+
+/*
+ * Create XML dump file and initialise markup headers.
+ * Does not close fd but returns it. fd is to be reused by subsequent
+ * xml_dump... functions calls.
+ */
+FILE * xml_dump_init(char *filename, char *root_mrkup, char *title)
+{
+       FILE *dat_fd;
+       struct utsname u;
+       char *xmlfile;
+
+       if (-1 == asprintf(&xmlfile, "%s.%s.xml", filename, 
testrun_start_time)) {
+               fprintf(stderr, "xml_dump_init: Failed to allocate string for 
data filename\n");
+               return NULL;
+       }
+
+       /* generate the data file */
+       if (!(dat_fd = fopen(filename, "a+")))
+               return NULL;
+
+       uname(&u);
+
+       fprintf(dat_fd, "<%s>\n", root_mrkup);
+       fprintf(dat_fd, "<start-time>%s</start-time>\n",testrun_start_time);
+       fprintf(dat_fd, "<uname>\n");
+       fprintf(dat_fd, "\t<sysname>%s</sysname>\n",u.sysname);
+       fprintf(dat_fd, "\t<nodename>%s</nodename>\n",u.nodename);
+       fprintf(dat_fd, "\t<release>%s</release>\n",u.release);
+       fprintf(dat_fd, "\t<version>%s</version>\n",u.version);
+       fprintf(dat_fd, "\t<machine>%s</machine>\n",u.machine);
+       fprintf(dat_fd, "</uname>\n");
+       fprintf(dat_fd, "<kernel-dev-id>%s</kernel-dev-id>\n",kernel_dev_id);
+       fprintf(dat_fd, 
"<online-cpus>%ld</online-cpus>\n",sysconf(_SC_NPROCESSORS_ONLN));
+       fprintf(dat_fd, "<testname>%s</testname>\n",test_name);
+       fprintf(dat_fd, "<title>%s</title>\n",title);
+
+       return dat_fd;
+}
+
+
+void xml_dump_close(FILE *dat_fd, char *root_mrkup)
+{
+       fprintf(dat_fd, "</%s>\n", root_mrkup);
+       fclose(dat_fd);
+       return;
 }
+
+int stats_container_save(char *filename, char *title, char *xlabel, char 
*ylabel, stats_container_t *data, char *mode)
+{
+       int rc = 0, rc_xml = 0;
+
+       if (save_stats) {
+               rc = _stats_container_save(0, filename, title, xlabel, ylabel, 
data, mode);
+               if (xml_dump)
+                       rc = _stats_container_save(1, filename, title, xlabel, 
ylabel, data, mode);
+       }
+
+       return 0;
+}
+
+
-- 
1.5.5.GIT


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to