Line data Source code
1 : #include <iostream>
2 : #include <iow/io/aux/read_buffer.hpp>
3 : #include <fas/testing.hpp>
4 : #include <cstring>
5 : #include <mutex>
6 : #include <cstdlib>
7 : //#include <ucommon/socket.h>
8 :
9 : typedef std::vector<char> data_type;
10 : typedef std::string sep_type;
11 : typedef ::iow::io::read_buffer read_buffer;
12 : typedef read_buffer::options_type options;
13 :
14 : UNIT(basic_test, "")
15 : {
16 : using namespace fas::testing;
17 : read_buffer buf;
18 : options opt;
19 : buf.get_options(opt);
20 : opt.bufsize = 3;
21 : buf.set_options(opt);
22 :
23 : //auto tmp = std::make_unique<data_type>(3);
24 : //! auto att = buf.attach(std::move(tmp));
25 :
26 : //t << is_true<assert>( att == nullptr) << FAS_TESTING_FILE_LINE;
27 :
28 : // Еще один attach() без next() запрещен
29 : //tmp = std::make_unique<data_type>(3);
30 : //! att = buf.attach(std::move(tmp));
31 : //t << is_true<assert>( att != nullptr) << FAS_TESTING_FILE_LINE;
32 :
33 : auto nxt1 = buf.next();
34 : t << is_true<assert>( nxt1.first != nullptr) << FAS_TESTING_FILE_LINE;
35 : t << is_true<assert>( nxt1.second == 3) << FAS_TESTING_FILE_LINE;
36 : std::strcpy(nxt1.first, "ab");
37 : // Еще один next() без confirm() запрещен
38 : auto nxt2 = buf.next();
39 : t << is_true<assert>( nxt2.first == nullptr) << FAS_TESTING_FILE_LINE;
40 : t << is_true<assert>( nxt2.second == 0) << FAS_TESTING_FILE_LINE;
41 :
42 : // После next() разрешен attach()
43 : //tmp = std::make_unique<data_type>(3);
44 : //! att = buf.attach(std::move(tmp));
45 : //t << is_true<assert>( att == nullptr) << FAS_TESTING_FILE_LINE;
46 :
47 : // Но еще один attach() без next() все еще запрещен
48 : //tmp = std::make_unique<data_type>(3);
49 : //! att = buf.attach(std::move(tmp));
50 : //t << is_true<assert>( att != nullptr) << FAS_TESTING_FILE_LINE;
51 :
52 : nxt1.second = 2;
53 : nxt1.first -= 1;
54 : bool res = buf.confirm(nxt1);
55 : t << is_false<assert>( res ) << FAS_TESTING_FILE_LINE;
56 : nxt1.first += 2;
57 : res = buf.confirm(nxt1);
58 : t << is_false<assert>( res ) << FAS_TESTING_FILE_LINE;
59 : nxt1.first -= 1;
60 : nxt1.second = 4096 + 1;
61 : res = buf.confirm(nxt1);
62 : t << is_false<assert>( res ) << FAS_TESTING_FILE_LINE;
63 : nxt1.second = 2;
64 : res = buf.confirm(nxt1);
65 : t << is_true<assert>( res ) << FAS_TESTING_FILE_LINE;
66 :
67 : auto d = buf.detach();
68 : t << is_true<assert>( d != nullptr) << FAS_TESTING_FILE_LINE;
69 : t << stop;
70 :
71 : auto str = std::string(d->begin(), d->end());
72 : t << equal_str<assert>( std::string("ab"), str ) << FAS_TESTING_FILE_LINE;
73 : }
74 :
75 : template<typename T>
76 : void test_buff1(T& t, read_buffer& buf, std::vector<std::string> reads, std::vector<std::string> chk)
77 : {
78 : using namespace fas::testing;
79 : t << message("test_buff1");
80 : std::string input;
81 : std::string result;
82 : std::vector<std::string> vectres;
83 : for (auto& s: reads)
84 : {
85 : input+= s;
86 : auto p = buf.next();
87 : t << is_true<assert>(s.size() <= p.second) << FAS_TESTING_FILE_LINE;
88 : t << stop;
89 : //std::strcpy( p.first, s.c_str());
90 : std::copy(s.begin(), s.end(), p.first );
91 : p.second = s.size();
92 : bool confirm = buf.confirm(p);
93 : t << is_true<assert>( confirm ) << FAS_TESTING_FILE_LINE;
94 : auto d = buf.detach();
95 : while ( d!=nullptr )
96 : {
97 : t << is_true<assert>( !d->empty() ) << FAS_TESTING_FILE_LINE;
98 : t << stop;
99 : auto str = std::string(d->begin(), d->end());
100 : vectres.push_back(str);
101 : result += vectres.back();
102 : d = buf.detach();
103 : }
104 : }
105 : t << equal<expect>(input, result) << input << "!=" << result << FAS_TESTING_FILE_LINE;
106 : if ( !chk.empty() )
107 : t << equal<expect>(chk, vectres) << FAS_TESTING_FILE_LINE;
108 : }
109 :
110 : template<typename T>
111 : void test_buff2(T& t, read_buffer& buf, std::vector<std::string> reads, std::vector<std::string> chk)
112 : {
113 : using namespace fas::testing;
114 : t << message("test_buff2");
115 : std::string input;
116 : std::string result;
117 : for (auto& s: reads)
118 : {
119 : input+= s;
120 : auto p = buf.next();
121 : t << is_true<assert>(s.size() <= p.second) << FAS_TESTING_FILE_LINE;
122 : t << stop;
123 : //std::strcpy( p.first, s.c_str());
124 : std::copy(s.begin(), s.end(), p.first );
125 : p.second = s.size();
126 : bool confirm = buf.confirm(p);
127 : t << is_true<assert>( confirm ) << FAS_TESTING_FILE_LINE;
128 : }
129 :
130 : std::vector<std::string> vectres;
131 : auto d = buf.detach();
132 : while ( d!=nullptr )
133 : {
134 : t << is_true<assert>( !d->empty() ) << FAS_TESTING_FILE_LINE;
135 : t << stop;
136 : auto str = std::string(d->begin(), d->end());
137 : vectres.push_back(str);
138 : result += str;
139 : d = buf.detach();
140 : }
141 :
142 : t << equal<expect>(input, result) << input << "!=" << result << FAS_TESTING_FILE_LINE;
143 : if ( !chk.empty() )
144 : {
145 : options opt;
146 : buf.get_options(opt);
147 : if ( !opt.sep.empty() )
148 : {
149 : t << equal<expect>(chk.size(), vectres.size()) << FAS_FL;
150 : for (size_t i = 0 ; i != chk.size(); i++)
151 : if ( i < vectres.size() )
152 : {
153 : t << equal<expect>(chk[i], vectres[i]) << FAS_TESTING_FILE_LINE;
154 : }
155 : }
156 : }
157 : }
158 :
159 :
160 : template<typename T>
161 : void do_detach(T& t, read_buffer& buf, std::vector<std::string>& vectres, std::string& result)
162 : {
163 : using namespace fas::testing;
164 : auto d = buf.detach();
165 : while ( d!=nullptr )
166 : {
167 : t << is_true<assert>( !d->empty() ) << FAS_TESTING_FILE_LINE;
168 : t << stop;
169 : auto str = std::string(d->begin(), d->end());
170 : //t << message("detach: ") << str;
171 : //t << message("-2-");
172 : vectres.push_back(str);
173 : result += vectres.back();
174 : d = buf.detach();
175 : }
176 : }
177 :
178 : template<typename T>
179 : void test_buff3(T& t, read_buffer& buf, std::vector<std::string> reads, std::vector<std::string> chk)
180 : {
181 : using namespace fas::testing;
182 : t << message("test_buff3");
183 : std::string input;
184 : std::string result;
185 : std::vector<std::string> vectres;
186 : for (auto& s: reads)
187 : {
188 : // t << message("read: ") << s ;
189 : // t << message("-1-");
190 : input+= s;
191 : auto p = buf.next();
192 : t << is_true<assert>(s.size() <= p.second) << s.size() << " > " << p.second << FAS_TESTING_FILE_LINE;
193 : t << stop;
194 : //std::strcpy( p.first, s.c_str());
195 : std::copy(s.begin(), s.end(), p.first );
196 : p.second = s.size();
197 : do_detach(t, buf, vectres, result);
198 : bool confirm = buf.confirm(p);
199 : t << is_true<assert>( confirm ) << FAS_TESTING_FILE_LINE;
200 : t << stop;
201 : }
202 : do_detach(t, buf, vectres, result);
203 : t << equal<expect>(input, result) << input << "!=" << result << FAS_TESTING_FILE_LINE;
204 : if ( !chk.empty() )
205 : t << equal<expect>(chk, vectres) << FAS_TESTING_FILE_LINE;
206 : }
207 :
208 : template<typename T>
209 : void test_buff4(T& t, read_buffer& buf, std::vector<std::string> reads, std::vector<std::string> chk)
210 : {
211 : using namespace fas::testing;
212 : t << message("test_buff4");
213 : std::string input;
214 : std::string result;
215 : std::vector<std::string> vectres;
216 : auto p = buf.next();
217 : for (auto& s: reads)
218 : {
219 : input += s;
220 : t << is_true<assert>(s.size() <= p.second) << s.size() << " > " << p.second << FAS_TESTING_FILE_LINE;
221 : t << stop;
222 : //std::strcpy( p.first, s.c_str());
223 : std::copy(s.begin(), s.end(), p.first );
224 : p.second = s.size();
225 :
226 : bool confirm = buf.confirm(p);
227 : t << is_true<assert>( confirm ) << FAS_TESTING_FILE_LINE;
228 : t << stop;
229 : p = buf.next();
230 : do_detach(t, buf, vectres, result);
231 : }
232 :
233 : p.second = 0;
234 : bool confirm = buf.confirm(p);
235 : t << is_true<assert>( confirm ) << FAS_TESTING_FILE_LINE;
236 : t << stop;
237 :
238 : do_detach(t, buf, vectres, result);
239 : t << equal<expect>(input, result) << input << "!=" << result << FAS_TESTING_FILE_LINE;
240 : if ( !chk.empty() )
241 : t << equal<expect>(chk, vectres) << FAS_TESTING_FILE_LINE;
242 : t << equal<assert, size_t>(buf.size(), 0) << "buf.size()==" << buf.size() << FAS_TESTING_FILE_LINE;
243 : t << equal<assert, size_t>(buf.count(), 0) << "buf.count()==" << buf.count() << FAS_TESTING_FILE_LINE;
244 : }
245 :
246 :
247 : template<typename T>
248 : void test_buff(T& t, read_buffer& buf, const std::vector<std::string>& reads, const std::vector<std::string>& chk)
249 : {
250 : test_buff1(t, buf, reads, chk);
251 : test_buff2(t, buf, reads, chk);
252 : test_buff3(t, buf, reads, chk);
253 : test_buff4(t, buf, reads, chk);
254 : }
255 :
256 : /*
257 : template<typename T>
258 : void test_buff0(T& t, read_buffer& buf, std::vector<std::string> reads, std::vector<std::string> chk)
259 : {
260 : using namespace fas::testing;
261 : t << message("test_buff0");
262 : std::string result;
263 : std::vector<std::string> vectres;
264 : auto p = buf.next();
265 : for (auto& s: reads)
266 : {
267 : t << is_true<assert>(s.size() <= p.second) << s.size() << " > " << p.second << FAS_FL;
268 : t << stop;
269 : std::strcpy( p.first, s.c_str());
270 : p.second = s.size();
271 :
272 : bool confirm = buf.confirm(p);
273 : t << is_true<assert>( confirm ) << FAS_TESTING_FILE_LINE;
274 : t << stop;
275 : p = buf.next();
276 : do_detach(t, buf, vectres, result);
277 : }
278 :
279 : p.second = 0;
280 : bool confirm = buf.confirm(p);
281 : t << is_true<assert>( confirm ) << FAS_TESTING_FILE_LINE;
282 : t << stop;
283 :
284 : do_detach(t, buf, vectres, result);
285 : t << equal<expect>(input, result) << input << "!=" << result << FAS_TESTING_FILE_LINE;
286 : if ( !chk.empty() )
287 : t << equal<expect>(chk, vectres) << FAS_TESTING_FILE_LINE;
288 : t << equal<assert, size_t>(buf.size(), 0) << "buf.size()==" << buf.size() << FAS_TESTING_FILE_LINE;
289 : t << equal<assert, size_t>(buf.count(), 0) << "buf.count()==" << buf.count() << FAS_TESTING_FILE_LINE;
290 : }
291 : */
292 :
293 : UNIT(basic_sep0, "")
294 : {
295 : using namespace fas::testing;
296 : read_buffer buf;
297 : options opt;
298 : buf.get_options(opt);
299 : opt.sep="";
300 : opt.bufsize = 6;
301 : opt.minbuf = 6;
302 : buf.set_options(opt);
303 : test_buff(t, buf,
304 : {"aa|", "|", "bb|", "|cc|", "|dd", "||ee||"},
305 : {"aa|", "|", "bb|", "|cc|", "|dd", "||ee||"}
306 : );
307 :
308 : opt.bufsize = 1;
309 : opt.minbuf = 1;
310 : buf.set_options(opt);
311 : test_buff(t, buf,
312 : {"a", "a", "|", "|", "b", "b", "|", "|", "c", "c", "|", "|", "d", "d", "|", "|", "e", "e", "|", "|"},
313 : {"a", "a", "|", "|", "b", "b", "|", "|", "c", "c", "|", "|", "d", "d", "|", "|", "e", "e", "|", "|"}
314 : );
315 :
316 : opt.bufsize = 2;
317 : opt.minbuf = 2;
318 : buf.set_options(opt);
319 : test_buff(t, buf,
320 : {"aa", "||", "bb", "||", "cc", "||", "dd", "||", "ee", "||"},
321 : {"aa", "||", "bb", "||", "cc", "||", "dd", "||", "ee", "||"}
322 : );
323 :
324 : }
325 :
326 : UNIT(basic_sep1, "")
327 : {
328 : using namespace fas::testing;
329 : read_buffer buf;
330 : options opt;
331 : buf.get_options(opt);
332 : opt.sep="|";
333 : opt.bufsize = 6;
334 : opt.minbuf = 6;
335 : buf.set_options(opt);
336 :
337 :
338 : test_buff(t, buf,
339 : {"aa|", "|", "bb|", "|cc|", "|dd", "||ee||"},
340 : {"aa|", "|", "bb|", "|", "cc|", "|", "dd|", "|", "ee|", "|"}
341 : );
342 :
343 :
344 :
345 : opt.bufsize = 1;
346 : opt.minbuf = 1;
347 : buf.set_options(opt);
348 : test_buff(t, buf,
349 : {"a", "a", "|", "|", "b", "b", "|", "|", "c", "c", "|", "|", "d", "d", "|", "|", "e", "e", "|", "|"},
350 : {"aa|", "|", "bb|", "|", "cc|", "|", "dd|", "|", "ee|", "|"}
351 : );
352 :
353 : opt.bufsize = 2;
354 : opt.minbuf = 2;
355 : buf.set_options(opt);
356 : test_buff(t, buf,
357 : {"aa", "||", "bb", "||", "cc", "||", "dd", "||", "ee", "||"},
358 : {"aa|", "|", "bb|", "|", "cc|", "|", "dd|", "|", "ee|", "|"}
359 : );
360 : }
361 :
362 :
363 : UNIT(basic_sep2, "")
364 : {
365 : using namespace fas::testing;
366 : read_buffer buf;
367 : options opt;
368 : buf.get_options(opt);
369 : opt.sep="##";
370 : opt.bufsize = 10;
371 : opt.minbuf = 10;
372 : buf.set_options(opt);
373 :
374 : test_buff(t, buf,
375 : {"aa##", "##", "bb##", "##cc##", "##dd", "####ee####"},
376 : {"aa##", "##", "bb##", "##", "cc##", "##", "dd##", "##", "ee##", "##"}
377 : );
378 : opt.bufsize = 1;
379 : opt.minbuf = 1;
380 : buf.set_options(opt);
381 : test_buff(t, buf,
382 : {"a", "a", "#","#", "#","#", "b", "b", "#","#", "#","#", "c", "c", "#","#", "#","#", "d", "d", "#","#", "#","#", "e", "e", "#","#", "#","#"},
383 : {"aa##", "##", "bb##", "##", "cc##", "##", "dd##", "##", "ee##", "##"}
384 : );
385 :
386 : opt.bufsize = 4;
387 : opt.minbuf = 4;
388 : buf.set_options(opt);
389 : test_buff(t, buf,
390 : {"aa", "####", "bb", "####", "cc", "####", "dd", "####", "ee", "####"},
391 : {"aa##", "##", "bb##", "##", "cc##", "##", "dd##", "##", "ee##", "##"}
392 : );
393 : }
394 :
395 : UNIT(basic_sep3, "")
396 : {
397 : using namespace fas::testing;
398 : read_buffer buf;
399 : options opt;
400 : buf.get_options(opt);
401 : opt.sep="@@@";
402 : opt.bufsize = 20;
403 : opt.minbuf = 20;
404 : buf.set_options(opt);
405 :
406 : test_buff(t, buf,
407 : {"aa@@@", "@@@", "bb@@@", "@@@cc@@@", "@@@dd", "@@@@@@ee@@@@@@"},
408 : {"aa@@@", "@@@", "bb@@@", "@@@", "cc@@@", "@@@", "dd@@@", "@@@", "ee@@@", "@@@"}
409 : );
410 :
411 :
412 :
413 : opt.bufsize = 1;
414 : opt.minbuf = 1;
415 : buf.set_options(opt);
416 : test_buff(t, buf,
417 : {"a", "a", "@","@","@", "@","@","@", "b", "b", "@", "@","@", "@", "@","@", "c", "c", "@", "@","@", "@", "@","@", "d", "d", "@", "@","@", "@", "@","@", "e", "e", "@","@","@", "@","@","@"},
418 : {"aa@@@", "@@@", "bb@@@", "@@@", "cc@@@", "@@@", "dd@@@", "@@@", "ee@@@", "@@@"}
419 : );
420 :
421 : opt.bufsize = 6;
422 : opt.minbuf = 6;
423 : buf.set_options(opt);
424 : test_buff(t, buf,
425 : {"aa", "@@@@@@", "bb", "@@@@@@", "cc", "@@@@@@", "dd", "@@@@@@", "ee", "@@@@@@"},
426 : {"aa@@@", "@@@", "bb@@@", "@@@", "cc@@@", "@@@", "dd@@@", "@@@", "ee@@@", "@@@"}
427 : );
428 : }
429 :
430 : UNIT(empty_test, "Ошибка без сепаратора (работает через раз)")
431 : {
432 : using namespace fas::testing;
433 : read_buffer buf;
434 : options opt;
435 : buf.get_options(opt);
436 : opt.sep="";
437 : buf.set_options(opt);
438 : std::string req1 = "{запрос номер одын}";
439 : std::string req2 = "{запрос номер два}";
440 : auto p = buf.next();
441 : std::copy(req1.begin(), req1.end(), p.first);
442 : p.second = req1.size();
443 : buf.confirm(p);
444 : auto res = buf.detach();
445 : t << equal<expect, std::string>( req1, std::string(res->begin(), res->end()) ) << FAS_FL;
446 : res = buf.detach();
447 : t << equal<expect>( res, nullptr ) << FAS_FL;
448 : p = buf.next();
449 : std::copy(req2.begin(), req2.end(), p.first);
450 : p.second = req2.size();
451 : buf.confirm(p);
452 : res = buf.detach();
453 : t << equal<expect, std::string>( req2, std::string(res->begin(), res->end()) ) << FAS_FL;
454 : }
455 :
456 3 : UNIT(bug_test, "Ошибка склеивания с мусором")
457 : {
458 : using namespace fas::testing;
459 1 : t << nothing;
460 1 : read_buffer buf;
461 2 : options opt;
462 1 : buf.get_options(opt);
463 1 : opt.sep="\r\n";
464 1 : opt.trimsep = true;
465 1 : opt.minbuf = 0;
466 1 : buf.set_options(opt);
467 :
468 1 : auto p = buf.next();
469 10001 : for (int i = 0; i!=10000; ++i)
470 : {
471 10000 : std::string req;
472 5121153 : std::generate_n( std::back_inserter(req), 1 + std::rand()%1024, [](){ return static_cast<char>('0' + std::rand()%32); });
473 10000 : req+="\r\n";
474 10000 : t << message("size=") << p.second << " req.size=" << req.size();
475 10000 : t << message("STRING [") << req << "] i=" << i ;
476 10000 : std::copy(req.begin(), req.end(), p.first);
477 10000 : p.second = req.size();
478 10000 : buf.confirm(p);
479 10000 : p = buf.next();
480 20000 : auto res = buf.detach();
481 10000 : t << not_equal<assert>(res, nullptr) << FAS_FL;
482 10000 : t << stop;
483 10000 : req.resize(req.size() - 2);
484 10000 : t << equal<expect, std::string>( req, std::string(res->begin(), res->end()) ) << FAS_FL;
485 : }
486 :
487 1 : opt.sep="\r\n";
488 1 : opt.trimsep = true;
489 1 : buf.set_options(opt);
490 :
491 :
492 2 : std::string req2 = "{'jsonrpc':'2.0'\r\n";
493 2 : std::string req1 = "{'jsonrpc':'2.0','method':'insert','params':{'table':'new_contact','fields':{'platform':['web-site'],'partner':['mambaru'],'link':['none'],'age_from':62,'age_to':62,'gender_from':['F'],'gender_to':['M'],'country_from':['Russian Federation'],'country_to':['Russian Federation']},'values':[1635296312,1645340482]}}\r\n";
494 :
495 : //p = buf.next();
496 : //t << message("size=") << p.second << " req1.size=" << req1.size();
497 : //t << message("-");
498 1 : std::copy(req1.begin(), req1.end(), p.first);
499 1 : p.second = req1.size();
500 1 : buf.confirm(p);
501 :
502 1 : p = buf.next();
503 1 : t << message("size=") << p.second << " req2.size=" << req1.size();
504 1 : std::copy(req2.begin(), req2.end(), p.first);
505 1 : p.second = req2.size();
506 1 : buf.confirm(p);
507 :
508 2 : auto res = buf.detach();
509 1 : t << not_equal<assert>(res, nullptr) << FAS_FL;
510 1 : t << stop;
511 1 : req1.resize(req1.size() - 2);
512 1 : t << equal<expect, std::string>( req1, std::string(res->begin(), res->end()) ) << FAS_FL;
513 :
514 1 : res = buf.detach();
515 1 : t << not_equal<assert>(res, nullptr) << FAS_FL;
516 1 : t << stop;
517 1 : req2.resize(req2.size() - 2);
518 1 : t << equal<expect, std::string>( req2, std::string(res->begin(), res->end()) ) << FAS_FL;
519 :
520 1 : res = buf.detach();
521 2 : t << equal<expect>( res, nullptr ) << FAS_FL;
522 1 : }
523 :
524 :
525 1 : BEGIN_SUITE(read_buffers, "read_buffer suite")
526 : /*ADD_UNIT(basic_test)
527 : ADD_UNIT(basic_sep0)
528 : ADD_UNIT(basic_sep1)
529 : ADD_UNIT(basic_sep2)
530 : ADD_UNIT(basic_sep3)
531 : ADD_UNIT(empty_test)
532 : */
533 : ADD_UNIT(bug_test)
534 4 : END_SUITE(read_buffers)
535 :
536 1 : BEGIN_TEST
537 1 : RUN_SUITE(read_buffers)
538 4 : END_TEST
|