blob: 7c9540d1c277e671f8e6e61fb0c59734ac0b65fa [file] [log] [blame]
#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",
"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]);
}
}
}