]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/container/test/string_test.cpp
b2d17f6aa4a9f956aba5bcffd331632e1c8a875f
[ceph.git] / ceph / src / boost / libs / container / test / string_test.cpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2004-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 #include <boost/container/detail/config_begin.hpp>
12 #include <boost/container/vector.hpp>
13 #include <boost/container/string.hpp>
14 #include <string>
15 #include <vector>
16 #include <boost/container/detail/algorithm.hpp> //equal()
17 #include <cstring>
18 #include <cstdio>
19 #include <cstddef>
20 #include <new>
21 #include "dummy_test_allocator.hpp"
22 #include "check_equal_containers.hpp"
23 #include "expand_bwd_test_allocator.hpp"
24 #include "expand_bwd_test_template.hpp"
25 #include "propagate_allocator_test.hpp"
26 #include "default_init_test.hpp"
27 #include "comparison_test.hpp"
28 #include "../../intrusive/test/iterator_test.hpp"
29 #include <boost/utility/string_view.hpp>
30 #include <boost/core/lightweight_test.hpp>
31
32 using namespace boost::container;
33
34 struct StringEqual
35 {
36 template<class Str1, class Str2>
37 bool operator ()(const Str1 &string1, const Str2 &string2) const
38 {
39 if(string1.size() != string2.size())
40 return false;
41 return std::char_traits<typename Str1::value_type>::compare
42 (string1.c_str(), string2.c_str(), string1.size()) == 0;
43 }
44 };
45
46 //Function to check if both lists are equal
47 template<class StrVector1, class StrVector2>
48 bool CheckEqualStringVector(StrVector1 *strvect1, StrVector2 *strvect2)
49 {
50 StringEqual comp;
51 return boost::container::algo_equal(strvect1->begin(), strvect1->end(),
52 strvect2->begin(), comp);
53 }
54
55 template<class ForwardIt>
56 ForwardIt unique(ForwardIt first, ForwardIt const last)
57 {
58 if(first == last){
59 ForwardIt i = first;
60 //Find first adjacent pair
61 while(1){
62 if(++i == last){
63 return last;
64 }
65 else if(*first == *i){
66 break;
67 }
68 ++first;
69 }
70 //Now overwrite skipping adjacent elements
71 while (++i != last) {
72 if (!(*first == *i)) {
73 *(++first) = boost::move(*i);
74 }
75 }
76 ++first;
77 }
78 return first;
79 }
80
81 template<class CharType>
82 struct string_literals;
83
84 template<>
85 struct string_literals<char>
86 {
87 static const char *String()
88 { return "String"; }
89 static const char *Prefix()
90 { return "Prefix"; }
91 static const char *Suffix()
92 { return "Suffix"; }
93 static const char *LongString()
94 { return "LongLongLongLongLongLongLongLongLongLongLongLongLongString"; }
95 static char Char()
96 { return 'C'; }
97 static void sprintf_number(char *buf, int number)
98 {
99 std::sprintf(buf, "%i", number);
100 }
101 };
102
103 template<>
104 struct string_literals<wchar_t>
105 {
106 static const wchar_t *String()
107 { return L"String"; }
108 static const wchar_t *Prefix()
109 { return L"Prefix"; }
110 static const wchar_t *Suffix()
111 { return L"Suffix"; }
112 static const wchar_t *LongString()
113 { return L"LongLongLongLongLongLongLongLongLongLongLongLongLongString"; }
114 static wchar_t Char()
115 { return L'C'; }
116 static void sprintf_number(wchar_t *buffer, unsigned int number)
117 {
118 //For compilers without wsprintf, print it backwards
119 const wchar_t *digits = L"0123456789";
120 wchar_t *buf = buffer;
121
122 while(1){
123 int rem = number % 10;
124 number = number / 10;
125
126 *buf = digits[rem];
127 ++buf;
128 if(!number){
129 *buf = 0;
130 break;
131 }
132 }
133
134 }
135 };
136
137 template<class CharType>
138 int string_test()
139 {
140 typedef std::basic_string<CharType> StdString;
141 typedef vector<StdString> StdStringVector;
142 typedef basic_string<CharType> BoostString;
143 typedef vector<BoostString> BoostStringVector;
144
145 const int MaxSize = 100;
146
147 {
148 BoostStringVector *boostStringVect = new BoostStringVector;
149 StdStringVector *stdStringVect = new StdStringVector;
150 BoostString auxBoostString;
151 StdString auxStdString(StdString(auxBoostString.begin(), auxBoostString.end() ));
152
153 CharType buffer [20];
154
155 //First, push back
156 for(int i = 0; i < MaxSize; ++i){
157 auxBoostString = string_literals<CharType>::String();
158 auxStdString = string_literals<CharType>::String();
159 string_literals<CharType>::sprintf_number(buffer, i);
160 auxBoostString += buffer;
161 auxStdString += buffer;
162 boostStringVect->push_back(auxBoostString);
163 stdStringVect->push_back(auxStdString);
164 }
165
166 if(auxBoostString.data() != const_cast<const BoostString&>(auxBoostString).data() &&
167 auxBoostString.data() != &auxBoostString[0])
168 return 1;
169
170 if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
171 return 1;
172 }
173
174 //Now push back moving
175 for(int i = 0; i < MaxSize; ++i){
176 auxBoostString = string_literals<CharType>::String();
177 auxStdString = string_literals<CharType>::String();
178 string_literals<CharType>::sprintf_number(buffer, i);
179 auxBoostString += buffer;
180 auxStdString += buffer;
181 boostStringVect->push_back(boost::move(auxBoostString));
182 stdStringVect->push_back(auxStdString);
183 }
184
185 if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
186 return 1;
187 }
188
189 //push front
190 for(int i = 0; i < MaxSize; ++i){
191 auxBoostString = string_literals<CharType>::String();
192 auxStdString = string_literals<CharType>::String();
193 string_literals<CharType>::sprintf_number(buffer, i);
194 auxBoostString += buffer;
195 auxStdString += buffer;
196 boostStringVect->insert(boostStringVect->begin(), auxBoostString);
197 stdStringVect->insert(stdStringVect->begin(), auxStdString);
198 }
199
200 if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
201 return 1;
202 }
203
204 //Now push front moving
205 for(int i = 0; i < MaxSize; ++i){
206 auxBoostString = string_literals<CharType>::String();
207 auxStdString = string_literals<CharType>::String();
208 string_literals<CharType>::sprintf_number(buffer, i);
209 auxBoostString += buffer;
210 auxStdString += buffer;
211 boostStringVect->insert(boostStringVect->begin(), boost::move(auxBoostString));
212 stdStringVect->insert(stdStringVect->begin(), auxStdString);
213 }
214
215 if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
216 return 1;
217 }
218
219 //Now test long and short representation swapping
220
221 //Short first
222 auxBoostString = string_literals<CharType>::String();
223 auxStdString = string_literals<CharType>::String();
224 BoostString boost_swapper;
225 StdString std_swapper;
226 boost_swapper.swap(auxBoostString);
227 std_swapper.swap(auxStdString);
228 if(!StringEqual()(auxBoostString, auxStdString))
229 return 1;
230 if(!StringEqual()(boost_swapper, std_swapper))
231 return 1;
232 boost_swapper.swap(auxBoostString);
233 std_swapper.swap(auxStdString);
234 if(!StringEqual()(auxBoostString, auxStdString))
235 return 1;
236 if(!StringEqual()(boost_swapper, std_swapper))
237 return 1;
238
239 //Shrink_to_fit
240 auxBoostString.shrink_to_fit();
241 StdString(auxStdString).swap(auxStdString);
242 if(!StringEqual()(auxBoostString, auxStdString))
243 return 1;
244
245 //Reserve + shrink_to_fit
246 auxBoostString.reserve(boost_swapper.size()*2+1);
247 auxStdString.reserve(std_swapper.size()*2+1);
248 if(!StringEqual()(auxBoostString, auxStdString))
249 return 1;
250
251 auxBoostString.shrink_to_fit();
252 StdString(auxStdString).swap(auxStdString);
253 if(!StringEqual()(auxBoostString, auxStdString))
254 return 1;
255
256 //Long string
257 auxBoostString = string_literals<CharType>::LongString();
258 auxStdString = string_literals<CharType>::LongString();
259 boost_swapper = BoostString();
260 std_swapper = StdString();
261 boost_swapper.swap(auxBoostString);
262 std_swapper.swap(auxStdString);
263 if(!StringEqual()(auxBoostString, auxStdString))
264 return 1;
265 if(!StringEqual()(boost_swapper, std_swapper))
266 return 1;
267 boost_swapper.swap(auxBoostString);
268 std_swapper.swap(auxStdString);
269
270 //Shrink_to_fit
271 auxBoostString.shrink_to_fit();
272 StdString(auxStdString).swap(auxStdString);
273 if(!StringEqual()(auxBoostString, auxStdString))
274 return 1;
275
276 auxBoostString.clear();
277 auxStdString.clear();
278 auxBoostString.shrink_to_fit();
279 StdString(auxStdString).swap(auxStdString);
280 if(!StringEqual()(auxBoostString, auxStdString))
281 return 1;
282
283 //No sort
284 std::sort(boostStringVect->begin(), boostStringVect->end());
285 std::sort(stdStringVect->begin(), stdStringVect->end());
286 if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
287
288 const CharType *prefix = string_literals<CharType>::Prefix();
289 const int prefix_size = std::char_traits<CharType>::length(prefix);
290 const CharType *sufix = string_literals<CharType>::Suffix();
291
292 for(int i = 0; i < MaxSize; ++i){
293 (*boostStringVect)[i].append(sufix);
294 (*stdStringVect)[i].append(sufix);
295 (*boostStringVect)[i].insert((*boostStringVect)[i].begin(),
296 prefix, prefix + prefix_size);
297 (*stdStringVect)[i].insert((*stdStringVect)[i].begin(),
298 prefix, prefix + prefix_size);
299 }
300
301 if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
302
303 for(int i = 0; i < MaxSize; ++i){
304 std::reverse((*boostStringVect)[i].begin(), (*boostStringVect)[i].end());
305 std::reverse((*stdStringVect)[i].begin(), (*stdStringVect)[i].end());
306 }
307
308 if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
309
310 for(int i = 0; i < MaxSize; ++i){
311 std::reverse((*boostStringVect)[i].begin(), (*boostStringVect)[i].end());
312 std::reverse((*stdStringVect)[i].begin(), (*stdStringVect)[i].end());
313 }
314
315 if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
316
317 for(int i = 0; i < MaxSize; ++i){
318 std::sort(boostStringVect->begin(), boostStringVect->end());
319 std::sort(stdStringVect->begin(), stdStringVect->end());
320 }
321
322 if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
323
324 for(int i = 0; i < MaxSize; ++i){
325 (*boostStringVect)[i].replace((*boostStringVect)[i].begin(),
326 (*boostStringVect)[i].end(),
327 string_literals<CharType>::String());
328 (*stdStringVect)[i].replace((*stdStringVect)[i].begin(),
329 (*stdStringVect)[i].end(),
330 string_literals<CharType>::String());
331 }
332
333 if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
334
335 boostStringVect->erase(::unique(boostStringVect->begin(), boostStringVect->end()),
336 boostStringVect->end());
337 stdStringVect->erase(::unique(stdStringVect->begin(), stdStringVect->end()),
338 stdStringVect->end());
339 if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
340
341 //Check addition
342 {
343 BoostString bs2 = string_literals<CharType>::String();
344 StdString ss2 = string_literals<CharType>::String();
345 BoostString bs3 = string_literals<CharType>::Suffix();
346 StdString ss3 = string_literals<CharType>::Suffix();
347 BoostString bs4 = bs2 + bs3;
348 StdString ss4 = ss2 + ss3;
349 if(!StringEqual()(bs4, ss4)){
350 return 1;
351 }
352
353 bs4 = bs2 + BoostString();
354 ss4 = ss2 + StdString();
355 if(!StringEqual()(bs4, ss4)){
356 return 1;
357 }
358
359 bs4 = BoostString() + bs2;
360 ss4 = StdString() + ss2;
361 if(!StringEqual()(bs4, ss4)){
362 return 1;
363 }
364
365 bs4 = BoostString() + boost::move(bs2);
366 ss4 = StdString() + boost::move(ss2);
367 if(!StringEqual()(bs4, ss4)){
368 return 1;
369 }
370
371 bs2 = string_literals<CharType>::String();
372 ss2 = string_literals<CharType>::String();
373 bs4 = boost::move(bs2) + BoostString();
374 ss4 = boost::move(ss2) + StdString();
375 if(!StringEqual()(bs4, ss4)){
376 return 1;
377 }
378
379 bs2 = string_literals<CharType>::String();
380 ss2 = string_literals<CharType>::String();
381 bs4 = string_literals<CharType>::Prefix() + boost::move(bs2);
382 ss4 = string_literals<CharType>::Prefix() + boost::move(ss2);
383 if(!StringEqual()(bs4, ss4)){
384 return 1;
385 }
386
387 bs2 = string_literals<CharType>::String();
388 ss2 = string_literals<CharType>::String();
389 bs4 = boost::move(bs2) + string_literals<CharType>::Suffix();
390 ss4 = boost::move(ss2) + string_literals<CharType>::Suffix();
391 if(!StringEqual()(bs4, ss4)){
392 return 1;
393 }
394
395 bs2 = string_literals<CharType>::String();
396 ss2 = string_literals<CharType>::String();
397 bs4 = string_literals<CharType>::Prefix() + bs2;
398 ss4 = string_literals<CharType>::Prefix() + ss2;
399 if(!StringEqual()(bs4, ss4)){
400 return 1;
401 }
402
403 bs2 = string_literals<CharType>::String();
404 ss2 = string_literals<CharType>::String();
405 bs4 = bs2 + string_literals<CharType>::Suffix();
406 ss4 = ss2 + string_literals<CharType>::Suffix();
407 if(!StringEqual()(bs4, ss4)){
408 return 1;
409 }
410
411 bs2 = string_literals<CharType>::String();
412 ss2 = string_literals<CharType>::String();
413 bs4 = string_literals<CharType>::Char() + bs2;
414 ss4 = string_literals<CharType>::Char() + ss2;
415 if(!StringEqual()(bs4, ss4)){
416 return 1;
417 }
418
419 bs2 = string_literals<CharType>::String();
420 ss2 = string_literals<CharType>::String();
421 bs4 = bs2 + string_literals<CharType>::Char();
422 ss4 = ss2 + string_literals<CharType>::Char();
423 if(!StringEqual()(bs4, ss4)){
424 return 1;
425 }
426
427 //Check front/back/begin/end
428
429 if(bs4.front() != *ss4.begin())
430 return 1;
431
432 if(bs4.back() != *(ss4.end()-1))
433 return 1;
434
435 bs4.pop_back();
436 ss4.erase(ss4.end()-1);
437 if(!StringEqual()(bs4, ss4)){
438 return 1;
439 }
440
441 if(*bs4.begin() != *ss4.begin())
442 return 1;
443 if(*bs4.cbegin() != *ss4.begin())
444 return 1;
445 if(*bs4.rbegin() != *ss4.rbegin())
446 return 1;
447 if(*bs4.crbegin() != *ss4.rbegin())
448 return 1;
449 if(*(bs4.end()-1) != *(ss4.end()-1))
450 return 1;
451 if(*(bs4.cend()-1) != *(ss4.end()-1))
452 return 1;
453 if(*(bs4.rend()-1) != *(ss4.rend()-1))
454 return 1;
455 if(*(bs4.crend()-1) != *(ss4.rend()-1))
456 return 1;
457 }
458
459 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
460 //Chect Constructor Template Auto Deduction
461 {
462 auto gold = StdString(string_literals<CharType>::String());
463 auto test = basic_string(gold.begin(), gold.end());
464 if(!StringEqual()(gold, test)) {
465 return 1;
466 }
467 }
468 #endif
469
470
471 //When done, delete vector
472 delete boostStringVect;
473 delete stdStringVect;
474 }
475 return 0;
476 }
477
478 bool test_expand_bwd()
479 {
480 //Now test all back insertion possibilities
481 typedef test::expand_bwd_test_allocator<char>
482 allocator_type;
483 typedef basic_string<char, std::char_traits<char>, allocator_type>
484 string_type;
485 return test::test_all_expand_bwd<string_type>();
486 }
487
488 struct boost_container_string;
489
490 namespace boost { namespace container { namespace test {
491
492 template<>
493 struct alloc_propagate_base<boost_container_string>
494 {
495 template <class T, class Allocator>
496 struct apply
497 {
498 typedef boost::container::basic_string<T, std::char_traits<T>, Allocator> type;
499 };
500 };
501
502
503 }}} //namespace boost::container::test
504
505
506 int main()
507 {
508 if(string_test<char>()){
509 return 1;
510 }
511
512 if(string_test<wchar_t>()){
513 return 1;
514 }
515
516 ////////////////////////////////////
517 // Backwards expansion test
518 ////////////////////////////////////
519 if(!test_expand_bwd())
520 return 1;
521
522 ////////////////////////////////////
523 // Allocator propagation testing
524 ////////////////////////////////////
525 if(!boost::container::test::test_propagate_allocator<boost_container_string>())
526 return 1;
527
528 ////////////////////////////////////
529 // Default init test
530 ////////////////////////////////////
531 if(!test::default_init_test< basic_string<char, std::char_traits<char>, test::default_init_allocator<char> > >()){
532 std::cerr << "Default init test failed" << std::endl;
533 return 1;
534 }
535
536 if(!test::default_init_test< basic_string<wchar_t, std::char_traits<wchar_t>, test::default_init_allocator<wchar_t> > >()){
537 std::cerr << "Default init test failed" << std::endl;
538 return 1;
539 }
540
541 ////////////////////////////////////
542 // Iterator testing
543 ////////////////////////////////////
544 {
545 typedef boost::container::basic_string<char> cont_int;
546 cont_int a; a.push_back(char(1)); a.push_back(char(2)); a.push_back(char(3));
547 boost::intrusive::test::test_iterator_random< cont_int >(a);
548 }
549 {
550 typedef boost::container::basic_string<wchar_t> cont_int;
551 cont_int a; a.push_back(wchar_t(1)); a.push_back(wchar_t(2)); a.push_back(wchar_t(3));
552 boost::intrusive::test::test_iterator_random< cont_int >(a);
553 }
554
555 ////////////////////////////////////
556 // Comparison testing
557 ////////////////////////////////////
558 {
559 if(!boost::container::test::test_container_comparisons<string>())
560 return 1;
561 if(!boost::container::test::test_container_comparisons<wstring>())
562 return 1;
563 }
564
565 ////////////////////////////////////
566 // has_trivial_destructor_after_move testing
567 ////////////////////////////////////
568 // default allocator
569 {
570 typedef boost::container::basic_string<char> cont;
571 typedef cont::allocator_type allocator_type;
572 typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
573 if (boost::has_trivial_destructor_after_move<cont>::value !=
574 boost::has_trivial_destructor_after_move<allocator_type>::value &&
575 boost::has_trivial_destructor_after_move<pointer>::value) {
576 std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl;
577 return 1;
578 }
579 }
580 // std::allocator
581 {
582 typedef boost::container::basic_string<char, std::char_traits<char>, std::allocator<char> > cont;
583 typedef cont::allocator_type allocator_type;
584 typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
585 if (boost::has_trivial_destructor_after_move<cont>::value !=
586 boost::has_trivial_destructor_after_move<allocator_type>::value &&
587 boost::has_trivial_destructor_after_move<pointer>::value) {
588 std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl;
589 return 1;
590 }
591 }
592
593 return boost::report_errors();
594 }
595
596 #include <boost/container/detail/config_end.hpp>