1 // Copyright (C) 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ********************************************************************** 5 * Copyright (C) 2002-2016, International Business Machines 6 * Corporation and others. All Rights Reserved. 7 ********************************************************************** 8 * file name: iotest.cpp 9 * encoding: US-ASCII 10 * tab size: 8 (not used) 11 * indentation:4 12 * 13 * created on: 2002feb21 14 * created by: George Rhoten 15 */ 16 17 18 #include "unicode/ustream.h" 19 20 #include "unicode/ucnv.h" 21 #include "unicode/ustring.h" 22 #include "ustr_cnv.h" 23 #include "cmemory.h" 24 #include "iotest.h" 25 26 #if U_IOSTREAM_SOURCE >= 199711 27 #if defined(__GNUC__) && __GNUC__ >= 4 28 #define USE_SSTREAM 1 29 #include <sstream> 30 #else 31 // <strstream> is deprecated on some platforms, and the compiler complains very loudly if you use it. 32 #include <strstream> 33 #endif 34 #include <fstream> 35 #include <iomanip> 36 using namespace std; 37 38 #include <string.h> 39 40 U_CDECL_BEGIN 41 #if U_PLATFORM_USES_ONLY_WIN32_API 42 const UChar NEW_LINE[] = {0x0d,0x0a,0}; 43 const char C_NEW_LINE[] = {0x0d,0x0a,0}; 44 #define UTF8_NEW_LINE "\x0d\x0a" 45 #else 46 const UChar NEW_LINE[] = {0x0a,0}; 47 const char C_NEW_LINE[] = {'\n',0}; 48 #define UTF8_NEW_LINE "\x0a" 49 #endif 50 U_CDECL_END 51 52 U_CDECL_BEGIN 53 static void U_CALLCONV TestStream(void) 54 { 55 const UChar thisMu[] = { 0x74, 0x48, 0x69, 0x73, 0x3BC, 0}; 56 const UChar mu[] = { 0x6D, 0x75, 0}; 57 UnicodeString str1 = UNICODE_STRING_SIMPLE("str1"); 58 UnicodeString str2 = UNICODE_STRING_SIMPLE(" <<"); 59 UnicodeString str3 = UNICODE_STRING_SIMPLE("2"); 60 UnicodeString str4 = UNICODE_STRING_SIMPLE(" UTF-8 "); 61 UnicodeString inStr = UNICODE_STRING_SIMPLE(" UTF-8 "); 62 UnicodeString inStr2; 63 char defConvName[UCNV_MAX_CONVERTER_NAME_LENGTH*2]; 64 char inStrC[128]; 65 UErrorCode status = U_ZERO_ERROR; 66 UConverter *defConv; 67 static const char testStr[] = "\x42\x65\x67\x69\x6E\x6E\x69\x6E\x67\x20\x6F\x66\x20\x74\x65\x73\x74\x20\x73\x74\x72\x31\x20\x20\x20\x3C\x3C\x32\x31\x20" UTF8_NEW_LINE "\x20\x55\x54\x46\x2D\x38\x20\xCE\xBC\xF0\x90\x80\x81\xF0\x90\x80\x82"; 68 69 str4.append((UChar32)0x03BC); /* mu */ 70 str4.append((UChar32)0x10001); 71 str4.append((UChar32)0x10002); 72 73 /* release the default converter and use utf-8 for a bit */ 74 defConv = u_getDefaultConverter(&status); 75 if (U_FAILURE(status)) { 76 log_err("Can't get default converter\n"); 77 return; 78 } 79 ucnv_close(defConv); 80 strncpy(defConvName, ucnv_getDefaultName(), UPRV_LENGTHOF(defConvName)); 81 ucnv_setDefaultName("UTF-8"); 82 83 static const char * const TESTSTRING = "\x20\x74\x48\x69\x73\xCE\xBC\xE2\x80\x82\x20\x6D\x75\x20\x77\x6F\x72\x6C\x64"; 84 #ifdef USE_SSTREAM 85 ostringstream outTestStream; 86 istringstream inTestStream(TESTSTRING); 87 #else 88 char testStreamBuf[512]; 89 ostrstream outTestStream(testStreamBuf, sizeof(testStreamBuf)); 90 istrstream inTestStream(TESTSTRING, 0); 91 92 /* initialize testStreamBuf */ 93 memset(testStreamBuf, '*', sizeof(testStreamBuf)); 94 testStreamBuf[sizeof(testStreamBuf)-1] = 0; 95 #endif 96 97 outTestStream << "\x42\x65\x67\x69\x6E\x6E\x69\x6E\x67\x20\x6F\x66\x20\x74\x65\x73\x74\x20"; 98 outTestStream << str1 << "\x20\x20" << str2 << str3 << "\x31\x20" << UTF8_NEW_LINE << str4 << ends; 99 #ifdef USE_SSTREAM 100 string tempStr = outTestStream.str(); 101 const char *testStreamBuf = tempStr.c_str(); 102 #endif 103 if (strcmp(testStreamBuf, testStr) != 0) { 104 log_err("Got: \"%s\", Expected: \"%s\"\n", testStreamBuf, testStr); 105 } 106 107 inTestStream >> inStr >> inStr2; 108 if (inStr.compare(thisMu) != 0) { 109 u_austrncpy(inStrC, inStr.getBuffer(), inStr.length()); 110 inStrC[inStr.length()] = 0; 111 log_err("Got: \"%s\", Expected: \"tHis\\u03BC\"\n", inStrC); 112 } 113 if (inStr2.compare(mu) != 0) { 114 u_austrncpy(inStrC, inStr.getBuffer(), inStr.length()); 115 inStrC[inStr.length()] = 0; 116 log_err("Got: \"%s\", Expected: \"mu\"\n", inStrC); 117 } 118 119 /* return the default converter to the original state. */ 120 ucnv_setDefaultName(defConvName); 121 defConv = u_getDefaultConverter(&status); 122 if (U_FAILURE(status)) { 123 log_err("Can't get default converter"); 124 return; 125 } 126 127 /* Test formatting when using '<<' and UnicodeString */ 128 #ifdef USE_SSTREAM 129 ostringstream outFormatStream; 130 #else 131 char testFormatStreamBuf[512]; 132 memset(testFormatStreamBuf, 0, sizeof(testFormatStreamBuf)); 133 ostrstream outFormatStream(testFormatStreamBuf, sizeof(testFormatStreamBuf)); 134 #endif 135 UnicodeString ustr("string"); 136 137 outFormatStream << "1234567890" << setw(10) << left << ustr << " " << "0123456789"; 138 139 #ifdef USE_SSTREAM 140 tempStr = outFormatStream.str(); 141 const char *testFormatStreamBuf = tempStr.c_str(); 142 #endif 143 const char *format_test_expected = "1234567890string 0123456789"; 144 if (strcmp(format_test_expected, testFormatStreamBuf) != 0) { 145 log_err("UnicodeString format test using << operator Got: '%s' Expected: '%s'\n", testFormatStreamBuf, format_test_expected); 146 } 147 148 /* Test large buffer (size > 200) when using '<<' and UnicodeString */ 149 #ifdef USE_SSTREAM 150 ostringstream outLargeStream; 151 #else 152 char testLargeStreamBuf[512]; 153 memset(testLargeStreamBuf, 0, sizeof(testLargeStreamBuf)); 154 ostrstream outLargeStream(testLargeStreamBuf, sizeof(testLargeStreamBuf)); 155 #endif 156 UChar large_array[200]; 157 int32_t large_array_length = UPRV_LENGTHOF(large_array); 158 for (int32_t i = 0; i < large_array_length; i++) { 159 large_array[i] = 0x41; 160 } 161 UnicodeString large_array_unistr(large_array, large_array_length); 162 163 outLargeStream << large_array_unistr; 164 165 #ifdef USE_SSTREAM 166 string tmpString = outLargeStream.str(); 167 const char *testLargeStreamBuf = tmpString.c_str(); 168 #endif 169 char expectedLargeStreamBuf[300]; 170 int32_t expectedBufLength = sizeof(expectedLargeStreamBuf); 171 172 ucnv_fromUChars(defConv, expectedLargeStreamBuf, expectedBufLength, large_array, large_array_length, &status); 173 if (U_SUCCESS(status)) { 174 if (strcmp(testLargeStreamBuf, expectedLargeStreamBuf) != 0) { 175 log_err("Large UnicodeString operator << output incorrect.\n"); 176 } 177 } else { 178 log_err("Error converting string for large stream buffer testing.\n"); 179 } 180 ucnv_close(defConv); 181 } 182 183 #define IOSTREAM_GOOD_SHIFT 3 184 #define IOSTREAM_GOOD (1<<IOSTREAM_GOOD_SHIFT) 185 #define IOSTREAM_BAD_SHIFT 2 186 #define IOSTREAM_BAD (1<<IOSTREAM_BAD_SHIFT) 187 #define IOSTREAM_EOF_SHIFT 1 188 #define IOSTREAM_EOF (1<<IOSTREAM_EOF_SHIFT) 189 #define IOSTREAM_FAIL_SHIFT 0 190 #define IOSTREAM_FAIL (1<<IOSTREAM_FAIL_SHIFT) 191 192 static int32_t getBitStatus(const iostream& stream) { 193 return (stream.good()<<IOSTREAM_GOOD_SHIFT) 194 | (stream.bad()<<IOSTREAM_BAD_SHIFT) 195 | (stream.eof()<<IOSTREAM_EOF_SHIFT) 196 | (stream.fail()<<IOSTREAM_FAIL_SHIFT); 197 } 198 199 void 200 printBits(const iostream& stream) 201 { 202 int32_t status = getBitStatus(stream); 203 log_verbose("status 0x%02X (", status); 204 if (status & IOSTREAM_GOOD) { 205 log_verbose("good"); 206 } 207 if (status & IOSTREAM_BAD) { 208 log_verbose("bad"); 209 } 210 if (status & IOSTREAM_EOF) { 211 log_verbose("eof"); 212 } 213 if (status & IOSTREAM_FAIL) { 214 log_verbose("fail"); 215 } 216 log_verbose(")\n"); 217 } 218 219 void 220 testString( 221 UnicodeString& str, 222 const char* testString, 223 const UChar* expectedString, 224 int32_t expectedStatus) 225 { 226 #ifdef USE_SSTREAM 227 stringstream sstrm; 228 #else 229 strstream sstrm; 230 #endif 231 232 sstrm << testString; 233 234 /*log_verbose("iostream before operator::>>() call \"%s\" ", testString); 235 printBits(sstrm);*/ 236 237 sstrm >> str; 238 239 log_verbose("iostream after operator::>>() call \"%s\" ", testString); 240 printBits(sstrm); 241 242 if (getBitStatus(sstrm) != expectedStatus) { 243 printBits(sstrm); 244 log_err("Expected status %d, Got %d. See verbose output for details\n", expectedStatus, getBitStatus(sstrm)); 245 } 246 if (str != UnicodeString(expectedString)) { 247 log_err("Did not get expected results from \"%s\", expected \"%s\"\n", testString, expectedString); 248 } 249 } 250 251 252 static void U_CALLCONV TestStreamEOF(void) 253 { 254 UnicodeString dest; 255 fstream fs(STANDARD_TEST_FILE, fstream::in | fstream::out | fstream::trunc); 256 #ifdef USE_SSTREAM 257 stringstream ss; 258 #else 259 strstream ss; 260 #endif 261 262 fs << "EXAMPLE"; 263 fs.seekg(0); 264 ss << "EXAMPLE"; 265 266 if (!(fs >> dest)) { 267 log_err("Reading of file did not return expected status result\n"); 268 } 269 if (dest != "EXAMPLE") { 270 log_err("Reading of file did not return expected string\n"); 271 } 272 273 if (!(ss >> dest)) { 274 log_err("Reading of string did not return expected status result\n"); 275 } 276 if (dest != "EXAMPLE") { 277 log_err("Reading of string did not return expected string\n"); 278 } 279 fs.close(); 280 281 log_verbose("Testing operator >> for UnicodeString...\n"); 282 283 /* The test cases needs to be converted to the default codepage. However, the stream operator needs char* so U_STRING_* is called. */ 284 U_STRING_DECL(testCase1, "", 0); 285 U_STRING_INIT(testCase1, "", 0); 286 U_STRING_DECL(testCase2, "foo", 3); 287 U_STRING_INIT(testCase2, "foo", 3); 288 U_STRING_DECL(testCase3, " ", 3); 289 U_STRING_INIT(testCase3, " ", 3); 290 U_STRING_DECL(testCase4, " bar", 6); 291 U_STRING_INIT(testCase4, " bar", 6); 292 U_STRING_DECL(testCase5, "bar ", 6); 293 U_STRING_INIT(testCase5, "bar ", 6); 294 U_STRING_DECL(testCase6, " bar ", 9); 295 U_STRING_INIT(testCase6, " bar ", 9); 296 297 298 U_STRING_DECL(expectedResultA, "", 0); 299 U_STRING_INIT(expectedResultA, "", 0); 300 U_STRING_DECL(expectedResultB, "foo", 3); 301 U_STRING_INIT(expectedResultB, "foo", 3); 302 U_STRING_DECL(expectedResultC, "unchanged", 9); 303 U_STRING_INIT(expectedResultC, "unchanged", 9); 304 U_STRING_DECL(expectedResultD, "bar", 3); 305 U_STRING_INIT(expectedResultD, "bar", 3); 306 307 308 UnicodeString UStr; 309 UnicodeString expectedResults; 310 char testcase[10]; 311 testString(UStr, u_austrcpy(testcase, testCase1), expectedResultA, IOSTREAM_EOF|IOSTREAM_FAIL); 312 testString(UStr, u_austrcpy(testcase, testCase2), expectedResultB, IOSTREAM_EOF); 313 UStr = UnicodeString(expectedResultC); 314 testString(UStr, u_austrcpy(testcase, testCase3), expectedResultC, IOSTREAM_EOF|IOSTREAM_FAIL); 315 testString(UStr, u_austrcpy(testcase, testCase4), expectedResultD, IOSTREAM_EOF); 316 testString(UStr, u_austrcpy(testcase, testCase5), expectedResultD, IOSTREAM_GOOD); 317 testString(UStr, u_austrcpy(testcase, testCase6), expectedResultD, IOSTREAM_GOOD); 318 } 319 U_CDECL_END 320 321 U_CFUNC void addStreamTests(TestNode** root) { 322 addTest(root, &TestStream, "stream/TestStream"); 323 addTest(root, &TestStreamEOF, "stream/TestStreamEOF"); 324 } 325 #endif 326