static void test_message_parser_small_blocks(void)
{
	struct message_parser_ctx *parser;
	struct istream *input;
	struct message_part *parts, *parts2;
	struct message_block block;
	unsigned int i, end_of_headers_idx;
	pool_t pool;
	int ret;

	test_begin("message parser in small blocks");
	pool = pool_alloconly_create("message parser", 10240);
	input = test_istream_create(test_msg);

	/* full parsing */
	parser = message_parser_init(pool, input, 0, 0);
	while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
	test_assert(ret < 0);
	test_assert(message_parser_deinit(&parser, &parts) == 0);

	/* parsing in small blocks */
	i_stream_seek(input, 0);
	test_istream_set_allow_eof(input, FALSE);

	parser = message_parser_init(pool, input, 0, 0);
	for (i = 1; i <= TEST_MSG_LEN*2+1; i++) {
		test_istream_set_size(input, i/2);
		if (i > TEST_MSG_LEN*2)
			test_istream_set_allow_eof(input, TRUE);
		while ((ret = message_parser_parse_next_block(parser,
							      &block)) > 0) ;
		test_assert((ret == 0 && i <= TEST_MSG_LEN*2) ||
			    (ret < 0 && i > TEST_MSG_LEN*2));
	}
	test_assert(message_parser_deinit(&parser, &parts2) == 0);
	test_assert(msg_parts_cmp(parts, parts2));

	/* parsing in small blocks from preparsed parts */
	i_stream_seek(input, 0);
	test_istream_set_allow_eof(input, FALSE);

	end_of_headers_idx = (strstr(test_msg, "\n-----") - test_msg);
	parser = message_parser_init_from_parts(parts, input, 0,
					MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK);
	for (i = 1; i <= TEST_MSG_LEN*2+1; i++) {
		test_istream_set_size(input, i/2);
		if (i > TEST_MSG_LEN*2)
			test_istream_set_allow_eof(input, TRUE);
		while ((ret = message_parser_parse_next_block(parser,
							      &block)) > 0) ;
		test_assert((ret == 0 && i/2 <= end_of_headers_idx) ||
			    (ret < 0 && i/2 > end_of_headers_idx));
	}
	test_assert(message_parser_deinit(&parser, &parts2) == 0);
	test_assert(msg_parts_cmp(parts, parts2));

	i_stream_unref(&input);
	pool_unref(&pool);
	test_end();
}
예제 #2
0
static int
message_search_msg_real(struct message_search_context *ctx,
			struct istream *input, struct message_part *parts,
			const char **error_r)
{
	const enum message_header_parser_flags hdr_parser_flags =
		MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
	struct message_parser_ctx *parser_ctx;
	struct message_block raw_block;
	struct message_part *new_parts;
	int ret;

	message_search_reset(ctx);

	if (parts != NULL) {
		parser_ctx = message_parser_init_from_parts(parts,
						input, hdr_parser_flags, 0);
	} else {
		parser_ctx = message_parser_init(pool_datastack_create(),
						 input, hdr_parser_flags, 0);
	}

	while ((ret = message_parser_parse_next_block(parser_ctx,
						      &raw_block)) > 0) {
		if (message_search_more(ctx, &raw_block)) {
			ret = 1;
			break;
		}
	}
	i_assert(ret != 0);
	if (ret < 0 && input->stream_errno == 0) {
		/* normal exit */
		ret = 0;
	}
	if (message_parser_deinit_from_parts(&parser_ctx, &new_parts, error_r) < 0) {
		/* broken parts */
		ret = -1;
	}
	return ret;
}