Line data Source code
1 : // Copyright (c) 2013-2022 Made to Order Software Corporation
2 : //
3 : // https://snapwebsites.org/project/libutf8
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 :
20 : // libutf8
21 : //
22 : #include <libutf8/exception.h>
23 : #include <libutf8/libutf8.h>
24 :
25 :
26 : // unit test
27 : //
28 : #include "catch_main.h"
29 :
30 :
31 : // C++
32 : //
33 : #include <cctype>
34 : #include <iostream>
35 : #include <iomanip>
36 :
37 :
38 : // last include
39 : //
40 : #include <snapdev/poison.h>
41 :
42 :
43 :
44 3 : CATCH_TEST_CASE("string_length", "[strings][valid][length][u8][u16][u32]")
45 : {
46 2 : CATCH_START_SECTION("string_length: length of valid Unicode strings")
47 : {
48 101 : for(int idx(0); idx < 100; ++idx)
49 : {
50 100 : std::size_t const length(rand() % 100 + 1);
51 200 : std::u32string str32;
52 5282 : for(std::size_t j(0); j < length; ++j)
53 : {
54 5182 : char32_t const c(SNAP_CATCH2_NAMESPACE::random_char(SNAP_CATCH2_NAMESPACE::character_t::CHARACTER_ZUNICODE));
55 5182 : str32 += c;
56 : }
57 100 : CATCH_REQUIRE(libutf8::is_valid_unicode(str32));
58 100 : CATCH_REQUIRE(str32.length() == length);
59 :
60 200 : std::string str8(libutf8::to_u8string(str32));
61 100 : CATCH_REQUIRE(libutf8::is_valid_utf8(str8));
62 100 : CATCH_REQUIRE(str8.length() >= length);
63 100 : CATCH_REQUIRE(libutf8::u8length(str8) == length);
64 :
65 200 : std::u16string str16(libutf8::to_u16string(str8));
66 100 : CATCH_REQUIRE(libutf8::is_valid_utf16(str16));
67 100 : CATCH_REQUIRE(str16.length() >= length);
68 100 : CATCH_REQUIRE(static_cast<std::size_t>(libutf8::u16length(str16)) == length);
69 : }
70 : }
71 : CATCH_END_SECTION()
72 1 : }
73 :
74 :
75 3 : CATCH_TEST_CASE("invalid_utf16_string_length", "[strings][invalid][length][u16]")
76 : {
77 2 : CATCH_START_SECTION("invalid_utf16_string_length: invalid UTF-16 returns -1 for length")
78 : {
79 101 : for(int idx(0); idx < 100; ++idx)
80 : {
81 100 : std::size_t const length(rand() % 30 + 5);
82 100 : char16_t bad_char(rand() & 0x03FF);
83 100 : std::size_t bad_pos(length / 2);
84 100 : switch(idx % 3)
85 : {
86 34 : case 0:
87 34 : bad_char += 0xDC00; // low without a high
88 34 : break;
89 :
90 33 : case 1:
91 33 : bad_char += 0xD800; // high not followed by a low
92 33 : break;
93 :
94 33 : case 2:
95 33 : bad_char += 0xD800; // high followed by u'\0'
96 33 : bad_pos = length - 1;
97 33 : break;
98 :
99 : }
100 200 : std::u16string str16;
101 2005 : for(std::size_t j(0); j < length; ++j)
102 : {
103 1905 : char32_t const wc(SNAP_CATCH2_NAMESPACE::random_char(SNAP_CATCH2_NAMESPACE::character_t::CHARACTER_ZUNICODE));
104 1905 : str16 += libutf8::to_u16string(wc);
105 1905 : if(j == bad_pos)
106 : {
107 100 : str16 += bad_char;
108 : }
109 : }
110 :
111 100 : CATCH_REQUIRE_FALSE(libutf8::is_valid_utf16(str16));
112 100 : CATCH_REQUIRE(libutf8::u16length(str16) == -1);
113 : }
114 : }
115 : CATCH_END_SECTION()
116 7 : }
117 :
118 :
119 : // vim: ts=4 sw=4 et
|