testsuite: allow to check generated files
authorLucas De Marchi <lucas.de.marchi@gmail.com>
Thu, 4 Oct 2012 03:21:52 +0000 (00:21 -0300)
committerLucas De Marchi <lucas.de.marchi@gmail.com>
Thu, 4 Oct 2012 04:04:52 +0000 (01:04 -0300)
This gives the test cases the ability to supply files that must be
checked after the test is run, rather than just checking stdout/stderr.

This is intended to be used with tools that generate files, like depmod.
It includes a poor's man implementation of a "check for differences in
files". Not really optimized, but it's simple enough and does what it
proposes to.

testsuite/testsuite.c
testsuite/testsuite.h

index e874191..db51dae 100644 (file)
@@ -434,6 +434,100 @@ out:
        return err == 0;
 }
 
+static inline int safe_read(int fd, void *buf, size_t count)
+{
+       int r;
+
+       while (1) {
+               r = read(fd, buf, count);
+               if (r == -1 && errno == -EINTR)
+                       continue;
+               break;
+       }
+
+       return r;
+}
+
+static bool check_generated_files(const struct test *t)
+{
+       const struct keyval *k;
+
+       /* This is not meant to be a diff replacement, just stupidly check if
+        * the files match. Bear in mind they can be binary files */
+       for (k = t->output.files; k && k->key; k++) {
+               struct stat sta, stb;
+               int fda = -1, fdb = -1;
+               char bufa[4096];
+               char bufb[4096];
+
+               fda = open(k->key, O_RDONLY);
+               if (fda < 0) {
+                       ERR("could not open %s\n - %m\n", k->key);
+                       goto fail;
+               }
+
+               fdb = open(k->val, O_RDONLY);
+               if (fdb < 0) {
+                       ERR("could not open %s\n - %m\n", k->val);
+                       goto fail;
+               }
+
+               if (fstat(fda, &sta) != 0) {
+                       ERR("could not fstat %d %s\n - %m\n", fda, k->key);
+                       goto fail;
+               }
+
+               if (fstat(fdb, &stb) != 0) {
+                       ERR("could not fstat %d %s\n - %m\n", fdb, k->key);
+                       goto fail;
+               }
+
+               if (sta.st_size != stb.st_size) {
+                       ERR("sizes do not match %s %s\n", k->key, k->val);
+                       goto fail;
+               }
+
+               for (;;) {
+                       int r, done;
+
+                       r = safe_read(fda, bufa, sizeof(bufa));
+                       if (r < 0)
+                               goto fail;
+
+                       if (r == 0)
+                               /* size is already checked, go to next file */
+                               goto next;
+
+                       for (done = 0; done < r;) {
+                               int r2 = safe_read(fdb, bufb + done, r - done);
+
+                               if (r2 <= 0)
+                                       goto fail;
+
+                               done += r2;
+                       }
+
+                       if (memcmp(bufa, bufb, r) != 0)
+                               goto fail;
+               }
+
+next:
+               close(fda);
+               close(fdb);
+               continue;
+
+fail:
+               if (fda >= 0)
+                       close(fda);
+               if (fdb >= 0)
+                       close(fdb);
+
+               return false;
+       }
+
+       return true;
+}
+
 static inline int test_run_parent(const struct test *t, int fdout[2],
                                int fderr[2], int fdmonitor[2], pid_t child)
 {
@@ -482,6 +576,9 @@ static inline int test_run_parent(const struct test *t, int fdout[2],
                return EXIT_FAILURE;
        }
 
+       if (matchout)
+               matchout = check_generated_files(t);
+
        if (t->expected_fail == false) {
                if (err == 0) {
                        if (matchout)
index 1f8eb6e..80bf8a1 100644 (file)
@@ -81,8 +81,17 @@ struct test {
        const char *name;
        const char *description;
        struct {
+               /* File with correct stdout */
                const char *stdout;
+               /* File with correct stderr */
                const char *stderr;
+
+               /*
+                * Vector with pair of files
+                * key = correct file
+                * val = file to check
+                */
+               const struct keyval *files;
        } output;
        testfunc func;
        const char *config[_TC_LAST];