1 /*
2 	restinio
3 */
4 
5 /*!
6 	Zlib.
7 */
8 
9 #include <catch2/catch.hpp>
10 
11 #include <restinio/all.hpp>
12 #include <restinio/transforms/zlib.hpp>
13 
14 #include "../random_data_generators.ipp"
15 
16 TEST_CASE( "Create parameters for zlib transformators" , "[zlib][params][create_params]" )
17 {
18 	namespace rtz = restinio::transforms::zlib;
19 
20 	{
21 		auto params = rtz::make_deflate_compress_params();
22 
23 		REQUIRE( rtz::params_t::operation_t::compress == params.operation() );
24 		REQUIRE( rtz::params_t::format_t::deflate == params.format() );
25 		REQUIRE( -1 == params.level() );
26 	}
27 
28 	{
29 		auto params = rtz::make_deflate_compress_params( 9 );
30 
31 		REQUIRE( rtz::params_t::operation_t::compress == params.operation() );
32 		REQUIRE( rtz::params_t::format_t::deflate == params.format() );
33 		REQUIRE( 9 == params.level() );
34 	}
35 
36 	{
37 		auto params = rtz::make_gzip_compress_params();
38 
39 		REQUIRE( rtz::params_t::operation_t::compress == params.operation() );
40 		REQUIRE( rtz::params_t::format_t::gzip == params.format() );
41 		REQUIRE( -1 == params.level() );
42 	}
43 
44 	{
45 		auto params = rtz::make_gzip_compress_params( 3 );
46 
47 		REQUIRE( rtz::params_t::operation_t::compress == params.operation() );
48 		REQUIRE( rtz::params_t::format_t::gzip == params.format() );
49 		REQUIRE( 3 == params.level() );
50 	}
51 
52 	{
53 		auto params = rtz::make_deflate_decompress_params();
54 
55 		REQUIRE( rtz::params_t::operation_t::decompress == params.operation() );
56 		REQUIRE( rtz::params_t::format_t::deflate == params.format() );
57 	}
58 
59 	{
60 		auto params = rtz::make_gzip_decompress_params();
61 
62 		REQUIRE( rtz::params_t::operation_t::decompress == params.operation() );
63 		REQUIRE( rtz::params_t::format_t::gzip == params.format() );
64 	}
65 
66 	{
67 		auto params = rtz::make_identity_params();
68 
69 		REQUIRE( rtz::params_t::format_t::identity == params.format() );
70 	}
71 }
72 
73 TEST_CASE( "Default parameters for zlib transformators" , "[zlib][params][defaults]" )
74 {
75 	namespace rtz = restinio::transforms::zlib;
76 
77 	auto params = rtz::make_deflate_compress_params();
78 
79 	REQUIRE( rtz::default_window_bits == params.window_bits() );
80 	REQUIRE( rtz::default_mem_level == params.mem_level() );
81 	REQUIRE( rtz::default_strategy == params.strategy() );
82 	REQUIRE( rtz::default_output_reserve_buffer_size ==
83 				params.reserve_buffer_size() );
84 }
85 
86 TEST_CASE( "Setting parameters for zlib transformators: window_bits" , "[zlib][params][window_bits]" )
87 {
88 	namespace rtz = restinio::transforms::zlib;
89 
90 	{
91 		auto params = rtz::make_deflate_compress_params();
92 
93 		REQUIRE_NOTHROW( params.window_bits( 12 ) );
94 		REQUIRE( 12 == params.window_bits() );
95 		REQUIRE_NOTHROW( params.window_bits( 8 ) );
96 		REQUIRE( 9 == params.window_bits() );
97 
98 		REQUIRE_NOTHROW( params.window_bits( 13 ) );
99 		REQUIRE( 13 == params.window_bits() );
100 
101 		REQUIRE_NOTHROW( params.window_bits( 9 ) );
102 		REQUIRE( 9 == params.window_bits() );
103 
104 		REQUIRE_THROWS( params.window_bits( 0 ) );
105 		REQUIRE( 9 == params.window_bits() );
106 
107 		REQUIRE_THROWS( params.window_bits( 1 ) );
108 		REQUIRE_THROWS( params.window_bits( 3 ) );
109 		REQUIRE_THROWS( params.window_bits( 16 ) );
110 		REQUIRE_THROWS( params.window_bits( 17 ) );
111 	}
112 
113 	{
114 		auto params = rtz::make_deflate_decompress_params();
115 		REQUIRE_NOTHROW( params.window_bits( 0 ) );
116 		REQUIRE( 0 == params.window_bits() );
117 	}
118 }
119 
120 TEST_CASE( "Setting parameters for zlib transformators: mem_level" , "[zlib][params][mem_level]" )
121 {
122 	namespace rtz = restinio::transforms::zlib;
123 
124 	{
125 		auto params = rtz::make_deflate_compress_params();
126 
127 		REQUIRE_NOTHROW( params.mem_level( 1 ) );
128 		REQUIRE( 1 == params.mem_level() );
129 		REQUIRE_NOTHROW( params.mem_level( 2 ) );
130 		REQUIRE( 2 == params.mem_level() );
131 		REQUIRE_NOTHROW( params.mem_level( 8 ) );
132 		REQUIRE( 8 == params.mem_level() );
133 		REQUIRE_NOTHROW( params.mem_level( MAX_MEM_LEVEL ) );
134 		REQUIRE( MAX_MEM_LEVEL == params.mem_level() );
135 
136 		REQUIRE_THROWS( params.mem_level( -1 ) );
137 		REQUIRE_THROWS( params.mem_level( 0 ) );
138 		REQUIRE_THROWS( params.mem_level( MAX_MEM_LEVEL + 1 ) );
139 	}
140 }
141 
142 TEST_CASE( "Setting parameters for zlib transformators: strategy" , "[zlib][params][strategy]" )
143 {
144 	namespace rtz = restinio::transforms::zlib;
145 
146 	{
147 		auto params = rtz::make_deflate_compress_params();
148 
149 		REQUIRE_NOTHROW( params.strategy( Z_DEFAULT_STRATEGY ) );
150 		REQUIRE( Z_DEFAULT_STRATEGY == params.strategy() );
151 		REQUIRE_NOTHROW( params.strategy( Z_FILTERED ) );
152 		REQUIRE( Z_FILTERED == params.strategy() );
153 		REQUIRE_NOTHROW( params.strategy( Z_HUFFMAN_ONLY ) );
154 		REQUIRE( Z_HUFFMAN_ONLY == params.strategy() );
155 		REQUIRE_NOTHROW( params.strategy( Z_RLE ) );
156 		REQUIRE( Z_RLE == params.strategy() );
157 		REQUIRE_THROWS( params.strategy( Z_RLE + 4242 ) );
158 	}
159 }
160 
161 TEST_CASE( "Setting parameters for zlib transformators: reserve_buffer_size" , "[zlib][params][reserve_buffer_size]" )
162 {
163 	namespace rtz = restinio::transforms::zlib;
164 
165 	{
166 		auto params = rtz::make_deflate_compress_params();
167 
168 		REQUIRE_NOTHROW( params.reserve_buffer_size( 512UL ) );
169 		REQUIRE( 512UL == params.reserve_buffer_size() );
170 		REQUIRE_NOTHROW( params.reserve_buffer_size( 10UL ) );
171 		REQUIRE( 10UL == params.reserve_buffer_size() );
172 		REQUIRE_NOTHROW( params.reserve_buffer_size( 4096UL ) );
173 		REQUIRE( 4096UL == params.reserve_buffer_size() );
174 		REQUIRE_THROWS( params.reserve_buffer_size( 9 ) );
175 		REQUIRE_THROWS( params.reserve_buffer_size( 1 ) );
176 		REQUIRE_THROWS( params.reserve_buffer_size( 0 ) );
177 	}
178 }
179 
180 TEST_CASE( "deflate" , "[zlib][compress][decompress][deflate]" )
181 {
182 	namespace rtz = restinio::transforms::zlib;
183 
184 	std::srand( static_cast<unsigned int>(std::time( nullptr )) );
185 
186 	{
187 		rtz::zlib_t zc{ rtz::make_deflate_compress_params() };
188 
189 		std::string
190 			input_data{
191 				"The zlib compression library provides "
192 				"in-memory compression and decompression functions, "
193 				"including integrity checks of the uncompressed data." };
194 
195 		REQUIRE_NOTHROW( zc.write( input_data ) );
196 		REQUIRE_NOTHROW( zc.write( input_data ) );
197 		REQUIRE_NOTHROW( zc.complete() );
198 
199 		const auto out_size = zc.output_size();
200 		const auto out_data = zc.giveaway_output();
201 		REQUIRE( out_size == out_data.size() );
202 		REQUIRE( 10 < out_data.size() );
203 
204 		rtz::zlib_t zd{ rtz::make_deflate_decompress_params() };
205 
206 		REQUIRE_NOTHROW( zd.write( out_data ) );
207 		REQUIRE_NOTHROW( zd.complete() );
208 
209 		const auto decompression_out_size = zd.output_size();
210 		const auto decompression_out_data = zd.giveaway_output();
211 		REQUIRE( decompression_out_size == decompression_out_data.size() );
212 		REQUIRE( decompression_out_data == input_data+input_data );
213 	}
214 
215 	{
216 		const std::size_t chunk_size = 1024;
217 		const std::size_t chunk_count = 128;
218 
219 		struct test_setting_t
220 		{
221 			std::size_t m_reserve_buffer_size{ 1024UL * (1UL << (std::rand() % 11UL) ) };
222 			std::size_t m_repeats_level{ 1 + std::rand() % 42UL };
223 			int m_data_gen{ std::rand() % 2 };
224 			int m_do_flush{ std::rand() % 2 };
225 			int m_window_bits{ 9 + (std::rand() % (MAX_WBITS - 8) ) };
226 			int m_mem_level{ 1 + (std::rand() % ( MAX_MEM_LEVEL ) )};
227 		};
228 
229 		unsigned int tests_count = 250;
230 
231 		while( 0 != tests_count-- )
232 		{
233 			test_setting_t ts;
234 			// std::cout << "tests_count = " << tests_count
235 			// 	<< "; ts = "
236 			// 		<< "{" << ts.m_reserve_buffer_size
237 			// 		<< "," << ts.m_repeats_level
238 			// 		<< "," << ts.m_data_gen
239 			// 		<< "," << ts.m_do_flush
240 			// 		<< "," << ts.m_window_bits
241 			// 		<< "," << ts.m_mem_level
242 			// 		<< "}" << std::endl;
243 
244 			const std::string input_data =
245 				ts.m_data_gen == 0 ?
246 					create_random_text( chunk_size * chunk_count, ts.m_repeats_level ) :
247 					create_random_binary( chunk_size * chunk_count, ts.m_repeats_level );
248 
249 			rtz::zlib_t zc{
250 				rtz::make_deflate_compress_params()
251 					.reserve_buffer_size( ts.m_reserve_buffer_size + 512 )
252 					.window_bits( ts.m_window_bits )
253 					.mem_level( ts.m_mem_level ) };
254 
255 			for( std::size_t i = 0; i < chunk_count; ++i )
256 			{
257 				const restinio::string_view_t
258 					chunk{ input_data.data() + i * chunk_size, chunk_size };
259 
260 				REQUIRE_NOTHROW( zc.write( chunk ) );
261 
262 				if( ts.m_do_flush ) zc.flush();
263 			}
264 
265 			REQUIRE_NOTHROW( zc.complete() );
266 			const auto out_size = zc.output_size();
267 			const auto out_data = zc.giveaway_output();
268 			REQUIRE( out_size == out_data.size() );
269 			REQUIRE( 10 < out_data.size() );
270 
271 			rtz::zlib_t zd{
272 				rtz::make_deflate_decompress_params()
273 					.reserve_buffer_size( ts.m_reserve_buffer_size + 512 )
274 					.window_bits( ts.m_window_bits )
275 					.mem_level( ts.m_mem_level ) };
276 
277 			for(
278 				const char* buf = out_data.data();
279 				buf < out_data.data() + out_data.size();
280 				buf += chunk_size )
281 			{
282 				const restinio::string_view_t
283 					chunk{
284 						buf,
285 						std::min< std::size_t >(
286 							chunk_size,
287 							out_data.size() - (buf - out_data.data() ) ) };
288 
289 				REQUIRE_NOTHROW( zd.write( chunk ) );
290 
291 				if( ts.m_do_flush ) zd.flush();
292 			}
293 
294 			zd.complete();
295 			const auto decompression_out_size = zd.output_size();
296 			const auto decompression_out_data = zd.giveaway_output();
297 			REQUIRE( decompression_out_size == decompression_out_data.size() );
298 			REQUIRE( decompression_out_data == input_data );
299 		}
300 	}
301 }
302 
303 TEST_CASE( "gzip" , "[zlib][compress][decompress][gzip]" )
304 {
305 	namespace rtz = restinio::transforms::zlib;
306 
307 	std::srand( static_cast<unsigned int>(std::time( nullptr )) );
308 
309 	{
310 		rtz::zlib_t zc{ rtz::make_gzip_compress_params() };
311 
312 		std::string
313 			input_data{
314 				"The zlib compression library provides "
315 				"in-memory compression and decompression functions, "
316 				"including integrity checks of the uncompressed data." };
317 
318 		REQUIRE_NOTHROW( zc.write( input_data ) );
319 		REQUIRE_NOTHROW( zc.write( input_data ) );
320 		REQUIRE_NOTHROW( zc.complete() );
321 
322 		const auto out_size = zc.output_size();
323 		const auto out_data = zc.giveaway_output();
324 		REQUIRE( out_size == out_data.size() );
325 		REQUIRE( 10 < out_data.size() );
326 
327 		rtz::zlib_t zd{ rtz::make_gzip_decompress_params() };
328 
329 		REQUIRE_NOTHROW( zd.write( out_data ) );
330 		REQUIRE_NOTHROW( zd.complete() );
331 
332 		const auto decompression_out_size = zd.output_size();
333 		const auto decompression_out_data = zd.giveaway_output();
334 		REQUIRE( decompression_out_size == decompression_out_data.size() );
335 		REQUIRE( decompression_out_data == input_data+input_data );
336 	}
337 
338 	{
339 		const std::size_t chunk_size = 1024;
340 		const std::size_t chunk_count = 128;
341 
342 		struct test_setting_t
343 		{
344 			std::size_t m_reserve_buffer_size{ 1024UL * (1UL << (std::rand() % 11UL) ) };
345 			std::size_t m_repeats_level{ 1 + std::rand() % 42UL };
346 			int m_data_gen{ std::rand() % 2 };
347 			int m_do_flush{ std::rand() % 2 };
348 			int m_window_bits{ 9 + (std::rand() % (MAX_WBITS - 8) ) };
349 			int m_mem_level{ 1 + (std::rand() % ( MAX_MEM_LEVEL ) )};
350 		};
351 
352 		unsigned int tests_count = 250;
353 
354 		while( 0 != tests_count-- )
355 		{
356 			test_setting_t ts;
357 			// std::cout << "tests_count = " << tests_count
358 			// 	<< "; ts = "
359 			// 		<< "{" << ts.m_reserve_buffer_size
360 			// 		<< "," << ts.m_repeats_level
361 			// 		<< "," << ts.m_data_gen
362 			// 		<< "," << ts.m_do_flush
363 			// 		<< "," << ts.m_window_bits
364 			// 		<< "," << ts.m_mem_level
365 			// 		<< "}" << std::endl;
366 
367 			const std::string input_data =
368 				ts.m_data_gen == 0 ?
369 					create_random_text( chunk_size * chunk_count, ts.m_repeats_level ) :
370 					create_random_binary( chunk_size * chunk_count, ts.m_repeats_level );
371 
372 			rtz::zlib_t zc{
373 				rtz::make_gzip_compress_params()
374 					.reserve_buffer_size( ts.m_reserve_buffer_size + 512 )
375 					.window_bits( ts.m_window_bits )
376 					.mem_level( ts.m_mem_level ) };
377 
378 			for( std::size_t i = 0; i < chunk_count; ++i )
379 			{
380 				const restinio::string_view_t
381 					chunk{ input_data.data() + i * chunk_size, chunk_size };
382 
383 				REQUIRE_NOTHROW( zc.write( chunk ) );
384 
385 				if( ts.m_do_flush ) zc.flush();
386 			}
387 
388 			REQUIRE_NOTHROW( zc.complete() );
389 			const auto out_size = zc.output_size();
390 			const auto out_data = zc.giveaway_output();
391 			REQUIRE( out_size == out_data.size() );
392 			REQUIRE( 10 < out_data.size() );
393 
394 			rtz::zlib_t zd{
395 				rtz::make_gzip_decompress_params()
396 					.reserve_buffer_size( ts.m_reserve_buffer_size + 512 )
397 					.window_bits( ts.m_window_bits )
398 					.mem_level( ts.m_mem_level ) };
399 
400 			for(
401 				const char* buf = out_data.data();
402 				buf < out_data.data() + out_data.size();
403 				buf += chunk_size )
404 			{
405 				const restinio::string_view_t
406 					chunk{
407 						buf,
408 						std::min< std::size_t >(
409 							chunk_size,
410 							out_data.size() - (buf - out_data.data() ) ) };
411 
412 				REQUIRE_NOTHROW( zd.write( chunk ) );
413 
414 				if( ts.m_do_flush ) zd.flush();
415 			}
416 
417 			zd.complete();
418 			const auto decompression_out_size = zd.output_size();
419 			const auto decompression_out_data = zd.giveaway_output();
420 			REQUIRE( decompression_out_size == decompression_out_data.size() );
421 			REQUIRE( decompression_out_data == input_data );
422 		}
423 	}
424 }
425 
426 TEST_CASE( "identity" , "[zlib][identity]" )
427 {
428 	namespace rtz = restinio::transforms::zlib;
429 
430 	std::srand( static_cast<unsigned int>(std::time( nullptr )) );
431 
432 	{
433 		rtz::zlib_t zc{ rtz::make_identity_params() };
434 
435 		std::string
436 			input_data{
437 				"The zlib compression library provides "
438 				"in-memory compression and decompression functions, "
439 				"including integrity checks of the uncompressed data." };
440 
441 		REQUIRE_NOTHROW( zc.write( input_data ) );
442 		REQUIRE_NOTHROW( zc.write( input_data ) );
443 		REQUIRE_NOTHROW( zc.complete() );
444 
445 		const auto out_data = zc.giveaway_output();
446 		REQUIRE( out_data == input_data + input_data );
447 	}
448 }
449 
450 TEST_CASE( "transform functions" , "[zlib][transform]" )
451 {
452 	namespace rtz = restinio::transforms::zlib;
453 
454 	const std::string
455 		input_data{
456 			"The zlib compression library provides "
457 			"in-memory compression and decompression functions, "
458 			"including integrity checks of the uncompressed data." };
459 
460 	REQUIRE( input_data == rtz::transform( input_data, rtz::make_identity_params() ) );
461 
462 	REQUIRE( input_data ==
463 		rtz::transform(
464 			rtz::transform(
465 				input_data,
466 				rtz::make_deflate_compress_params() ),
467 			rtz::make_deflate_decompress_params() ) );
468 
469 	REQUIRE( input_data ==
470 		rtz::transform(
471 			rtz::transform(
472 				input_data,
473 				rtz::make_gzip_compress_params() ),
474 			rtz::make_gzip_decompress_params() ) );
475 
476 	REQUIRE( input_data ==
477 		rtz::deflate_decompress( rtz::deflate_compress( input_data ) ) );
478 
479 	REQUIRE( input_data ==
480 		rtz::gzip_decompress( rtz::gzip_compress( input_data ) ) );
481 }
482 
483 TEST_CASE( "complete" , "[zlib][compress][decompress][commplete]" )
484 {
485 	namespace rtz = restinio::transforms::zlib;
486 
487 	std::srand( static_cast<unsigned int>(std::time( nullptr )) );
488 
489 	{
490 		rtz::zlib_t zc{ rtz::make_gzip_compress_params() };
491 		REQUIRE_FALSE( zc.is_completed() );
492 
493 		std::string
494 			input_data{
495 				"The zlib compression library provides "
496 				"in-memory compression and decompression functions, "
497 				"including integrity checks of the uncompressed data." };
498 
499 		REQUIRE_NOTHROW( zc.write( input_data ) );
500 		REQUIRE_FALSE( zc.is_completed() );
501 
502 		REQUIRE_NOTHROW( zc.flush() );
503 		REQUIRE_FALSE( zc.is_completed() );
504 
505 		REQUIRE_NOTHROW( zc.write( input_data ) );
506 		REQUIRE_FALSE( zc.is_completed() );
507 
508 		REQUIRE_NOTHROW( zc.complete() );
509 		REQUIRE( zc.is_completed() );
510 		REQUIRE_THROWS( zc.complete() );
511 		REQUIRE( zc.is_completed() );
512 
513 		const auto out_size = zc.output_size();
514 		const auto out_data = zc.giveaway_output();
515 		REQUIRE( out_size == out_data.size() );
516 
517 		rtz::zlib_t zd{ rtz::make_gzip_decompress_params() };
518 		REQUIRE_FALSE( zd.is_completed() );
519 
520 		REQUIRE_NOTHROW( zd.write( out_data.substr(0, out_data.size()/2 ) ) );
521 		REQUIRE_FALSE( zd.is_completed() );
522 
523 		REQUIRE_NOTHROW( zd.flush() );
524 		REQUIRE_FALSE( zd.is_completed() );
525 
526 		REQUIRE_NOTHROW( zd.write( out_data.substr( out_data.size()/2 ) ) );
527 		REQUIRE_FALSE( zd.is_completed() );
528 
529 		REQUIRE_NOTHROW( zd.complete() );
530 		REQUIRE( zd.is_completed() );
531 		REQUIRE_THROWS( zd.complete() );
532 		REQUIRE( zd.is_completed() );
533 
534 		const auto decompression_out_size = zd.output_size();
535 		const auto decompression_out_data = zd.giveaway_output();
536 		REQUIRE( decompression_out_size == decompression_out_data.size() );
537 		REQUIRE( decompression_out_data == input_data + input_data );
538 	}
539 }
540 
541 TEST_CASE( "take output" , "[zlib][compress][decompress][output]" )
542 {
543 	namespace rtz = restinio::transforms::zlib;
544 
545 	std::srand( static_cast<unsigned int>(std::time( nullptr )) );
546 
547 	{
548 		rtz::zlib_t zc{ rtz::make_gzip_compress_params() };
549 
550 		std::string
551 			input_data{
552 				"The zlib compression library provides "
553 				"in-memory compression and decompression functions, "
554 				"including integrity checks of the uncompressed data." };
555 
556 		std::string out_data;
557 		REQUIRE_NOTHROW( zc.write( input_data ) );
558 		REQUIRE_NOTHROW( out_data += zc.giveaway_output() );
559 		REQUIRE_NOTHROW( zc.giveaway_output() == "" );
560 
561 		REQUIRE_NOTHROW( zc.flush() );
562 		REQUIRE_NOTHROW( out_data += zc.giveaway_output() );
563 		REQUIRE_NOTHROW( zc.giveaway_output() == "" );
564 
565 		REQUIRE_NOTHROW( zc.write( input_data ) );
566 		REQUIRE_NOTHROW( out_data += zc.giveaway_output() );
567 		REQUIRE_NOTHROW( zc.giveaway_output() == "" );
568 
569 		REQUIRE_NOTHROW( zc.complete() );
570 		REQUIRE_NOTHROW( out_data += zc.giveaway_output() );
571 		REQUIRE_NOTHROW( zc.giveaway_output() == "" );
572 
573 		rtz::zlib_t zd{ rtz::make_gzip_decompress_params() };
574 		std::string decompression_out_data;
575 
576 		REQUIRE_NOTHROW( zd.write( out_data.substr(0, out_data.size()/2 ) ) );
577 		REQUIRE_NOTHROW( decompression_out_data += zd.giveaway_output() );
578 		REQUIRE_NOTHROW( zd.giveaway_output() == "" );
579 
580 		REQUIRE_NOTHROW( zd.flush() );
581 		REQUIRE_NOTHROW( decompression_out_data += zd.giveaway_output() );
582 		REQUIRE_NOTHROW( zd.giveaway_output() == "" );
583 
584 		REQUIRE_NOTHROW( zd.write( out_data.substr( out_data.size()/2 ) ) );
585 		REQUIRE_NOTHROW( decompression_out_data += zd.giveaway_output() );
586 		REQUIRE_NOTHROW( zd.giveaway_output() == "" );
587 
588 		REQUIRE_NOTHROW( zd.complete() );
589 		REQUIRE_NOTHROW( decompression_out_data += zd.giveaway_output() );
590 		REQUIRE_NOTHROW( zd.giveaway_output() == "" );
591 
592 		REQUIRE( decompression_out_data == input_data + input_data );
593 	}
594 
595 	{
596 		rtz::zlib_t zc{ rtz::make_identity_params() };
597 
598 		std::string
599 			input_data{
600 				"The zlib compression library provides "
601 				"in-memory compression and decompression functions, "
602 				"including integrity checks of the uncompressed data." };
603 
604 		std::string out_data;
605 		REQUIRE_NOTHROW( zc.write( input_data ) );
606 		REQUIRE_NOTHROW( out_data += zc.giveaway_output() );
607 		REQUIRE( out_data == input_data );
608 		REQUIRE_NOTHROW( zc.giveaway_output() == "" );
609 
610 		REQUIRE_NOTHROW( zc.flush() );
611 		REQUIRE_NOTHROW( out_data += zc.giveaway_output() );
612 		REQUIRE( out_data == input_data );
613 		REQUIRE_NOTHROW( zc.giveaway_output() == "" );
614 
615 		REQUIRE_NOTHROW( zc.write( input_data ) );
616 		REQUIRE_NOTHROW( out_data += zc.giveaway_output() );
617 		REQUIRE( out_data == input_data + input_data );
618 		REQUIRE_NOTHROW( zc.giveaway_output() == "" );
619 
620 		REQUIRE_NOTHROW( zc.complete() );
621 		REQUIRE_NOTHROW( out_data += zc.giveaway_output() );
622 		REQUIRE( out_data == input_data + input_data );
623 		REQUIRE_NOTHROW( zc.giveaway_output() == "" );
624 	}
625 }
626 
627 TEST_CASE( "write check input size" , "[zlib][write][large input]" )
628 {
629 	namespace rtz = restinio::transforms::zlib;
630 
631 	std::srand( static_cast<unsigned int>(std::time( nullptr )) );
632 
633 	if( sizeof( restinio::string_view_t::size_type ) == 8 )
634 	{
635 		rtz::zlib_t zc{ rtz::make_gzip_compress_params() };
636 
637 		const char * s =
638 			"The zlib compression library provides "
639 			"in-memory compression and decompression functions, "
640 			"including integrity checks of the uncompressed data.";
641 
642 		restinio::string_view_t large_input{
643 			s,
644 			restinio::string_view_t::size_type{ 1 } + std::numeric_limits< decltype( z_stream::avail_in ) >::max() };
645 
646 		REQUIRE_THROWS( zc.write( large_input ) );
647 	}
648 }
649