@@ -162,6 +162,7 @@ RegressionTest *RegressionTest::from_yajl_node(const yajl_val &node) {
162162 }
163163 if (strcmp (key2, " body" ) == 0 ) {
164164 u->request_body = yajl_array_to_str (val2);
165+ u->request_body_lines = yajl_array_to_vec_str (val2);
165166 }
166167 }
167168 }
@@ -175,6 +176,7 @@ RegressionTest *RegressionTest::from_yajl_node(const yajl_val &node) {
175176 }
176177 if (strcmp (key2, " body" ) == 0 ) {
177178 u->response_body = yajl_array_to_str (val2);
179+ u->response_body_lines = yajl_array_to_vec_str (val2);
178180 }
179181 if (strcmp (key2, " protocol" ) == 0 ) {
180182 u->response_protocol = YAJL_GET_STRING (val2);
@@ -214,6 +216,7 @@ RegressionTest *RegressionTest::from_yajl_node(const yajl_val &node) {
214216 si << keyj << " \n " ;
215217 }
216218 u->rules = si.str ();
219+ u->rules_lines = yajl_array_to_vec_str (val);
217220 }
218221 }
219222
@@ -223,7 +226,7 @@ RegressionTest *RegressionTest::from_yajl_node(const yajl_val &node) {
223226}
224227
225228RegressionTests *RegressionTests::from_yajl_node (const yajl_val &node) {
226- RegressionTests *u = new RegressionTests (node );
229+ RegressionTests *u = new RegressionTests ();
227230 size_t num_tests = node->u .array .len ;
228231 for ( int i = 0 ; i < num_tests; i++ ) {
229232 yajl_val obj = node->u .array .values [i];
@@ -232,94 +235,82 @@ RegressionTests *RegressionTests::from_yajl_node(const yajl_val &node) {
232235 return u;
233236}
234237
235- RegressionTests::~RegressionTests () {
236- #ifdef WITH_YAJL
237- yajl_tree_free (node);
238- #endif
239- }
240-
241238#ifdef WITH_YAJL
242239
243- static yajl_gen_status jayl_gen_string_view (yajl_gen g, std::string_view s) {
240+ static yajl_gen_status gen_string_view (yajl_gen g, std::string_view s) {
244241 return yajl_gen_string (g, reinterpret_cast <const unsigned char *>(s.data ()), s.length ());
245242}
246243
247- static yajl_gen_status jayl_gen_key_val (yajl_gen g, std::string_view key, std::string_view val) {
248- auto s = jayl_gen_string_view (g, key);
249- if (s != yajl_gen_status_ok) {
244+ static yajl_gen_status gen_key_str (yajl_gen g, std::string_view key, std::string_view val) {
245+ if (auto s{gen_string_view (g, key)}; s != yajl_gen_status_ok) {
250246 return s;
251247 }
252- return jayl_gen_string_view (g, val);
248+ return gen_string_view (g, val);
253249}
254250
255- static yajl_gen_status copy_number (yajl_gen g, std::string_view key, yajl_val val) {
256- if (!YAJL_IS_NUMBER (val)) {
257- std::cerr << " error: " << key << " must be number.\n " ;
258- exit (1 );
251+ static yajl_gen_status gen_key_str_if_non_empty (yajl_gen g, std::string_view key, std::string_view val) {
252+ if (val.empty ()) {
253+ return yajl_gen_status_ok;
259254 }
260- auto s = jayl_gen_string_view (g, key);
261- if (s != yajl_gen_status_ok) {
255+ return gen_key_str (g, key, val);
256+ }
257+
258+ static yajl_gen_status gen_key_int (yajl_gen g, std::string_view key, int val) {
259+ if (auto s{gen_string_view (g, key)}; s != yajl_gen_status_ok) {
262260 return s;
263261 }
264- return yajl_gen_number (g,
265- reinterpret_cast <const char *>(val->u .number .r ),
266- strlen (val->u .number .r ));
262+ return yajl_gen_integer (g, val);
267263}
268264
269- static yajl_gen_status copy_string (yajl_gen g, std::string_view key, yajl_val val) {
270- if (!YAJL_IS_STRING (val)) {
271- std::cerr << " error: " << key << " must be string.\n " ;
272- exit (1 );
265+ static yajl_gen_status gen_key_opt_int (yajl_gen g, std::string_view key, std::optional<int > val) {
266+ if (!val) {
267+ return yajl_gen_status_ok;
273268 }
274- return jayl_gen_key_val (g, key, val-> u . string );
269+ return gen_key_int (g, key, val. value () );
275270}
276271
277- static void ensure_obj (std::string_view key, yajl_val obj) {
278- if (!YAJL_IS_OBJECT (obj)) {
279- std::cerr << " error: " << key << " must be object.\n " ;
280- exit (1 );
272+ static yajl_gen_status gen_key_int_if_non_zero (yajl_gen g, std::string_view key, int val) {
273+ if (val == 0 ) {
274+ return yajl_gen_status_ok;
281275 }
276+ return gen_key_int (g, key, val);
282277}
283278
284- static void copy_str_map (yajl_gen g, std::string_view key, yajl_val val) {
285- if (!YAJL_IS_OBJECT (val)) {
286- std::cerr << " error: " << key << " must be object.\n " ;
287- exit (1 );
288- }
289- jayl_gen_string_view (g, key);
290- yajl_gen_map_open (g);
291- for (size_t i = 0 ; i < val->u .object .len ; ++i) {
292- const char *key2 = val->u .object .keys [i];
293- yajl_val val2 = val->u .object .values [i];
294- copy_string (g, key2, val2);
279+ static yajl_gen_status gen_key_number (yajl_gen g, std::string_view key, std::string_view raw_val) {
280+ if (auto s{gen_string_view (g, key)}; s != yajl_gen_status_ok) {
281+ return s;
295282 }
296- yajl_gen_map_close (g );
283+ return yajl_gen_number (g, reinterpret_cast < const char *>(raw_val. data ()), raw_val. length () );
297284}
298285
299- static void copy_str_array (yajl_gen g, std::string_view key, yajl_val val) {
300- if (!YAJL_IS_ARRAY (val)) {
301- std::cerr << " error: " << key << " must be array.\n " ;
302- exit (1 );
286+ static yajl_gen_status gen_key_str_array (yajl_gen g, std::string_view key, const std::vector<std::string> &lines) {
287+ if (auto s{gen_string_view (g, key)}; s != yajl_gen_status_ok) {
288+ return s;
303289 }
304- jayl_gen_string_view (g, key);
305- yajl_gen_array_open (g);
306- for (size_t i = 0 ; i < val->u .array .len ; ++i) {
307- yajl_val val2 = val->u .array .values [i];
308- if (!YAJL_IS_STRING (val2)) {
309- std::cerr << " error: array element of " << key << " must be string.\n " ;
310- exit (1 );
290+ if (auto s{yajl_gen_array_open (g)}; s != yajl_gen_status_ok) {
291+ return s;
292+ }
293+ for (const auto &line : lines) {
294+ if (auto s{gen_string_view (g, line)}; s != yajl_gen_status_ok) {
295+ return s;
311296 }
312- jayl_gen_string_view (g, val2->u .string );
313297 }
314- yajl_gen_array_close (g);
298+ return yajl_gen_array_close (g);
315299}
316300
317- static void copy_body (yajl_gen g, std::string_view key, yajl_val val) {
318- if (YAJL_IS_STRING (val)) {
319- jayl_gen_key_val (g, key, val->u .string );
320- } else {
321- copy_str_array (g, key, val);
301+ static yajl_gen_status gen_key_headers (yajl_gen g, std::string_view key, const std::vector<std::pair<std::string, std::string>> &headers) {
302+ if (auto s{gen_string_view (g, key)}; s != yajl_gen_status_ok) {
303+ return s;
304+ }
305+ if (auto s{yajl_gen_map_open (g)}; s != yajl_gen_status_ok) {
306+ return s;
307+ }
308+ for (const auto &header : headers) {
309+ if (auto s{gen_key_str (g, header.first , header.second )}; s != yajl_gen_status_ok) {
310+ return s;
311+ }
322312 }
313+ return yajl_gen_map_close (g);
323314}
324315
325316std::string RegressionTests::toJSON () {
@@ -332,115 +323,73 @@ std::string RegressionTests::toJSON() {
332323 return " " ;
333324 }
334325 yajl_gen_config (g, yajl_gen_beautify, 1 );
335-
336- if (!YAJL_IS_ARRAY (node)) {
337- std::cerr << " error: toplevel must be array.\n " ;
338- exit (1 );
339- }
326+ yajl_gen_config (g, yajl_gen_indent_string, " " );
340327
341328 yajl_gen_array_open (g);
342- for (size_t i = 0 ; i < node->u .array .len ; ++i) {
343- yajl_val test_obj = node->u .array .values [i];
344- ensure_obj (" test" , test_obj);
329+ for (const auto & test : tests) {
345330 yajl_gen_map_open (g);
346- for (size_t j = 0 ; j < test_obj->u .object .len ; ++j) {
347- const char *key = test_obj->u .object .keys [j];
348- yajl_val val = test_obj->u .object .values [j];
349- if (strcmp (key, " enabled" ) == 0
350- || strcmp (key, " version_min" ) == 0
351- || strcmp (key, " version_max" ) == 0
352- || strcmp (key, " github_issue" ) == 0 ) {
353- copy_number (g, key, val);
354- } else if (strcmp (key, " title" ) == 0
355- || strcmp (key, " url" ) == 0
356- || strcmp (key, " resource" ) == 0 ) {
357- copy_string (g, key, val);
358- } else if (strcmp (key, " client" ) == 0 ) {
359- ensure_obj (" client" , val);
360- jayl_gen_string_view (g, " client" );
361- yajl_gen_map_open (g);
362- for (size_t k = 0 ; k < val->u .object .len ; ++k) {
363- const char *key2 = val->u .object .keys [k];
364- yajl_val val2 = val->u .object .values [k];
365- if (strcmp (key2, " ip" ) == 0 ) {
366- copy_string (g, key2, val2);
367- } else if (strcmp (key2, " port" ) == 0 ) {
368- copy_number (g, key2, val2);
369- }
370- }
371- yajl_gen_map_close (g);
372- } else if (strcmp (key, " server" ) == 0 ) {
373- ensure_obj (" server" , val);
374- jayl_gen_string_view (g, " server" );
375- yajl_gen_map_open (g);
376- for (size_t k = 0 ; k < val->u .object .len ; ++k) {
377- const char *key2 = val->u .object .keys [k];
378- yajl_val val2 = val->u .object .values [k];
379- if (strcmp (key2, " ip" ) == 0
380- || strcmp (key2, " hostname" ) == 0 ) {
381- copy_string (g, key2, val2);
382- } else if (strcmp (key2, " port" ) == 0 ) {
383- copy_number (g, key2, val2);
384- }
385- }
386- yajl_gen_map_close (g);
387- } else if (strcmp (key, " request" ) == 0 ) {
388- ensure_obj (" request" , val);
389- jayl_gen_string_view (g, " request" );
390- yajl_gen_map_open (g);
391- for (size_t k = 0 ; k < val->u .object .len ; ++k) {
392- const char *key2 = val->u .object .keys [k];
393- yajl_val val2 = val->u .object .values [k];
394- if (strcmp (key2, " url" ) == 0
395- || strcmp (key2, " method" ) == 0 ) {
396- copy_string (g, key2, val2);
397- } else if (strcmp (key2, " http_version" ) == 0 ) {
398- copy_number (g, key2, val2);
399- } else if (strcmp (key2, " headers" ) == 0 ) {
400- copy_str_map (g, key2, val2);
401- } else if (strcmp (key2, " body" ) == 0 ) {
402- copy_body (g, key2, val2);
403- }
404- }
405- yajl_gen_map_close (g);
406- } else if (strcmp (key, " response" ) == 0 ) {
407- ensure_obj (" response" , val);
408- jayl_gen_string_view (g, " response" );
409- yajl_gen_map_open (g);
410- for (size_t k = 0 ; k < val->u .object .len ; ++k) {
411- const char *key2 = val->u .object .keys [k];
412- yajl_val val2 = val->u .object .values [k];
413- if (strcmp (key2, " protocol" ) == 0 ) {
414- copy_string (g, key2, val2);
415- } else if (strcmp (key2, " headers" ) == 0 ) {
416- copy_str_map (g, key2, val2);
417- } else if (strcmp (key2, " body" ) == 0 ) {
418- copy_body (g, key2, val2);
419- }
420- }
421- yajl_gen_map_close (g);
422- } else if (strcmp (key, " expected" ) == 0 ) {
423- ensure_obj (" expected" , val);
424- jayl_gen_string_view (g, " expected" );
425- yajl_gen_map_open (g);
426- for (size_t k = 0 ; k < val->u .object .len ; ++k) {
427- const char *key2 = val->u .object .keys [k];
428- yajl_val val2 = val->u .object .values [k];
429- if (strcmp (key2, " audit_log" ) == 0
430- || strcmp (key2, " debug_log" ) == 0
431- || strcmp (key2, " error_log" ) == 0
432- || strcmp (key2, " redirect_url" ) == 0
433- || strcmp (key2, " parser_error" ) == 0 ) {
434- copy_string (g, key2, val2);
435- } else if (strcmp (key2, " http_code" ) == 0 ) {
436- copy_number (g, key2, val2);
437- }
438- }
439- yajl_gen_map_close (g);
440- } else if (strcmp (key, " rules" ) == 0 ) {
441- copy_str_array (g, key, val);
442- }
331+ gen_key_int (g, " enabled" , test.enabled );
332+ gen_key_int (g, " version_min" , test.version_min );
333+ gen_key_opt_int (g, " version_max" , test.version_max );
334+ gen_key_str (g, " title" , test.title );
335+ gen_key_str_if_non_empty (g, " url" , test.url );
336+ gen_key_str_if_non_empty (g, " resource" , test.resource );
337+ gen_key_opt_int (g, " github_issue" , test.github_issue );
338+
339+ gen_string_view (g, " client" );
340+ yajl_gen_map_open (g);
341+ gen_key_str (g, " ip" , test.clientIp );
342+ gen_key_int (g, " port" , test.clientPort );
343+ yajl_gen_map_close (g);
344+
345+ gen_string_view (g, " server" );
346+ yajl_gen_map_open (g);
347+ gen_key_str (g, " ip" , test.serverIp );
348+ gen_key_int (g, " port" , test.serverPort );
349+ yajl_gen_map_close (g);
350+
351+ gen_string_view (g, " request" );
352+ yajl_gen_map_open (g);
353+ gen_key_headers (g, " headers" , test.request_headers );
354+ gen_key_str (g, " uri" , test.uri );
355+ gen_key_str (g, " method" , test.method );
356+ if (!test.httpVersion .empty ()) {
357+ gen_key_number (g, " http_version" , test.httpVersion );
358+ }
359+
360+ auto request_body_lines{test.request_body_lines };
361+ if (request_body_lines.empty ()) {
362+ request_body_lines.push_back (" " );
363+ }
364+ gen_key_str_array (g, " body" , request_body_lines);
365+
366+ yajl_gen_map_close (g);
367+
368+ gen_string_view (g, " response" );
369+ yajl_gen_map_open (g);
370+ gen_key_headers (g, " headers" , test.response_headers );
371+
372+ auto response_body_lines{test.response_body_lines };
373+ if (response_body_lines.empty ()) {
374+ response_body_lines.push_back (" " );
443375 }
376+ gen_key_str_array (g, " body" , response_body_lines);
377+
378+ gen_key_str_if_non_empty (g, " protocol" , test.response_protocol );
379+ yajl_gen_map_close (g);
380+
381+ gen_string_view (g, " expected" );
382+ yajl_gen_map_open (g);
383+ gen_key_str_if_non_empty (g, " audit_log" , test.audit_log );
384+ gen_key_str_if_non_empty (g, " debug_log" , test.debug_log );
385+ gen_key_str_if_non_empty (g, " error_log" , test.error_log );
386+ gen_key_int (g, " http_code" , test.http_code );
387+ gen_key_str_if_non_empty (g, " redirect_url" , test.redirect_url );
388+ gen_key_str_if_non_empty (g, " parser_error" , test.parser_error );
389+ yajl_gen_map_close (g);
390+
391+ gen_key_str_array (g, " rules" , test.rules_lines );
392+
444393 yajl_gen_map_close (g);
445394 }
446395 yajl_gen_array_close (g);
0 commit comments