JSON_GENERATOR_STATE_END,
};
+enum json_format_state {
+ JSON_FORMAT_STATE_NONE = 0,
+ JSON_FORMAT_STATE_INDENT,
+ JSON_FORMAT_STATE_SPACE,
+ JSON_FORMAT_STATE_CR,
+ JSON_FORMAT_STATE_LF,
+ JSON_FORMAT_STATE_DONE,
+};
+
struct json_generator_level {
bool object:1;
};
/* Write state: stack position of written syntax levels */
unsigned int level_stack_written;
+ /* Formatting state */
+ struct json_format format;
+ char *format_indent;
+ enum json_format_state format_state;
+ unsigned int indent_pos, indent_count;
+
/* Currently opened string output stream */
struct json_string_ostream *str_stream;
/* Currently pending string input stream */
bool text_stream:1; /* API state */
/* A json_string_ostream is running the generator */
bool streaming:1;
+ /* Finish writing formatting whitespace element */
+ bool format_finish:1;
};
static int json_generator_flush_string_input(struct json_generator *generator);
str_free(&generator->buf);
}
array_free(&generator->level_stack);
+ i_free(generator->format_indent);
i_free(generator);
}
+void json_generator_set_format(struct json_generator *generator,
+ const struct json_format *format)
+{
+ i_assert(generator->state == JSON_GENERATOR_STATE_VALUE);
+ i_assert(generator->write_state == JSON_GENERATOR_STATE_VALUE);
+ generator->format = *format;
+
+ i_free(generator->format_indent);
+ if (format->indent_chars > 0) {
+ generator->format_indent = i_malloc(format->indent_chars);
+ memset(generator->format_indent,
+ (format->indent_tab ? '\t' : ' '),
+ format->indent_chars);
+ }
+}
+
static inline size_t
json_generator_bytes_available(struct json_generator *generator)
{
return 1;
}
+static int json_generator_flush_format(struct json_generator *generator)
+{
+ int ret;
+
+ for (;;) switch (generator->format_state) {
+ case JSON_FORMAT_STATE_NONE:
+ return 1;
+ case JSON_FORMAT_STATE_CR:
+ ret = json_generator_write_all(generator, "\r", 1);
+ if (ret <= 0)
+ return ret;
+ generator->format_state = JSON_FORMAT_STATE_LF;
+ /* fall through */
+ case JSON_FORMAT_STATE_LF:
+ ret = json_generator_write_all(generator, "\n", 1);
+ if (ret <= 0)
+ return ret;
+ if (generator->format.indent_chars == 0) {
+ generator->format_state = JSON_FORMAT_STATE_DONE;
+ break;
+ }
+ generator->format_state = JSON_FORMAT_STATE_INDENT;
+ /* fall through */
+ case JSON_FORMAT_STATE_INDENT:
+ i_assert(generator->format.indent_chars != 0);
+ while (generator->indent_pos < generator->indent_count) {
+ ret = json_generator_write_buffered(
+ generator, generator->format_indent,
+ generator->format.indent_chars, FALSE);
+ if (ret <= 0)
+ return -1;
+ generator->indent_pos++;
+ }
+ generator->format_state = JSON_FORMAT_STATE_DONE;
+ break;
+ case JSON_FORMAT_STATE_SPACE:
+ ret = json_generator_write_all(generator, " ", 1);
+ if (ret <= 0)
+ return ret;
+ generator->format_state = JSON_FORMAT_STATE_DONE;
+ break;
+ case JSON_FORMAT_STATE_DONE:
+ if (!generator->format_finish)
+ return 1;
+ generator->format_state = JSON_FORMAT_STATE_NONE;
+ break;
+ }
+ i_unreached();
+}
+
+static int
+json_generator_write_newline(struct json_generator *generator,
+ unsigned int indent_count, bool finish)
+{
+ if (generator->format_state == JSON_FORMAT_STATE_DONE)
+ return 1;
+ i_assert(generator->format_state == JSON_FORMAT_STATE_NONE);
+ if (!generator->format.new_line)
+ return 1;
+ if (generator->format.crlf)
+ generator->format_state = JSON_FORMAT_STATE_CR;
+ else
+ generator->format_state = JSON_FORMAT_STATE_LF;
+ generator->indent_pos = 0;
+ generator->indent_count = indent_count;
+ generator->format_finish = finish;
+ return json_generator_flush_format(generator);
+}
+
+static int
+json_generator_write_space(struct json_generator *generator,
+ bool finish)
+{
+ if (generator->format_state == JSON_FORMAT_STATE_DONE)
+ return 1;
+ i_assert(generator->format_state == JSON_FORMAT_STATE_NONE);
+ if (!generator->format.whitespace)
+ return 1;
+ generator->format_state = JSON_FORMAT_STATE_SPACE;
+ generator->format_finish = finish;
+ return json_generator_flush_format(generator);
+}
+
+static void json_generator_finish_format(struct json_generator *generator)
+{
+ generator->format_state = JSON_FORMAT_STATE_NONE;
+}
+
int json_generator_flush(struct json_generator *generator)
{
bool hide_root = HAS_ALL_BITS(generator->flags,
/* Flush buffer */
ret = json_generator_flush_buffer(generator);
+ if (ret <= 0)
+ return ret;
+ /* Flush formatting whitespace */
+ ret = json_generator_flush_format(generator);
if (ret <= 0)
return ret;
/* Flush closing string */
if (ret <= 0)
return ret;
generator->write_state = JSON_GENERATOR_STATE_VALUE;
+ ret = json_generator_write_space(generator, TRUE);
+ if (ret <= 0)
+ return ret;
}
/* Flush opening objects/arrays */
for (;;) {
if (ret <= 0)
return ret;
generator->write_state = JSON_GENERATOR_STATE_VALUE;
+ ret = json_generator_write_newline(
+ generator, generator->level_stack_written,
+ TRUE);
+ if (ret <= 0)
+ return ret;
}
// FIXME: add indent
generator->object_level_written = FALSE;
generator->write_state = JSON_GENERATOR_STATE_VALUE;
}
+ ret = json_generator_write_newline(
+ generator, generator->level_stack_written, TRUE);
+ if (ret <= 0)
+ return ret;
}
/* Flush separator */
switch (generator->write_state) {
case JSON_GENERATOR_STATE_VALUE_END:
if (generator->level_stack_pos == 0) {
generator->write_state = JSON_GENERATOR_STATE_END;
+ ret = json_generator_write_newline(
+ generator, generator->level_stack_written,
+ TRUE);
+ if (ret <= 0)
+ return ret;
break;
}
if (generator->state != JSON_GENERATOR_STATE_STRING &&
} else {
generator->write_state = JSON_GENERATOR_STATE_VALUE;
}
+ ret = json_generator_write_newline(
+ generator, generator->level_stack_written, TRUE);
+ if (ret <= 0)
+ return ret;
break;
/* Flush colon */
case JSON_GENERATOR_STATE_OBJECT_VALUE:
if (ret <= 0)
return ret;
generator->write_state = JSON_GENERATOR_STATE_VALUE;
+ ret = json_generator_write_space(generator, TRUE);
+ if (ret <= 0)
+ return ret;
break;
default:
break;
generator->write_state == JSON_GENERATOR_STATE_VALUE_END);
i_assert(generator->level_stack_written > 0);
+ ret = json_generator_write_newline(
+ generator, generator->level_stack_written - 1, FALSE);
+ if (ret <= 0)
+ return ret;
if (!hide_root || generator->level_stack_written > 1) {
ret = json_generator_write_all(generator, "]", 1);
if (ret <= 0)
}
json_generator_level_close(generator, FALSE);
json_generator_value_end(generator);
+ json_generator_finish_format(generator);
return 1;
}
i_assert(generator->write_state == JSON_GENERATOR_STATE_OBJECT_MEMBER ||
generator->write_state == JSON_GENERATOR_STATE_VALUE_END);
i_assert(generator->level_stack_written > 0);
+ ret = json_generator_write_newline(
+ generator, generator->level_stack_written - 1, FALSE);
+ if (ret <= 0)
+ return ret;
if (!hide_root || generator->level_stack_written > 1) {
ret = json_generator_write_all(generator, "}", 1);
if (ret <= 0)
}
json_generator_level_close(generator, TRUE);
json_generator_value_end(generator);
+ json_generator_finish_format(generator);
return 1;
}
void json_generator_deinit(struct json_generator **_generator);
+void json_generator_set_format(struct json_generator *generator,
+ const struct json_format *format);
+
int json_generator_flush(struct json_generator *generator);
/* number */
return stream->closed;
}
+void json_ostream_set_format(struct json_ostream *stream,
+ const struct json_format *format)
+{
+ json_generator_set_format(stream->generator, format);
+}
+
void json_ostream_cork(struct json_ostream *stream)
{
if (stream->output != NULL)
void json_ostream_close(struct json_ostream *stream);
bool json_ostream_is_closed(struct json_ostream *stream) ATTR_PURE;
+void json_ostream_set_format(struct json_ostream *stream,
+ const struct json_format *format);
+
/*
* Position
*/
*/
void json_tree_write_buffer(const struct json_tree *jtree, buffer_t *buf,
- enum json_generator_flags gen_flags)
+ enum json_generator_flags gen_flags,
+ const struct json_format *format)
+
{
struct json_ostream *joutput;
joutput = json_ostream_create_str(buf, gen_flags);
+ if (format != NULL)
+ json_ostream_set_format(joutput, format);
json_ostream_nwrite_tree(joutput, NULL, jtree);
json_ostream_nfinish_destroy(&joutput);
}
const char *
json_tree_to_text(const struct json_tree *jtree,
- enum json_generator_flags gen_flags)
+ enum json_generator_flags gen_flags,
+ const struct json_format *format)
{
string_t *str = t_str_new(1024);
- json_tree_write_buffer(jtree, str, gen_flags);
+ json_tree_write_buffer(jtree, str, gen_flags, format);
return str_c(str);
}
{
string_t *str = t_str_new(1024);
- json_tree_write_buffer(jtree, str, 0);
+ json_tree_write_buffer(jtree, str, 0, NULL);
return str_c(str);
}
*/
void json_tree_write_buffer(const struct json_tree *jtree, buffer_t *buf,
- enum json_generator_flags gen_flags);
+ enum json_generator_flags gen_flags,
+ const struct json_format *format);
+
const char *
json_tree_to_text(const struct json_tree *jtree,
- enum json_generator_flags gen_flags);
+ enum json_generator_flags gen_flags,
+ const struct json_format *format);
const char *json_tree_to_text_line(const struct json_tree *jtree);
#endif
unsigned int max_list_items;
};
+/*
+ * Format
+ */
+
+struct json_format {
+ /* Number of indent characters (either TAB or SPACE) */
+ unsigned int indent_chars;
+
+ /* Indent character is TAB instead of SPACE */
+ bool indent_tab:1;
+ /* Insert whitespace at appropriate places around separators */
+ bool whitespace:1;
+ /* Insert newlines */
+ bool new_line:1;
+ /* Newlines are CRLF rather than the default LF */
+ bool crlf:1;
+};
+
#endif
str_free(&buffer);
}
+static void test_json_generate_formatted(void)
+{
+ string_t *buffer;
+ struct ostream *output;
+ struct json_format format;
+ struct json_generator *generator;
+ unsigned int state, pos;
+ int ret;
+
+ i_zero(&format);
+ format.indent_chars = 2;
+ format.indent_tab = FALSE;
+ format.whitespace = TRUE;
+ format.new_line = TRUE;
+
+ buffer = str_new(default_pool, 256);
+ output = o_stream_create_buffer(buffer);
+ o_stream_set_no_error_handling(output, TRUE);
+
+ /* value */
+ test_begin("json format value");
+ generator = json_generator_init(output, 0);
+ json_generator_set_format(generator, &format);
+ ret = json_generate_number(generator, 23423);
+ test_assert(ret > 0);
+ json_generator_flush(generator);
+ test_assert(ret > 0);
+ json_generator_deinit(&generator);
+ test_assert(strcmp("23423\n", str_c(buffer)) == 0);
+ test_end();
+ str_truncate(buffer, 0);
+ output->offset = 0;
+
+ /* [ value ] */
+ test_begin("json format array - [ string ]");
+ generator = json_generator_init(output, 0);
+ json_generator_set_format(generator, &format);
+ json_generate_array_open(generator);
+ ret = json_generate_string(generator, "frop");
+ test_assert(ret > 0);
+ ret = json_generate_array_close(generator);
+ test_assert(ret > 0);
+ json_generator_flush(generator);
+ test_assert(ret > 0);
+ json_generator_deinit(&generator);
+ test_assert(strcmp("[\n"
+ " \"frop\"\n"
+ "]\n", str_c(buffer)) == 0);
+ test_end();
+ str_truncate(buffer, 0);
+ output->offset = 0;
+
+ /* [ true, true, true ] */
+ test_begin("json format array - [ true, true, true ]");
+ generator = json_generator_init(output, 0);
+ json_generator_set_format(generator, &format);
+ json_generate_array_open(generator);
+ ret = json_generate_true(generator);
+ test_assert(ret > 0);
+ ret = json_generate_true(generator);
+ test_assert(ret > 0);
+ ret = json_generate_true(generator);
+ test_assert(ret > 0);
+ ret = json_generate_array_close(generator);
+ test_assert(ret > 0);
+ json_generator_flush(generator);
+ test_assert(ret > 0);
+ json_generator_deinit(&generator);
+ test_assert(strcmp("[\n"
+ " true,\n"
+ " true,\n"
+ " true\n"
+ "]\n",
+ str_c(buffer)) == 0);
+ test_end();
+ str_truncate(buffer, 0);
+ output->offset = 0;
+
+ /* [ "frop", "friep", "frml" ] */
+ test_begin("json format array - [ \"frop\", \"friep\", \"frml\" ]");
+ generator = json_generator_init(output, 0);
+ json_generator_set_format(generator, &format);
+ json_generate_array_open(generator);
+ ret = json_generate_string(generator, "frop");
+ test_assert(ret > 0);
+ ret = json_generate_string(generator, "friep");
+ test_assert(ret > 0);
+ ret = json_generate_string(generator, "frml");
+ test_assert(ret > 0);
+ ret = json_generate_array_close(generator);
+ test_assert(ret > 0);
+ json_generator_flush(generator);
+ test_assert(ret > 0);
+ json_generator_deinit(&generator);
+ test_assert(strcmp("[\n"
+ " \"frop\",\n"
+ " \"friep\",\n"
+ " \"frml\"\n"
+ "]\n",
+ str_c(buffer)) == 0);
+ test_end();
+ str_truncate(buffer, 0);
+ output->offset = 0;
+
+ /* { "a": [{"d": 1}], "b": [{"e": 2}], "c": [{"f": 3}] } */
+ test_begin("json format object - "
+ "{ \"a\": [{\"d\": 1}], \"b\": [{\"e\": 2}], "
+ "\"c\": [{\"f\": 3}] }");
+ generator = json_generator_init(output, 0);
+ json_generator_set_format(generator, &format);
+ json_generate_object_open(generator);
+ ret = json_generate_object_member(generator, "a");
+ test_assert(ret > 0);
+ json_generate_array_open(generator);
+ json_generate_object_open(generator);
+ ret = json_generate_object_member(generator, "d");
+ test_assert(ret > 0);
+ ret = json_generate_number(generator, 1);
+ ret = json_generate_object_close(generator);
+ test_assert(ret > 0);
+ ret = json_generate_array_close(generator);
+ test_assert(ret > 0);
+ ret = json_generate_object_member(generator, "b");
+ test_assert(ret > 0);
+ json_generate_array_open(generator);
+ json_generate_object_open(generator);
+ ret = json_generate_object_member(generator, "e");
+ test_assert(ret > 0);
+ ret = json_generate_number(generator, 2);
+ ret = json_generate_object_close(generator);
+ test_assert(ret > 0);
+ ret = json_generate_array_close(generator);
+ test_assert(ret > 0);
+ ret = json_generate_object_member(generator, "c");
+ test_assert(ret > 0);
+ json_generate_array_open(generator);
+ json_generate_object_open(generator);
+ ret = json_generate_object_member(generator, "f");
+ test_assert(ret > 0);
+ ret = json_generate_number(generator, 3);
+ ret = json_generate_object_close(generator);
+ test_assert(ret > 0);
+ ret = json_generate_array_close(generator);
+ test_assert(ret > 0);
+ ret = json_generate_object_close(generator);
+ test_assert(ret > 0);
+ json_generator_flush(generator);
+ test_assert(ret > 0);
+ json_generator_deinit(&generator);
+ test_assert(strcmp("{\n"
+ " \"a\": [\n"
+ " {\n"
+ " \"d\": 1\n"
+ " }\n"
+ " ],\n"
+ " \"b\": [\n"
+ " {\n"
+ " \"e\": 2\n"
+ " }\n"
+ " ],\n"
+ " \"c\": [\n"
+ " {\n"
+ " \"f\": 3\n"
+ " }\n"
+ " ]\n"
+ "}\n", str_c(buffer)) == 0);
+ test_end();
+ str_truncate(buffer, 0);
+ output->offset = 0;
+
+ /* trickle */
+ test_begin("json format object - trickle");
+ o_stream_set_max_buffer_size(output, 0);
+ generator = json_generator_init(output, 0);
+ json_generator_set_format(generator, &format);
+ json_generate_object_open(generator);
+ state = 0;
+ for (pos = 0; pos < 65535 && state <= 25; pos++) {
+ o_stream_set_max_buffer_size(output, pos);
+ switch (state) {
+ case 0:
+ ret = json_generate_object_member(generator, "aaaaaa");
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ json_generate_array_open(generator);
+ json_generate_object_open(generator);
+ state++;
+ continue;
+ case 1:
+ ret = json_generate_object_member(generator, "dddddd");
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 2:
+ ret = json_generate_number(generator, 1);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 3:
+ ret = json_generate_object_close(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ json_generate_object_open(generator);
+ state++;
+ continue;
+ case 4:
+ ret = json_generate_object_member(generator, "gggggg");
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 5:
+ ret = json_generate_number(generator, 4);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 6:
+ ret = json_generate_object_close(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 7:
+ ret = json_generate_array_close(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 8:
+ ret = json_generate_object_member(generator, "bbbbbb");
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ json_generate_array_open(generator);
+ json_generate_object_open(generator);
+ state++;
+ continue;
+ case 9:
+ ret = json_generate_object_member(generator, "eeeeee");
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 10:
+ ret = json_generate_number(generator, 2);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 11:
+ ret = json_generate_object_close(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ json_generate_object_open(generator);
+ state++;
+ continue;
+ case 12:
+ ret = json_generate_object_member(generator, "hhhhhh");
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 13:
+ ret = json_generate_number(generator, 5);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 14:
+ ret = json_generate_object_close(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 15:
+ ret = json_generate_array_close(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 16:
+ ret = json_generate_object_member(generator, "cccccc");
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ json_generate_array_open(generator);
+ json_generate_object_open(generator);
+ state++;
+ continue;
+ case 17:
+ ret = json_generate_object_member(generator, "ffffff");
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 18:
+ ret = json_generate_number(generator, 3);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 19:
+ ret = json_generate_object_close(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ json_generate_object_open(generator);
+ state++;
+ continue;
+ case 20:
+ ret = json_generate_object_member(generator, "iiiiii");
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 21:
+ ret = json_generate_number(generator, 6);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 22:
+ ret = json_generate_object_close(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 23:
+ ret = json_generate_array_close(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 24:
+ ret = json_generate_object_close(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ case 25:
+ ret = json_generator_flush(generator);
+ test_assert(ret >= 0);
+ if (ret == 0) break;
+ state++;
+ continue;
+ }
+ }
+ json_generator_deinit(&generator);
+ test_assert(state == 26);
+ test_assert(strcmp("{\n"
+ " \"aaaaaa\": [\n"
+ " {\n"
+ " \"dddddd\": 1\n"
+ " },\n"
+ " {\n"
+ " \"gggggg\": 4\n"
+ " }\n"
+ " ],\n"
+ " \"bbbbbb\": [\n"
+ " {\n"
+ " \"eeeeee\": 2\n"
+ " },\n"
+ " {\n"
+ " \"hhhhhh\": 5\n"
+ " }\n"
+ " ],\n"
+ " \"cccccc\": [\n"
+ " {\n"
+ " \"ffffff\": 3\n"
+ " },\n"
+ " {\n"
+ " \"iiiiii\": 6\n"
+ " }\n"
+ " ]\n"
+ "}\n", str_c(buffer)) == 0);
+ test_end();
+ str_truncate(buffer, 0);
+ output->offset = 0;
+
+ o_stream_destroy(&output);
+ str_free(&buffer);
+}
+
static void test_json_append_escaped(void)
{
string_t *str = t_str_new(32);
static void (*test_functions[])(void) = {
test_json_generate_buffer,
test_json_generate_stream,
+ test_json_generate_formatted,
test_json_append_escaped,
test_json_append_escaped_data,
NULL
output = o_stream_create_buffer(outbuf);
switch (scenario) {
- case 0: case 2:
+ case 0: case 2: case 4: case 6:
pipe1_input = i_stream_create_fd_autoclose(&fd_pipe1[0], 16);
pipe2_input = i_stream_create_fd_autoclose(&fd_pipe2[0], 32);
pipe3_input = i_stream_create_fd_autoclose(&fd_pipe3[0], 64);
break;
- case 1: case 3:
+ case 1: case 3: case 5: case 7:
pipe1_input = i_stream_create_fd_autoclose(&fd_pipe1[0], 128);
pipe2_input = i_stream_create_fd_autoclose(&fd_pipe2[0], 64);
pipe3_input = i_stream_create_fd_autoclose(&fd_pipe3[0], 32);
}
switch (scenario) {
- case 0: case 1:
+ case 0: case 1: case 4: case 5:
pipe1_output = o_stream_create_fd_autoclose(&fd_pipe1[1], 32);
pipe2_output = o_stream_create_fd_autoclose(&fd_pipe2[1], 64);
pipe3_output = o_stream_create_fd_autoclose(&fd_pipe3[1], 128);
break;
- case 2: case 3:
+ case 2: case 3: case 6: case 7:
pipe1_output = o_stream_create_fd_autoclose(&fd_pipe1[1], 64);
pipe2_output = o_stream_create_fd_autoclose(&fd_pipe2[1], 32);
pipe3_output = o_stream_create_fd_autoclose(&fd_pipe3[1], 16);
tproc2.io = io_add_istream(tproc2.input,
test_json_async_io_input_callback, &tproc2);
+ struct json_format json_format;
+
+ switch (scenario) {
+ case 0: case 1: case 2: case 3:
+ break;
+ case 4: case 5: case 6: case 7:
+ i_zero(&json_format);
+ json_format.indent_chars = 2;
+ json_format.new_line = TRUE;
+ json_format.whitespace = TRUE;
+ json_generator_set_format(tproc1.generator, &json_format);
+ break;
+ default:
+ i_unreached();
+ }
+
struct timeout *to = timeout_add(5000, io_loop_stop, ioloop);
iostream_pump_start(tctx.pump_in);
for (i = 0; i < tests_count; i++) T_BEGIN {
test_begin(t_strdup_printf("json io async [%d]", i));
- for (sc = 0; sc < 4; sc++)
+ for (sc = 0; sc < 8; sc++)
test_json_async_io_run(&tests[i], sc);
test_end();
output = o_stream_create_buffer(outbuf);
switch (scenario) {
- case 0: case 2:
+ case 0: case 2: case 4: case 6:
pipe1_input = i_stream_create_fd_autoclose(&fd_pipe1[0], 16);
pipe2_input = i_stream_create_fd_autoclose(&fd_pipe2[0], 32);
pipe3_input = i_stream_create_fd_autoclose(&fd_pipe3[0], 64);
break;
- case 1: case 3:
+ case 1: case 3: case 5: case 7:
pipe1_input = i_stream_create_fd_autoclose(&fd_pipe1[0], 128);
pipe2_input = i_stream_create_fd_autoclose(&fd_pipe2[0], 64);
pipe3_input = i_stream_create_fd_autoclose(&fd_pipe3[0], 32);
}
switch (scenario) {
- case 0: case 1:
+ case 0: case 1: case 4: case 5:
pipe1_output = o_stream_create_fd_autoclose(&fd_pipe1[1], 32);
pipe2_output = o_stream_create_fd_autoclose(&fd_pipe2[1], 64);
pipe3_output = o_stream_create_fd_autoclose(&fd_pipe3[1], 128);
break;
- case 2: case 3:
+ case 2: case 3: case 6: case 7:
pipe1_output = o_stream_create_fd_autoclose(&fd_pipe1[1], 64);
pipe2_output = o_stream_create_fd_autoclose(&fd_pipe2[1], 32);
pipe3_output = o_stream_create_fd_autoclose(&fd_pipe3[1], 16);
tproc2.tctx = &tctx;
tproc2.name = "proc_b";
+ struct json_format json_format;
+
+ switch (scenario) {
+ case 0: case 1: case 2: case 3:
+ break;
+ case 4: case 5: case 6: case 7:
+ i_zero(&json_format);
+ json_format.indent_chars = 2;
+ json_format.new_line = TRUE;
+ json_format.whitespace = TRUE;
+ json_ostream_set_format(tproc1.joutput, &json_format);
+ break;
+ default:
+ i_unreached();
+ }
+
struct timeout *to = timeout_add(5000, io_loop_stop, ioloop);
iostream_pump_start(tctx.pump_in);
for (i = 0; i < tests_count; i++) T_BEGIN {
test_begin(t_strdup_printf("json stream io async [%d]", i));
- for (sc = 0; sc < 4; sc++)
+ for (sc = 0; sc < 8; sc++)
test_json_stream_io_async_run(&tests[i], sc);
test_end();
} T_END;
test_out_reason_quiet("input ok", ret >= 0, error);
if (jtree != NULL)
- json_tree_write_buffer(jtree, outbuf, 0);
+ json_tree_write_buffer(jtree, outbuf, 0, NULL);
test_out_quiet("io match",
strcmp(text_out, str_c(outbuf)) == 0);