• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #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 
10 static char testdatadir[] = JSON_TESTS_DIRECTORY;
11 
read_json(int fd)12 static 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 
31 static void compare(struct json_object *one,
32 		    struct json_object *two);
33 
compare_objects(struct json_object * one,struct json_object * two)34 static 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 
compare_arrays(struct json_object * one,struct json_object * two)49 static 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 
compatible_types(struct json_object * one,struct json_object * two)61 static 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 
compare(struct json_object * one,struct json_object * two)89 static 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 
run_results_and_compare(int dirfd,const char * dirname)126 static 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 
150 static 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 	"aborted-on-boot",
158 	"aborted-after-a-test",
159 	"dmesg-escapes",
160 	"notrun-results",
161 	"notrun-results-multiple-mode",
162 	"dmesg-warn-level",
163 	"dmesg-warn-level-piglit-style",
164 	"dmesg-warn-level-one-piglit-style"
165 };
166 
167 igt_main
168 {
169 	int dirfd = open(testdatadir, O_RDONLY | O_DIRECTORY);
170 	size_t i;
171 
172 	igt_assert_fd(dirfd);
173 
174 	for (i = 0; i < ARRAY_SIZE(dirnames); i++) {
igt_subtest(dirnames[i])175 		igt_subtest(dirnames[i]) {
176 			run_results_and_compare(dirfd, dirnames[i]);
177 		}
178 	}
179 }
180