summaryrefslogtreecommitdiff
path: root/runner/runner_json_tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'runner/runner_json_tests.c')
-rw-r--r--runner/runner_json_tests.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/runner/runner_json_tests.c b/runner/runner_json_tests.c
new file mode 100644
index 00000000..758700d4
--- /dev/null
+++ b/runner/runner_json_tests.c
@@ -0,0 +1,171 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <json.h>
+
+#include "igt.h"
+#include "resultgen.h"
+
+static char testdatadir[] = JSON_TESTS_DIRECTORY;
+
+static struct json_object *read_json(int fd)
+{
+ struct json_object *obj;
+ struct json_tokener *tok = json_tokener_new();
+ enum json_tokener_error err;
+ char buf[512];
+ ssize_t s;
+
+ do {
+ s = read(fd, buf, sizeof(buf));
+ obj = json_tokener_parse_ex(tok, buf, s);
+ } while ((err = json_tokener_get_error(tok)) == json_tokener_continue);
+
+ igt_assert_eq(err, json_tokener_success);
+
+ json_tokener_free(tok);
+ return obj;
+}
+
+static void compare(struct json_object *one,
+ struct json_object *two);
+
+static void compare_objects(struct json_object *one,
+ struct json_object *two)
+{
+ json_object_iter iter;
+ struct json_object *subobj;
+
+ json_object_object_foreachC(one, iter) {
+ igt_debug("Key %s\n", iter.key);
+
+ igt_assert(json_object_object_get_ex(two, iter.key, &subobj));
+
+ compare(iter.val, subobj);
+ }
+}
+
+static void compare_arrays(struct json_object *one,
+ struct json_object *two)
+{
+ size_t i;
+
+ for (i = 0; i < json_object_array_length(one); i++) {
+ igt_debug("Array index %zd\n", i);
+ compare(json_object_array_get_idx(one, i),
+ json_object_array_get_idx(two, i));
+ }
+}
+
+static bool compatible_types(struct json_object *one,
+ struct json_object *two)
+{
+ /*
+ * A double of value 0.0 gets written as "0", which gets read
+ * as an int.
+ */
+ json_type onetype = json_object_get_type(one);
+ json_type twotype = json_object_get_type(two);
+
+ switch (onetype) {
+ case json_type_boolean:
+ case json_type_string:
+ case json_type_object:
+ case json_type_array:
+ case json_type_null:
+ return onetype == twotype;
+ break;
+ case json_type_double:
+ case json_type_int:
+ return twotype == json_type_double || twotype == json_type_int;
+ break;
+ }
+
+ igt_assert(!"Cannot be reached");
+ return false;
+}
+
+static void compare(struct json_object *one,
+ struct json_object *two)
+{
+ igt_assert(compatible_types(one, two));
+
+ switch (json_object_get_type(one)) {
+ case json_type_boolean:
+ igt_assert_eq(json_object_get_boolean(one), json_object_get_boolean(two));
+ break;
+ case json_type_double:
+ case json_type_int:
+ /*
+ * A double of value 0.0 gets written as "0", which
+ * gets read as an int. Both yield 0.0 with
+ * json_object_get_double(). Comparing doubles with ==
+ * considered crazy but it's good enough.
+ */
+ igt_assert(json_object_get_double(one) == json_object_get_double(two));
+ break;
+ case json_type_string:
+ igt_assert(!strcmp(json_object_get_string(one), json_object_get_string(two)));
+ break;
+ case json_type_object:
+ igt_assert_eq(json_object_object_length(one), json_object_object_length(two));
+ compare_objects(one, two);
+ break;
+ case json_type_array:
+ igt_assert_eq(json_object_array_length(one), json_object_array_length(two));
+ compare_arrays(one, two);
+ break;
+ case json_type_null:
+ break;
+ default:
+ igt_assert(!"Cannot be reached");
+ }
+}
+
+static void run_results_and_compare(int dirfd, const char *dirname)
+{
+ int testdirfd = openat(dirfd, dirname, O_RDONLY | O_DIRECTORY);
+ int reference;
+ struct json_object *resultsobj, *referenceobj;
+
+ igt_assert_fd(testdirfd);
+
+ igt_assert((resultsobj = generate_results_json(testdirfd)) != NULL);
+
+ reference = openat(testdirfd, "reference.json", O_RDONLY);
+ close(testdirfd);
+
+ igt_assert_fd(reference);
+ referenceobj = read_json(reference);
+ close(reference);
+ igt_assert(referenceobj != NULL);
+
+ igt_debug("Root object\n");
+ compare(resultsobj, referenceobj);
+ igt_assert_eq(json_object_put(resultsobj), 1);
+ igt_assert_eq(json_object_put(referenceobj), 1);
+}
+
+static const char *dirnames[] = {
+ "normal-run",
+ "warnings",
+ "warnings-with-dmesg-warns",
+ "piglit-style-dmesg",
+ "incomplete-before-any-subtests",
+ "dmesg-results",
+};
+
+igt_main
+{
+ int dirfd = open(testdatadir, O_RDONLY | O_DIRECTORY);
+ size_t i;
+
+ igt_assert_fd(dirfd);
+
+ for (i = 0; i < ARRAY_SIZE(dirnames); i++) {
+ igt_subtest(dirnames[i]) {
+ run_results_and_compare(dirfd, dirnames[i]);
+ }
+ }
+}