]> 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 9ced1fd5a4a8043ee45f1023fc79af155be43c7f..7bb9662c36c58b01c7325d53fd4c4b43e309ac0c 100644 (file)
@@ -1,10 +1,12 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /********************************************************************
  * COPYRIGHT: 
- * Copyright (c) 1997-2010, International Business Machines Corporation and
+ * Copyright (c) 1997-2015, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 /*   file name:  strtest.cpp
-*   encoding:   US-ASCII
+*   encoding:   UTF-8
 *   tab size:   8 (not used)
 *   indentation:4
 *
 *   created by: Markus W. Scherer
 */
 
+#ifdef U_HAVE_STRING_VIEW
+#include <string_view>
+#endif
+
+#include <cstddef>
 #include <string.h>
 
 #include "unicode/utypes.h"
 #include "unicode/stringpiece.h"
 #include "unicode/unistr.h"
 #include "unicode/ustring.h"
+#include "unicode/utf_old.h"    // for UTF8_COUNT_TRAIL_BYTES
+#include "unicode/utf8.h"
 #include "charstr.h"
+#include "cstr.h"
 #include "intltest.h"
 #include "strtest.h"
+#include "uinvchar.h"
 
 StringTest::~StringTest() {}
 
@@ -94,7 +105,7 @@ U_STRING_DECL(ustringVar, "aZ0 -", 5);
 void
 StringTest::Test_U_STRING() {
     U_STRING_INIT(ustringVar, "aZ0 -", 5);
-    if( sizeof(ustringVar)/sizeof(*ustringVar)!=6 ||
+    if( u_strlen(ustringVar)!=5 ||
         ustringVar[0]!=0x61 ||
         ustringVar[1]!=0x5a ||
         ustringVar[2]!=0x30 ||
@@ -137,15 +148,81 @@ 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 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.");
     }
 }
 
@@ -160,49 +237,25 @@ 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(TestStdNamespaceQualifier);
-    TESTCASE_AUTO(TestUsingStdNamespace);
     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);
     TESTCASE_AUTO(TestCharString);
+    TESTCASE_AUTO(TestCStr);
+    TESTCASE_AUTO(Testctou);
     TESTCASE_AUTO_END;
 }
 
-// Syntax check for the correct namespace qualifier for the standard string class.
-void
-StringTest::TestStdNamespaceQualifier() {
-#if U_HAVE_STD_STRING
-    U_STD_NSQ string s="abc xyz";
-    U_STD_NSQ string t="abc";
-    t.append(" ");
-    t.append("xyz");
-    if(s!=t) {
-        errln("standard string concatenation error: %s != %s", s.c_str(), t.c_str());
-    }
-#endif
-}
-
-void
-StringTest::TestUsingStdNamespace() {
-#if U_HAVE_STD_STRING
-    // Now test that "using namespace std;" is defined correctly.
-    U_STD_NS_USE
-
-    string s="abc xyz";
-    string t="abc";
-    t.append(" ");
-    t.append("xyz");
-    if(s!=t) {
-        errln("standard string concatenation error: %s != %s", s.c_str(), t.c_str());
-    }
-#endif
-}
-
 void
 StringTest::TestStringPiece() {
     // Default constructor.
@@ -227,14 +280,12 @@ StringTest::TestStringPiece() {
     if(abcd.empty() || abcd.data()!=abcdefg_chars || abcd.length()!=4 || abcd.size()!=4) {
         errln("StringPiece(abcdefg_chars, 4) failed");
     }
-#if U_HAVE_STD_STRING
     // Construct from std::string.
-    U_STD_NSQ string uvwxyz_string("uvwxyz");
+    std::string uvwxyz_string("uvwxyz");
     StringPiece uvwxyz(uvwxyz_string);
     if(uvwxyz.empty() || uvwxyz.data()!=uvwxyz_string.data() || uvwxyz.length()!=6 || uvwxyz.size()!=6) {
         errln("StringPiece(uvwxyz_string) failed");
     }
-#endif
     // Substring constructor with pos.
     StringPiece sp(abcd, -1);
     if(sp.empty() || sp.data()!=abcdefg_chars || sp.length()!=4 || sp.size()!=4) {
@@ -365,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:
@@ -478,25 +559,32 @@ StringTest::TestCheckedArrayByteSink() {
 
 void
 StringTest::TestStringByteSink() {
-#if U_HAVE_STD_STRING
-    // 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.
-    U_STD_NSQ string result("abc");  // std::string
-    StringByteSink<U_STD_NSQ string> sink(&result);
+    std::string result("abc");  // std::string
+    StringByteSink<std::string> sink(&result);
     sink.Append("def", 3);
     if(result != "abcdef") {
         errln("StringByteSink did not Append() as expected");
     }
-#endif
+    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(U_WINDOWS) && defined(_MSC_VER)
+#if defined(_MSC_VER)
 #include <vector>
 #endif
 
 void
 StringTest::TestSTLCompatibility() {
-#if defined(U_WINDOWS) && defined(_MSC_VER)
+#if defined(_MSC_VER)
     /* Just make sure that it compiles with STL's placement new usage. */
     std::vector<UnicodeString> myvect;
     myvect.push_back(UnicodeString("blah"));
@@ -553,4 +641,53 @@ StringTest::TestCharString() {
     if (0 != strcmp(expected, chStr.data()) || (int32_t)strlen(expected) != chStr.length()) {
         errln("CharString.getAppendBuffer().append(**) failed.");
     }
+
+    UErrorCode ec = U_ZERO_ERROR;
+    chStr.clear();
+    chStr.appendInvariantChars(UnicodeString("The '@' character is not invariant."), ec);
+    if (ec != U_INVARIANT_CONVERSION_ERROR) {
+        errln("%s:%d expected U_INVARIANT_CONVERSION_ERROR, got %s", __FILE__, __LINE__, u_errorName(ec));
+    }
+    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
+StringTest::TestCStr() {
+    const char *cs = "This is a test string.";
+    UnicodeString us(cs);
+    if (0 != strcmp(CStr(us)(), cs)) {
+        errln("%s:%d CStr(s)() failed. Expected \"%s\", got \"%s\"", __FILE__, __LINE__, cs, CStr(us)());
+    }
+}
+
+void
+StringTest::Testctou() {
+  const char *cs = "Fa\\u0127mu";
+  UnicodeString u = ctou(cs);
+  assertEquals("Testing unescape@0", (int32_t)0x0046, u.charAt(0));
+  assertEquals("Testing unescape@2", (int32_t)295, u.charAt(2));
 }