15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier 
95a83710eSEric Fiselier // <string>
105a83710eSEric Fiselier 
115a83710eSEric Fiselier // template<class InputIterator>
12*425620ccSNikolas Klauser //   basic_string& append(InputIterator first, InputIterator last); // constexpr since C++20
135a83710eSEric Fiselier 
145a83710eSEric Fiselier #include <string>
155a83710eSEric Fiselier #include <cassert>
165a83710eSEric Fiselier 
177fc6a556SMarshall Clow #include "test_macros.h"
1876b4afc0SMarshall Clow #include "test_iterators.h"
195a83710eSEric Fiselier #include "min_allocator.h"
205a83710eSEric Fiselier 
215a83710eSEric Fiselier template <class S, class It>
22dcffa7d3SNikolas Klauser TEST_CONSTEXPR_CXX20 void
test(S s,It first,It last,S expected)235a83710eSEric Fiselier test(S s, It first, It last, S expected)
245a83710eSEric Fiselier {
255a83710eSEric Fiselier     s.append(first, last);
261f4231f8SEric Fiselier     LIBCPP_ASSERT(s.__invariants());
275a83710eSEric Fiselier     assert(s == expected);
285a83710eSEric Fiselier }
295a83710eSEric Fiselier 
30e612a887SMarshall Clow #ifndef TEST_HAS_NO_EXCEPTIONS
operator charWidget31e87479b0SArthur O'Dwyer struct Widget { operator char() const { throw 42; } };
32e87479b0SArthur O'Dwyer 
3376b4afc0SMarshall Clow template <class S, class It>
34dcffa7d3SNikolas Klauser TEST_CONSTEXPR_CXX20 void
test_exceptions(S s,It first,It last)3576b4afc0SMarshall Clow test_exceptions(S s, It first, It last)
3676b4afc0SMarshall Clow {
37036b80fcSArthur O'Dwyer     S original = s;
38036b80fcSArthur O'Dwyer     typename S::iterator begin = s.begin();
39036b80fcSArthur O'Dwyer     typename S::iterator end = s.end();
40036b80fcSArthur O'Dwyer 
4176b4afc0SMarshall Clow     try {
4276b4afc0SMarshall Clow         s.append(first, last);
4376b4afc0SMarshall Clow         assert(false);
44036b80fcSArthur O'Dwyer     } catch (...) {}
45036b80fcSArthur O'Dwyer 
46036b80fcSArthur O'Dwyer     // Part of "no effects" is that iterators and pointers
47036b80fcSArthur O'Dwyer     // into the string must not have been invalidated.
481f4231f8SEric Fiselier     LIBCPP_ASSERT(s.__invariants());
49036b80fcSArthur O'Dwyer     assert(s == original);
50036b80fcSArthur O'Dwyer     assert(s.begin() == begin);
51036b80fcSArthur O'Dwyer     assert(s.end() == end);
5276b4afc0SMarshall Clow }
53e612a887SMarshall Clow #endif
5476b4afc0SMarshall Clow 
test()55*425620ccSNikolas Klauser TEST_CONSTEXPR_CXX20 bool test() {
565a83710eSEric Fiselier   {
575a83710eSEric Fiselier     typedef std::string S;
585a83710eSEric Fiselier     const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
595a83710eSEric Fiselier     test(S(), s, s, S());
605a83710eSEric Fiselier     test(S(), s, s+1, S("A"));
615a83710eSEric Fiselier     test(S(), s, s+10, S("ABCDEFGHIJ"));
625a83710eSEric Fiselier     test(S(), s, s+52, S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
635a83710eSEric Fiselier 
645a83710eSEric Fiselier     test(S("12345"), s, s, S("12345"));
655a83710eSEric Fiselier     test(S("12345"), s, s+1, S("12345A"));
665a83710eSEric Fiselier     test(S("12345"), s, s+10, S("12345ABCDEFGHIJ"));
675a83710eSEric Fiselier     test(S("12345"), s, s+52, S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
685a83710eSEric Fiselier 
695a83710eSEric Fiselier     test(S("1234567890"), s, s, S("1234567890"));
705a83710eSEric Fiselier     test(S("1234567890"), s, s+1, S("1234567890A"));
715a83710eSEric Fiselier     test(S("1234567890"), s, s+10, S("1234567890ABCDEFGHIJ"));
725a83710eSEric Fiselier     test(S("1234567890"), s, s+52, S("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
735a83710eSEric Fiselier 
745a83710eSEric Fiselier     test(S("12345678901234567890"), s, s, S("12345678901234567890"));
755a83710eSEric Fiselier     test(S("12345678901234567890"), s, s+1, S("12345678901234567890""A"));
765a83710eSEric Fiselier     test(S("12345678901234567890"), s, s+10, S("12345678901234567890""ABCDEFGHIJ"));
775a83710eSEric Fiselier     test(S("12345678901234567890"), s, s+52,
785a83710eSEric Fiselier          S("12345678901234567890""ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
795a83710eSEric Fiselier 
80773ae441SChristopher Di Bella     test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S());
81773ae441SChristopher Di Bella     test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), S("A"));
82773ae441SChristopher Di Bella     test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10),
835a83710eSEric Fiselier          S("ABCDEFGHIJ"));
84773ae441SChristopher Di Bella     test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52),
855a83710eSEric Fiselier          S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
865a83710eSEric Fiselier 
87773ae441SChristopher Di Bella     test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s),
885a83710eSEric Fiselier          S("12345"));
89773ae441SChristopher Di Bella     test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1),
905a83710eSEric Fiselier          S("12345A"));
91773ae441SChristopher Di Bella     test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10),
925a83710eSEric Fiselier          S("12345ABCDEFGHIJ"));
93773ae441SChristopher Di Bella     test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52),
945a83710eSEric Fiselier          S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
955a83710eSEric Fiselier 
96773ae441SChristopher Di Bella     test(S("1234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s),
975a83710eSEric Fiselier          S("1234567890"));
98773ae441SChristopher Di Bella     test(S("1234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1),
995a83710eSEric Fiselier          S("1234567890A"));
100773ae441SChristopher Di Bella     test(S("1234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10),
1015a83710eSEric Fiselier          S("1234567890ABCDEFGHIJ"));
102773ae441SChristopher Di Bella     test(S("1234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52),
1035a83710eSEric Fiselier          S("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
1045a83710eSEric Fiselier 
105773ae441SChristopher Di Bella     test(S("12345678901234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s),
1065a83710eSEric Fiselier          S("12345678901234567890"));
107773ae441SChristopher Di Bella     test(S("12345678901234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1),
1085a83710eSEric Fiselier          S("12345678901234567890""A"));
109773ae441SChristopher Di Bella     test(S("12345678901234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10),
1105a83710eSEric Fiselier          S("12345678901234567890""ABCDEFGHIJ"));
111773ae441SChristopher Di Bella     test(S("12345678901234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52),
1125a83710eSEric Fiselier          S("12345678901234567890""ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
1135a83710eSEric Fiselier   }
11476b4afc0SMarshall Clow #if TEST_STD_VER >= 11
1155a83710eSEric Fiselier   {
1165a83710eSEric Fiselier     typedef std::basic_string<char, std::char_traits<char>, min_allocator<char>> S;
1175a83710eSEric Fiselier     const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1185a83710eSEric Fiselier     test(S(), s, s, S());
1195a83710eSEric Fiselier     test(S(), s, s+1, S("A"));
1205a83710eSEric Fiselier     test(S(), s, s+10, S("ABCDEFGHIJ"));
1215a83710eSEric Fiselier     test(S(), s, s+52, S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
1225a83710eSEric Fiselier 
1235a83710eSEric Fiselier     test(S("12345"), s, s, S("12345"));
1245a83710eSEric Fiselier     test(S("12345"), s, s+1, S("12345A"));
1255a83710eSEric Fiselier     test(S("12345"), s, s+10, S("12345ABCDEFGHIJ"));
1265a83710eSEric Fiselier     test(S("12345"), s, s+52, S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
1275a83710eSEric Fiselier 
1285a83710eSEric Fiselier     test(S("1234567890"), s, s, S("1234567890"));
1295a83710eSEric Fiselier     test(S("1234567890"), s, s+1, S("1234567890A"));
1305a83710eSEric Fiselier     test(S("1234567890"), s, s+10, S("1234567890ABCDEFGHIJ"));
1315a83710eSEric Fiselier     test(S("1234567890"), s, s+52, S("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
1325a83710eSEric Fiselier 
1335a83710eSEric Fiselier     test(S("12345678901234567890"), s, s, S("12345678901234567890"));
1345a83710eSEric Fiselier     test(S("12345678901234567890"), s, s+1, S("12345678901234567890""A"));
1355a83710eSEric Fiselier     test(S("12345678901234567890"), s, s+10, S("12345678901234567890""ABCDEFGHIJ"));
1365a83710eSEric Fiselier     test(S("12345678901234567890"), s, s+52,
1375a83710eSEric Fiselier          S("12345678901234567890""ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
1385a83710eSEric Fiselier 
139773ae441SChristopher Di Bella     test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s), S());
140773ae441SChristopher Di Bella     test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1), S("A"));
141773ae441SChristopher Di Bella     test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10),
1425a83710eSEric Fiselier          S("ABCDEFGHIJ"));
143773ae441SChristopher Di Bella     test(S(), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52),
1445a83710eSEric Fiselier          S("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
1455a83710eSEric Fiselier 
146773ae441SChristopher Di Bella     test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s),
1475a83710eSEric Fiselier          S("12345"));
148773ae441SChristopher Di Bella     test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1),
1495a83710eSEric Fiselier          S("12345A"));
150773ae441SChristopher Di Bella     test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10),
1515a83710eSEric Fiselier          S("12345ABCDEFGHIJ"));
152773ae441SChristopher Di Bella     test(S("12345"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52),
1535a83710eSEric Fiselier          S("12345ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
1545a83710eSEric Fiselier 
155773ae441SChristopher Di Bella     test(S("1234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s),
1565a83710eSEric Fiselier          S("1234567890"));
157773ae441SChristopher Di Bella     test(S("1234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1),
1585a83710eSEric Fiselier          S("1234567890A"));
159773ae441SChristopher Di Bella     test(S("1234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10),
1605a83710eSEric Fiselier          S("1234567890ABCDEFGHIJ"));
161773ae441SChristopher Di Bella     test(S("1234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52),
1625a83710eSEric Fiselier          S("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
1635a83710eSEric Fiselier 
164773ae441SChristopher Di Bella     test(S("12345678901234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s),
1655a83710eSEric Fiselier          S("12345678901234567890"));
166773ae441SChristopher Di Bella     test(S("12345678901234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+1),
1675a83710eSEric Fiselier          S("12345678901234567890""A"));
168773ae441SChristopher Di Bella     test(S("12345678901234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+10),
1695a83710eSEric Fiselier          S("12345678901234567890""ABCDEFGHIJ"));
170773ae441SChristopher Di Bella     test(S("12345678901234567890"), cpp17_input_iterator<const char*>(s), cpp17_input_iterator<const char*>(s+52),
1715a83710eSEric Fiselier          S("12345678901234567890""ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
1725a83710eSEric Fiselier   }
1735a83710eSEric Fiselier #endif
1749d10d27cSMarshall Clow #ifndef TEST_HAS_NO_EXCEPTIONS
17585e9b268SNikolas Klauser   if (!TEST_IS_CONSTANT_EVALUATED) { // test iterator operations that throw
17676b4afc0SMarshall Clow     typedef std::string S;
17776b4afc0SMarshall Clow     typedef ThrowingIterator<char> TIter;
178773ae441SChristopher Di Bella     typedef cpp17_input_iterator<TIter> IIter;
17976b4afc0SMarshall Clow     const char* s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1804a47ac7dSLouis Dionne     test_exceptions(S(), IIter(TIter(s, s+10, 4, TIter::TAIncrement)), IIter(TIter()));
1814a47ac7dSLouis Dionne     test_exceptions(S(), IIter(TIter(s, s+10, 5, TIter::TADereference)), IIter(TIter()));
1824a47ac7dSLouis Dionne     test_exceptions(S(), IIter(TIter(s, s+10, 6, TIter::TAComparison)), IIter(TIter()));
18376b4afc0SMarshall Clow 
18476b4afc0SMarshall Clow     test_exceptions(S(), TIter(s, s+10, 4, TIter::TAIncrement), TIter());
18576b4afc0SMarshall Clow     test_exceptions(S(), TIter(s, s+10, 5, TIter::TADereference), TIter());
18676b4afc0SMarshall Clow     test_exceptions(S(), TIter(s, s+10, 6, TIter::TAComparison), TIter());
187e87479b0SArthur O'Dwyer 
188e87479b0SArthur O'Dwyer     Widget w[100];
189e87479b0SArthur O'Dwyer     test_exceptions(S(), w, w+100);
19076b4afc0SMarshall Clow   }
1919d10d27cSMarshall Clow #endif
1927e1a2300SMarshall Clow 
1937e1a2300SMarshall Clow   { // test appending to self
1947e1a2300SMarshall Clow     typedef std::string S;
1957e1a2300SMarshall Clow     S s_short = "123/";
1967e1a2300SMarshall Clow     S s_long  = "Lorem ipsum dolor sit amet, consectetur/";
1977e1a2300SMarshall Clow 
1987e1a2300SMarshall Clow     s_short.append(s_short.begin(), s_short.end());
1997e1a2300SMarshall Clow     assert(s_short == "123/123/");
2007e1a2300SMarshall Clow     s_short.append(s_short.begin(), s_short.end());
2017e1a2300SMarshall Clow     assert(s_short == "123/123/123/123/");
2027e1a2300SMarshall Clow     s_short.append(s_short.begin(), s_short.end());
2037e1a2300SMarshall Clow     assert(s_short == "123/123/123/123/123/123/123/123/");
2047e1a2300SMarshall Clow 
2057e1a2300SMarshall Clow     s_long.append(s_long.begin(), s_long.end());
2067e1a2300SMarshall Clow     assert(s_long == "Lorem ipsum dolor sit amet, consectetur/Lorem ipsum dolor sit amet, consectetur/");
2077e1a2300SMarshall Clow   }
2087e1a2300SMarshall Clow 
209a77bb8efSMarshall Clow   { // test appending a different type
210a77bb8efSMarshall Clow     typedef std::string S;
211a77bb8efSMarshall Clow     const uint8_t p[] = "ABCD";
212a77bb8efSMarshall Clow 
213a77bb8efSMarshall Clow     S s;
214a77bb8efSMarshall Clow     s.append(p, p + 4);
215a77bb8efSMarshall Clow     assert(s == "ABCD");
216a77bb8efSMarshall Clow   }
217a77bb8efSMarshall Clow 
218e87479b0SArthur O'Dwyer   { // regression-test appending to self in sneaky ways
219e87479b0SArthur O'Dwyer     std::string s_short = "hello";
220e87479b0SArthur O'Dwyer     std::string s_long = "Lorem ipsum dolor sit amet, consectetur/";
221e87479b0SArthur O'Dwyer     std::string s_othertype = "hello";
222e87479b0SArthur O'Dwyer     std::string s_sneaky = "hello";
223e87479b0SArthur O'Dwyer 
224e87479b0SArthur O'Dwyer     test(s_short, s_short.data() + s_short.size(), s_short.data() + s_short.size() + 1,
225e87479b0SArthur O'Dwyer          std::string("hello\0", 6));
226e87479b0SArthur O'Dwyer     test(s_long, s_long.data() + s_long.size(), s_long.data() + s_long.size() + 1,
227e87479b0SArthur O'Dwyer          std::string("Lorem ipsum dolor sit amet, consectetur/\0", 41));
228e87479b0SArthur O'Dwyer 
229e87479b0SArthur O'Dwyer     s_sneaky.reserve(12);
230e87479b0SArthur O'Dwyer     test(s_sneaky, s_sneaky.data(), s_sneaky.data() + 6, std::string("hellohello\0", 11));
23185e9b268SNikolas Klauser 
23285e9b268SNikolas Klauser      if (!TEST_IS_CONSTANT_EVALUATED) {
23385e9b268SNikolas Klauser        const unsigned char *first = reinterpret_cast<const unsigned char*>(s_othertype.data());
23485e9b268SNikolas Klauser        test(s_othertype, first + 2, first + 5, std::string("hellollo"));
23585e9b268SNikolas Klauser      }
236e87479b0SArthur O'Dwyer   }
237e87479b0SArthur O'Dwyer 
238e84fcb5fSEric Fiselier   { // test with a move iterator that returns char&&
239e84fcb5fSEric Fiselier     typedef forward_iterator<const char*> It;
240e84fcb5fSEric Fiselier     typedef std::move_iterator<It> MoveIt;
241e84fcb5fSEric Fiselier     const char p[] = "ABCD";
242e84fcb5fSEric Fiselier     std::string s;
243e84fcb5fSEric Fiselier     s.append(MoveIt(It(std::begin(p))), MoveIt(It(std::end(p) - 1)));
244e84fcb5fSEric Fiselier     assert(s == "ABCD");
245e84fcb5fSEric Fiselier   }
246e84fcb5fSEric Fiselier   { // test with a move iterator that returns char&&
247e84fcb5fSEric Fiselier     typedef const char* It;
248e84fcb5fSEric Fiselier     typedef std::move_iterator<It> MoveIt;
249e84fcb5fSEric Fiselier     const char p[] = "ABCD";
250e84fcb5fSEric Fiselier     std::string s;
251e84fcb5fSEric Fiselier     s.append(MoveIt(It(std::begin(p))), MoveIt(It(std::end(p) - 1)));
252e84fcb5fSEric Fiselier     assert(s == "ABCD");
253e84fcb5fSEric Fiselier   }
2542df59c50SJF Bastien 
255dcffa7d3SNikolas Klauser   return true;
256dcffa7d3SNikolas Klauser }
257dcffa7d3SNikolas Klauser 
main(int,char **)258dcffa7d3SNikolas Klauser int main(int, char**)
259dcffa7d3SNikolas Klauser {
260dcffa7d3SNikolas Klauser   test();
261dcffa7d3SNikolas Klauser #if TEST_STD_VER > 17
262*425620ccSNikolas Klauser   static_assert(test());
263dcffa7d3SNikolas Klauser #endif
264dcffa7d3SNikolas Klauser 
2652df59c50SJF Bastien   return 0;
2665a83710eSEric Fiselier }
267