#include #include #include #include #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", "aborted-on-boot", "aborted-after-a-test", "dmesg-escapes", "notrun-results", "notrun-results-multiple-mode", "dmesg-warn-level", "dmesg-warn-level-piglit-style", "dmesg-warn-level-one-piglit-style" }; 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]); } } }