]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/test/intltest/strtest.cpp
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / intltest / strtest.cpp
index ccc618a55444ad6fd72b046153b46b42053c864b..7bb9662c36c58b01c7325d53fd4c4b43e309ac0c 100644 (file)
 *   created by: Markus W. Scherer
 */
 
+#ifdef U_HAVE_STRING_VIEW
+#include <string_view>
+#endif
+
+#include <cstddef>
 #include <string.h>
 
 #include "unicode/utypes.h"
@@ -28,6 +33,7 @@
 #include "cstr.h"
 #include "intltest.h"
 #include "strtest.h"
+#include "uinvchar.h"
 
 StringTest::~StringTest() {}
 
@@ -142,26 +148,82 @@ StringTest::Test_UNICODE_STRING_SIMPLE() {
     }
 }
 
+namespace {
+
+// See U_CHARSET_FAMILY in unicode/platform.h.
+const char *nativeInvChars =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyz"
+    "0123456789 \"%&'()*+,-./:;<=>?_";
+const char16_t *asciiInvChars =
+    u"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    u"abcdefghijklmnopqrstuvwxyz"
+    u"0123456789 \"%&'()*+,-./:;<=>?_";
+
+}  // namespace
+
+void
+StringTest::TestUpperOrdinal() {
+    for (int32_t i = 0;; ++i) {
+        char ic = nativeInvChars[i];
+        uint8_t ac = asciiInvChars[i];
+        int32_t expected = ac - 'A';
+        int32_t actual = uprv_upperOrdinal(ic);
+        if (0 <= expected && expected <= 25) {
+            if (actual != expected) {
+                errln("uprv_upperOrdinal('%c')=%d != expected %d",
+                      ic, (int)actual, (int)expected);
+            }
+        } else {
+            if (0 <= actual && actual <= 25) {
+                errln("uprv_upperOrdinal('%c')=%d should have been outside 0..25",
+                      ic, (int)actual);
+            }
+        }
+        if (ic == 0) { break; }
+    }
+}
+
+void
+StringTest::TestLowerOrdinal() {
+    for (int32_t i = 0;; ++i) {
+        char ic = nativeInvChars[i];
+        uint8_t ac = asciiInvChars[i];
+        int32_t expected = ac - 'a';
+        int32_t actual = uprv_lowerOrdinal(ic);
+        if (0 <= expected && expected <= 25) {
+            if (actual != expected) {
+                errln("uprv_lowerOrdinal('%c')=%d != expected %d",
+                      ic, (int)actual, (int)expected);
+            }
+        } else {
+            if (0 <= actual && actual <= 25) {
+                errln("uprv_lowerOrdinal('%c')=%d should have been outside 0..25",
+                      ic, (int)actual);
+            }
+        }
+        if (ic == 0) { break; }
+    }
+}
+
 void
 StringTest::Test_UTF8_COUNT_TRAIL_BYTES() {
+#if !U_HIDE_OBSOLETE_UTF_OLD_H
     if(UTF8_COUNT_TRAIL_BYTES(0x7F) != 0
-        || UTF8_COUNT_TRAIL_BYTES(0xC0) != 1
-        || UTF8_COUNT_TRAIL_BYTES(0xE0) != 2
-        || UTF8_COUNT_TRAIL_BYTES(0xF0) != 3)
-    {
-        errln("Test_UTF8_COUNT_TRAIL_BYTES: UTF8_COUNT_TRAIL_BYTES does not work right! "
-              "See utf_old.h.");
-    }
-       // Note: U8_COUNT_TRAIL_BYTES (current) and UTF8_COUNT_TRAIL_BYTES (deprecated)
-       //       have completely different implementations.
-       if (U8_COUNT_TRAIL_BYTES(0x7F) != 0
-               || U8_COUNT_TRAIL_BYTES(0xC0) != 1
-               || U8_COUNT_TRAIL_BYTES(0xE0) != 2
-               || U8_COUNT_TRAIL_BYTES(0xF0) != 3)
-       {
-               errln("Test_UTF8_COUNT_TRAIL_BYTES: U8_COUNT_TRAIL_BYTES does not work right! "
-                       "See utf8.h.");
-       }
+            || UTF8_COUNT_TRAIL_BYTES(0xC2) != 1
+            || UTF8_COUNT_TRAIL_BYTES(0xE0) != 2
+            || UTF8_COUNT_TRAIL_BYTES(0xF0) != 3) {
+        errln("UTF8_COUNT_TRAIL_BYTES does not work right! See utf_old.h.");
+    }
+#endif
+    // Note: U8_COUNT_TRAIL_BYTES (current) and UTF8_COUNT_TRAIL_BYTES (deprecated)
+    //       have completely different implementations.
+    if (U8_COUNT_TRAIL_BYTES(0x7F) != 0
+            || U8_COUNT_TRAIL_BYTES(0xC2) != 1
+            || U8_COUNT_TRAIL_BYTES(0xE0) != 2
+            || U8_COUNT_TRAIL_BYTES(0xF0) != 3) {
+        errln("U8_COUNT_TRAIL_BYTES does not work right! See utf8.h.");
+    }
 }
 
 void StringTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) {
@@ -175,10 +237,16 @@ void StringTest::runIndexedTest(int32_t index, UBool exec, const char *&name, ch
     TESTCASE_AUTO(Test_U_STRING);
     TESTCASE_AUTO(Test_UNICODE_STRING);
     TESTCASE_AUTO(Test_UNICODE_STRING_SIMPLE);
+    TESTCASE_AUTO(TestUpperOrdinal);
+    TESTCASE_AUTO(TestLowerOrdinal);
     TESTCASE_AUTO(Test_UTF8_COUNT_TRAIL_BYTES);
     TESTCASE_AUTO(TestSTLCompatibility);
     TESTCASE_AUTO(TestStringPiece);
     TESTCASE_AUTO(TestStringPieceComparisons);
+    TESTCASE_AUTO(TestStringPieceOther);
+#ifdef U_HAVE_STRING_VIEW
+    TESTCASE_AUTO(TestStringPieceStringView);
+#endif
     TESTCASE_AUTO(TestByteSink);
     TESTCASE_AUTO(TestCheckedArrayByteSink);
     TESTCASE_AUTO(TestStringByteSink);
@@ -348,6 +416,36 @@ StringTest::TestStringPieceComparisons() {
     }
 }
 
+void
+StringTest::TestStringPieceOther() {
+    static constexpr char msg[] = "Kapow!";
+
+    // Another string piece implementation.
+    struct Other {
+        const char* data() { return msg; }
+        size_t size() { return sizeof msg - 1; }
+    };
+
+    Other other;
+    StringPiece piece(other);
+
+    assertEquals("size()", piece.size(), other.size());
+    assertEquals("data()", piece.data(), other.data());
+}
+
+#ifdef U_HAVE_STRING_VIEW
+void
+StringTest::TestStringPieceStringView() {
+    static constexpr char msg[] = "Kapow!";
+
+    std::string_view view(msg);  // C++17
+    StringPiece piece(view);
+
+    assertEquals("size()", piece.size(), view.size());
+    assertEquals("data()", piece.data(), view.data());
+}
+#endif
+
 // Verify that ByteSink is subclassable and Flush() overridable.
 class SimpleByteSink : public ByteSink {
 public:
@@ -461,7 +559,7 @@ StringTest::TestCheckedArrayByteSink() {
 
 void
 StringTest::TestStringByteSink() {
-    // Not much to test because only the constructor and Append()
+    // Not much to test because only the constructors and Append()
     // are implemented, and trivially so.
     std::string result("abc");  // std::string
     StringByteSink<std::string> sink(&result);
@@ -469,6 +567,15 @@ StringTest::TestStringByteSink() {
     if(result != "abcdef") {
         errln("StringByteSink did not Append() as expected");
     }
+    StringByteSink<std::string> sink2(&result, 20);
+    if(result.capacity() < (result.length() + 20)) {
+        errln("StringByteSink should have 20 append capacity, has only %d",
+              (int)(result.capacity() - result.length()));
+    }
+    sink.Append("ghi", 3);
+    if(result != "abcdefghi") {
+        errln("StringByteSink did not Append() as expected");
+    }
 }
 
 #if defined(_MSC_VER)
@@ -544,6 +651,28 @@ StringTest::TestCharString() {
     if (chStr.length() != 0) {
         errln("%s:%d expected length() = 0, got %d", __FILE__, __LINE__, chStr.length());
     }
+
+    {
+        CharString s1("Short string", errorCode);
+        CharString s2(std::move(s1));
+        assertEquals("s2 should have content of s1", "Short string", s2.data());
+        CharString s3("Dummy", errorCode);
+        s3 = std::move(s2);
+        assertEquals("s3 should have content of s2", "Short string", s3.data());
+    }
+
+    {
+        CharString s1("Long string over 40 characters to trigger heap allocation", errorCode);
+        CharString s2(std::move(s1));
+        assertEquals("s2 should have content of s1",
+                "Long string over 40 characters to trigger heap allocation",
+                s2.data());
+        CharString s3("Dummy string with over 40 characters to trigger heap allocation", errorCode);
+        s3 = std::move(s2);
+        assertEquals("s3 should have content of s2",
+                "Long string over 40 characters to trigger heap allocation",
+                s3.data());
+    }
 }
 
 void