blob: 758700d46b021e377e152d668d0fa4dd0dacd94b [file] [log] [blame]
Petri Latvalae2d7d222018-10-23 15:20:24 +03001#include <sys/types.h>
2#include <sys/stat.h>
3#include <fcntl.h>
4
5#include <json.h>
6
7#include "igt.h"
8#include "resultgen.h"
9
10static char testdatadir[] = JSON_TESTS_DIRECTORY;
11
12static struct json_object *read_json(int fd)
13{
14 struct json_object *obj;
15 struct json_tokener *tok = json_tokener_new();
16 enum json_tokener_error err;
17 char buf[512];
18 ssize_t s;
19
20 do {
21 s = read(fd, buf, sizeof(buf));
22 obj = json_tokener_parse_ex(tok, buf, s);
23 } while ((err = json_tokener_get_error(tok)) == json_tokener_continue);
24
25 igt_assert_eq(err, json_tokener_success);
26
27 json_tokener_free(tok);
28 return obj;
29}
30
31static void compare(struct json_object *one,
32 struct json_object *two);
33
34static void compare_objects(struct json_object *one,
35 struct json_object *two)
36{
37 json_object_iter iter;
38 struct json_object *subobj;
39
40 json_object_object_foreachC(one, iter) {
41 igt_debug("Key %s\n", iter.key);
42
43 igt_assert(json_object_object_get_ex(two, iter.key, &subobj));
44
45 compare(iter.val, subobj);
46 }
47}
48
49static void compare_arrays(struct json_object *one,
50 struct json_object *two)
51{
52 size_t i;
53
54 for (i = 0; i < json_object_array_length(one); i++) {
55 igt_debug("Array index %zd\n", i);
56 compare(json_object_array_get_idx(one, i),
57 json_object_array_get_idx(two, i));
58 }
59}
60
61static bool compatible_types(struct json_object *one,
62 struct json_object *two)
63{
64 /*
65 * A double of value 0.0 gets written as "0", which gets read
66 * as an int.
67 */
68 json_type onetype = json_object_get_type(one);
69 json_type twotype = json_object_get_type(two);
70
71 switch (onetype) {
72 case json_type_boolean:
73 case json_type_string:
74 case json_type_object:
75 case json_type_array:
76 case json_type_null:
77 return onetype == twotype;
78 break;
79 case json_type_double:
80 case json_type_int:
81 return twotype == json_type_double || twotype == json_type_int;
82 break;
83 }
84
85 igt_assert(!"Cannot be reached");
86 return false;
87}
88
89static void compare(struct json_object *one,
90 struct json_object *two)
91{
92 igt_assert(compatible_types(one, two));
93
94 switch (json_object_get_type(one)) {
95 case json_type_boolean:
96 igt_assert_eq(json_object_get_boolean(one), json_object_get_boolean(two));
97 break;
98 case json_type_double:
99 case json_type_int:
100 /*
101 * A double of value 0.0 gets written as "0", which
102 * gets read as an int. Both yield 0.0 with
103 * json_object_get_double(). Comparing doubles with ==
104 * considered crazy but it's good enough.
105 */
106 igt_assert(json_object_get_double(one) == json_object_get_double(two));
107 break;
108 case json_type_string:
109 igt_assert(!strcmp(json_object_get_string(one), json_object_get_string(two)));
110 break;
111 case json_type_object:
112 igt_assert_eq(json_object_object_length(one), json_object_object_length(two));
113 compare_objects(one, two);
114 break;
115 case json_type_array:
116 igt_assert_eq(json_object_array_length(one), json_object_array_length(two));
117 compare_arrays(one, two);
118 break;
119 case json_type_null:
120 break;
121 default:
122 igt_assert(!"Cannot be reached");
123 }
124}
125
126static void run_results_and_compare(int dirfd, const char *dirname)
127{
128 int testdirfd = openat(dirfd, dirname, O_RDONLY | O_DIRECTORY);
129 int reference;
130 struct json_object *resultsobj, *referenceobj;
131
132 igt_assert_fd(testdirfd);
133
134 igt_assert((resultsobj = generate_results_json(testdirfd)) != NULL);
135
136 reference = openat(testdirfd, "reference.json", O_RDONLY);
137 close(testdirfd);
138
139 igt_assert_fd(reference);
140 referenceobj = read_json(reference);
141 close(reference);
142 igt_assert(referenceobj != NULL);
143
144 igt_debug("Root object\n");
145 compare(resultsobj, referenceobj);
146 igt_assert_eq(json_object_put(resultsobj), 1);
147 igt_assert_eq(json_object_put(referenceobj), 1);
148}
149
150static const char *dirnames[] = {
151 "normal-run",
152 "warnings",
153 "warnings-with-dmesg-warns",
154 "piglit-style-dmesg",
155 "incomplete-before-any-subtests",
156 "dmesg-results",
157};
158
159igt_main
160{
161 int dirfd = open(testdatadir, O_RDONLY | O_DIRECTORY);
162 size_t i;
163
164 igt_assert_fd(dirfd);
165
166 for (i = 0; i < ARRAY_SIZE(dirnames); i++) {
167 igt_subtest(dirnames[i]) {
168 run_results_and_compare(dirfd, dirnames[i]);
169 }
170 }
171}