12e5b6d6dSopenharmony_ci// © 2016 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci/* 42e5b6d6dSopenharmony_ci********************************************************************** 52e5b6d6dSopenharmony_ci* Copyright (C) 2001-2009, International Business Machines 62e5b6d6dSopenharmony_ci* Corporation and others. All Rights Reserved. 72e5b6d6dSopenharmony_ci********************************************************************** 82e5b6d6dSopenharmony_ci* Date Name Description 92e5b6d6dSopenharmony_ci* 05/23/00 aliu Creation. 102e5b6d6dSopenharmony_ci********************************************************************** 112e5b6d6dSopenharmony_ci*/ 122e5b6d6dSopenharmony_ci 132e5b6d6dSopenharmony_ci#include <algorithm> 142e5b6d6dSopenharmony_ci#include <vector> 152e5b6d6dSopenharmony_ci#include "unicode/utypes.h" 162e5b6d6dSopenharmony_ci#include "unicode/edits.h" 172e5b6d6dSopenharmony_ci#include "unicode/unistr.h" 182e5b6d6dSopenharmony_ci#include "unicode/utf16.h" 192e5b6d6dSopenharmony_ci#include "cmemory.h" 202e5b6d6dSopenharmony_ci#include "testutil.h" 212e5b6d6dSopenharmony_ci#include "intltest.h" 222e5b6d6dSopenharmony_ci 232e5b6d6dSopenharmony_cistatic const UChar HEX[] = u"0123456789ABCDEF"; 242e5b6d6dSopenharmony_ci 252e5b6d6dSopenharmony_ciUnicodeString &TestUtility::appendHex(UnicodeString &buf, UChar32 ch) { 262e5b6d6dSopenharmony_ci if (ch >= 0x10000) { 272e5b6d6dSopenharmony_ci if (ch >= 0x100000) { 282e5b6d6dSopenharmony_ci buf.append(HEX[0xF&(ch>>20)]); 292e5b6d6dSopenharmony_ci } 302e5b6d6dSopenharmony_ci buf.append(HEX[0xF&(ch>>16)]); 312e5b6d6dSopenharmony_ci } 322e5b6d6dSopenharmony_ci buf.append(HEX[0xF&(ch>>12)]); 332e5b6d6dSopenharmony_ci buf.append(HEX[0xF&(ch>>8)]); 342e5b6d6dSopenharmony_ci buf.append(HEX[0xF&(ch>>4)]); 352e5b6d6dSopenharmony_ci buf.append(HEX[0xF&ch]); 362e5b6d6dSopenharmony_ci return buf; 372e5b6d6dSopenharmony_ci} 382e5b6d6dSopenharmony_ci 392e5b6d6dSopenharmony_ciUnicodeString TestUtility::hex(UChar32 ch) { 402e5b6d6dSopenharmony_ci UnicodeString buf; 412e5b6d6dSopenharmony_ci appendHex(buf, ch); 422e5b6d6dSopenharmony_ci return buf; 432e5b6d6dSopenharmony_ci} 442e5b6d6dSopenharmony_ci 452e5b6d6dSopenharmony_ciUnicodeString TestUtility::hex(const UnicodeString& s) { 462e5b6d6dSopenharmony_ci return hex(s, u','); 472e5b6d6dSopenharmony_ci} 482e5b6d6dSopenharmony_ci 492e5b6d6dSopenharmony_ciUnicodeString TestUtility::hex(const UnicodeString& s, UChar sep) { 502e5b6d6dSopenharmony_ci UnicodeString result; 512e5b6d6dSopenharmony_ci if (s.isEmpty()) return result; 522e5b6d6dSopenharmony_ci UChar32 c; 532e5b6d6dSopenharmony_ci for (int32_t i = 0; i < s.length(); i += U16_LENGTH(c)) { 542e5b6d6dSopenharmony_ci c = s.char32At(i); 552e5b6d6dSopenharmony_ci if (i > 0) { 562e5b6d6dSopenharmony_ci result.append(sep); 572e5b6d6dSopenharmony_ci } 582e5b6d6dSopenharmony_ci appendHex(result, c); 592e5b6d6dSopenharmony_ci } 602e5b6d6dSopenharmony_ci return result; 612e5b6d6dSopenharmony_ci} 622e5b6d6dSopenharmony_ci 632e5b6d6dSopenharmony_ciUnicodeString TestUtility::hex(const uint8_t* bytes, int32_t len) { 642e5b6d6dSopenharmony_ci UnicodeString buf; 652e5b6d6dSopenharmony_ci for (int32_t i = 0; i < len; ++i) { 662e5b6d6dSopenharmony_ci buf.append(HEX[0x0F & (bytes[i] >> 4)]); 672e5b6d6dSopenharmony_ci buf.append(HEX[0x0F & bytes[i]]); 682e5b6d6dSopenharmony_ci } 692e5b6d6dSopenharmony_ci return buf; 702e5b6d6dSopenharmony_ci} 712e5b6d6dSopenharmony_ci 722e5b6d6dSopenharmony_cinamespace { 732e5b6d6dSopenharmony_ci 742e5b6d6dSopenharmony_ciUnicodeString printOneEdit(const Edits::Iterator &ei) { 752e5b6d6dSopenharmony_ci if (ei.hasChange()) { 762e5b6d6dSopenharmony_ci return UnicodeString() + ei.oldLength() + u"->" + ei.newLength(); 772e5b6d6dSopenharmony_ci } else { 782e5b6d6dSopenharmony_ci return UnicodeString() + ei.oldLength() + u"=" + ei.newLength(); 792e5b6d6dSopenharmony_ci } 802e5b6d6dSopenharmony_ci} 812e5b6d6dSopenharmony_ci 822e5b6d6dSopenharmony_ci/** 832e5b6d6dSopenharmony_ci * Maps indexes according to the expected edits. 842e5b6d6dSopenharmony_ci * A destination index can occur multiple times when there are source deletions. 852e5b6d6dSopenharmony_ci * Map according to the last occurrence, normally in a non-empty destination span. 862e5b6d6dSopenharmony_ci * Simplest is to search from the back. 872e5b6d6dSopenharmony_ci */ 882e5b6d6dSopenharmony_ciint32_t srcIndexFromDest(const EditChange expected[], int32_t expLength, 892e5b6d6dSopenharmony_ci int32_t srcLength, int32_t destLength, int32_t index) { 902e5b6d6dSopenharmony_ci int32_t srcIndex = srcLength; 912e5b6d6dSopenharmony_ci int32_t destIndex = destLength; 922e5b6d6dSopenharmony_ci int32_t i = expLength; 932e5b6d6dSopenharmony_ci while (index < destIndex && i > 0) { 942e5b6d6dSopenharmony_ci --i; 952e5b6d6dSopenharmony_ci int32_t prevSrcIndex = srcIndex - expected[i].oldLength; 962e5b6d6dSopenharmony_ci int32_t prevDestIndex = destIndex - expected[i].newLength; 972e5b6d6dSopenharmony_ci if (index == prevDestIndex) { 982e5b6d6dSopenharmony_ci return prevSrcIndex; 992e5b6d6dSopenharmony_ci } else if (index > prevDestIndex) { 1002e5b6d6dSopenharmony_ci if (expected[i].change) { 1012e5b6d6dSopenharmony_ci // In a change span, map to its end. 1022e5b6d6dSopenharmony_ci return srcIndex; 1032e5b6d6dSopenharmony_ci } else { 1042e5b6d6dSopenharmony_ci // In an unchanged span, offset within it. 1052e5b6d6dSopenharmony_ci return prevSrcIndex + (index - prevDestIndex); 1062e5b6d6dSopenharmony_ci } 1072e5b6d6dSopenharmony_ci } 1082e5b6d6dSopenharmony_ci srcIndex = prevSrcIndex; 1092e5b6d6dSopenharmony_ci destIndex = prevDestIndex; 1102e5b6d6dSopenharmony_ci } 1112e5b6d6dSopenharmony_ci // index is outside the string. 1122e5b6d6dSopenharmony_ci return srcIndex; 1132e5b6d6dSopenharmony_ci} 1142e5b6d6dSopenharmony_ci 1152e5b6d6dSopenharmony_ciint32_t destIndexFromSrc(const EditChange expected[], int32_t expLength, 1162e5b6d6dSopenharmony_ci int32_t srcLength, int32_t destLength, int32_t index) { 1172e5b6d6dSopenharmony_ci int32_t srcIndex = srcLength; 1182e5b6d6dSopenharmony_ci int32_t destIndex = destLength; 1192e5b6d6dSopenharmony_ci int32_t i = expLength; 1202e5b6d6dSopenharmony_ci while (index < srcIndex && i > 0) { 1212e5b6d6dSopenharmony_ci --i; 1222e5b6d6dSopenharmony_ci int32_t prevSrcIndex = srcIndex - expected[i].oldLength; 1232e5b6d6dSopenharmony_ci int32_t prevDestIndex = destIndex - expected[i].newLength; 1242e5b6d6dSopenharmony_ci if (index == prevSrcIndex) { 1252e5b6d6dSopenharmony_ci return prevDestIndex; 1262e5b6d6dSopenharmony_ci } else if (index > prevSrcIndex) { 1272e5b6d6dSopenharmony_ci if (expected[i].change) { 1282e5b6d6dSopenharmony_ci // In a change span, map to its end. 1292e5b6d6dSopenharmony_ci return destIndex; 1302e5b6d6dSopenharmony_ci } else { 1312e5b6d6dSopenharmony_ci // In an unchanged span, offset within it. 1322e5b6d6dSopenharmony_ci return prevDestIndex + (index - prevSrcIndex); 1332e5b6d6dSopenharmony_ci } 1342e5b6d6dSopenharmony_ci } 1352e5b6d6dSopenharmony_ci srcIndex = prevSrcIndex; 1362e5b6d6dSopenharmony_ci destIndex = prevDestIndex; 1372e5b6d6dSopenharmony_ci } 1382e5b6d6dSopenharmony_ci // index is outside the string. 1392e5b6d6dSopenharmony_ci return destIndex; 1402e5b6d6dSopenharmony_ci} 1412e5b6d6dSopenharmony_ci 1422e5b6d6dSopenharmony_ci} // namespace 1432e5b6d6dSopenharmony_ci 1442e5b6d6dSopenharmony_ci// For debugging, set -v to see matching edits up to a failure. 1452e5b6d6dSopenharmony_ciUBool TestUtility::checkEqualEdits(IntlTest &test, const UnicodeString &name, 1462e5b6d6dSopenharmony_ci const Edits &e1, const Edits &e2, UErrorCode &errorCode) { 1472e5b6d6dSopenharmony_ci Edits::Iterator ei1 = e1.getFineIterator(); 1482e5b6d6dSopenharmony_ci Edits::Iterator ei2 = e2.getFineIterator(); 1492e5b6d6dSopenharmony_ci UBool ok = true; 1502e5b6d6dSopenharmony_ci for (int32_t i = 0; ok; ++i) { 1512e5b6d6dSopenharmony_ci UBool ei1HasNext = ei1.next(errorCode); 1522e5b6d6dSopenharmony_ci UBool ei2HasNext = ei2.next(errorCode); 1532e5b6d6dSopenharmony_ci ok &= test.assertEquals(name + u" next()[" + i + u"]" + __LINE__, 1542e5b6d6dSopenharmony_ci ei1HasNext, ei2HasNext); 1552e5b6d6dSopenharmony_ci ok &= test.assertSuccess(name + u" errorCode[" + i + u"]" + __LINE__, errorCode); 1562e5b6d6dSopenharmony_ci ok &= test.assertEquals(name + u" edit[" + i + u"]" + __LINE__, 1572e5b6d6dSopenharmony_ci printOneEdit(ei1), printOneEdit(ei2)); 1582e5b6d6dSopenharmony_ci if (!ei1HasNext || !ei2HasNext) { 1592e5b6d6dSopenharmony_ci break; 1602e5b6d6dSopenharmony_ci } 1612e5b6d6dSopenharmony_ci test.logln(); 1622e5b6d6dSopenharmony_ci } 1632e5b6d6dSopenharmony_ci return ok; 1642e5b6d6dSopenharmony_ci} 1652e5b6d6dSopenharmony_ci 1662e5b6d6dSopenharmony_civoid TestUtility::checkEditsIter( 1672e5b6d6dSopenharmony_ci IntlTest &test, 1682e5b6d6dSopenharmony_ci const UnicodeString &name, 1692e5b6d6dSopenharmony_ci Edits::Iterator ei1, Edits::Iterator ei2, // two equal iterators 1702e5b6d6dSopenharmony_ci const EditChange expected[], int32_t expLength, UBool withUnchanged, 1712e5b6d6dSopenharmony_ci UErrorCode &errorCode) { 1722e5b6d6dSopenharmony_ci test.assertFalse(name + u":" + __LINE__, ei2.findSourceIndex(-1, errorCode)); 1732e5b6d6dSopenharmony_ci test.assertFalse(name + u":" + __LINE__, ei2.findDestinationIndex(-1, errorCode)); 1742e5b6d6dSopenharmony_ci 1752e5b6d6dSopenharmony_ci int32_t expSrcIndex = 0; 1762e5b6d6dSopenharmony_ci int32_t expDestIndex = 0; 1772e5b6d6dSopenharmony_ci int32_t expReplIndex = 0; 1782e5b6d6dSopenharmony_ci for (int32_t expIndex = 0; expIndex < expLength; ++expIndex) { 1792e5b6d6dSopenharmony_ci const EditChange &expect = expected[expIndex]; 1802e5b6d6dSopenharmony_ci UnicodeString msg = UnicodeString(name).append(u' ') + expIndex; 1812e5b6d6dSopenharmony_ci if (withUnchanged || expect.change) { 1822e5b6d6dSopenharmony_ci test.assertTrue(msg + u":" + __LINE__, ei1.next(errorCode)); 1832e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expect.change, ei1.hasChange()); 1842e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expect.oldLength, ei1.oldLength()); 1852e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expect.newLength, ei1.newLength()); 1862e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expSrcIndex, ei1.sourceIndex()); 1872e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expDestIndex, ei1.destinationIndex()); 1882e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expReplIndex, ei1.replacementIndex()); 1892e5b6d6dSopenharmony_ci } 1902e5b6d6dSopenharmony_ci 1912e5b6d6dSopenharmony_ci if (expect.oldLength > 0) { 1922e5b6d6dSopenharmony_ci test.assertTrue(msg + u":" + __LINE__, ei2.findSourceIndex(expSrcIndex, errorCode)); 1932e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expect.change, ei2.hasChange()); 1942e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expect.oldLength, ei2.oldLength()); 1952e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expect.newLength, ei2.newLength()); 1962e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expSrcIndex, ei2.sourceIndex()); 1972e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expDestIndex, ei2.destinationIndex()); 1982e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expReplIndex, ei2.replacementIndex()); 1992e5b6d6dSopenharmony_ci if (!withUnchanged) { 2002e5b6d6dSopenharmony_ci // For some iterators, move past the current range 2012e5b6d6dSopenharmony_ci // so that findSourceIndex() has to look before the current index. 2022e5b6d6dSopenharmony_ci ei2.next(errorCode); 2032e5b6d6dSopenharmony_ci ei2.next(errorCode); 2042e5b6d6dSopenharmony_ci } 2052e5b6d6dSopenharmony_ci } 2062e5b6d6dSopenharmony_ci 2072e5b6d6dSopenharmony_ci if (expect.newLength > 0) { 2082e5b6d6dSopenharmony_ci test.assertTrue(msg + u":" + __LINE__, ei2.findDestinationIndex(expDestIndex, errorCode)); 2092e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expect.change, ei2.hasChange()); 2102e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expect.oldLength, ei2.oldLength()); 2112e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expect.newLength, ei2.newLength()); 2122e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expSrcIndex, ei2.sourceIndex()); 2132e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expDestIndex, ei2.destinationIndex()); 2142e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expReplIndex, ei2.replacementIndex()); 2152e5b6d6dSopenharmony_ci if (!withUnchanged) { 2162e5b6d6dSopenharmony_ci // For some iterators, move past the current range 2172e5b6d6dSopenharmony_ci // so that findSourceIndex() has to look before the current index. 2182e5b6d6dSopenharmony_ci ei2.next(errorCode); 2192e5b6d6dSopenharmony_ci ei2.next(errorCode); 2202e5b6d6dSopenharmony_ci } 2212e5b6d6dSopenharmony_ci } 2222e5b6d6dSopenharmony_ci 2232e5b6d6dSopenharmony_ci expSrcIndex += expect.oldLength; 2242e5b6d6dSopenharmony_ci expDestIndex += expect.newLength; 2252e5b6d6dSopenharmony_ci if (expect.change) { 2262e5b6d6dSopenharmony_ci expReplIndex += expect.newLength; 2272e5b6d6dSopenharmony_ci } 2282e5b6d6dSopenharmony_ci } 2292e5b6d6dSopenharmony_ci UnicodeString msg = UnicodeString(name).append(u" end"); 2302e5b6d6dSopenharmony_ci test.assertFalse(msg + u":" + __LINE__, ei1.next(errorCode)); 2312e5b6d6dSopenharmony_ci test.assertFalse(msg + u":" + __LINE__, ei1.hasChange()); 2322e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, 0, ei1.oldLength()); 2332e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, 0, ei1.newLength()); 2342e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expSrcIndex, ei1.sourceIndex()); 2352e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expDestIndex, ei1.destinationIndex()); 2362e5b6d6dSopenharmony_ci test.assertEquals(msg + u":" + __LINE__, expReplIndex, ei1.replacementIndex()); 2372e5b6d6dSopenharmony_ci 2382e5b6d6dSopenharmony_ci test.assertFalse(name + u":" + __LINE__, ei2.findSourceIndex(expSrcIndex, errorCode)); 2392e5b6d6dSopenharmony_ci test.assertFalse(name + u":" + __LINE__, ei2.findDestinationIndex(expDestIndex, errorCode)); 2402e5b6d6dSopenharmony_ci 2412e5b6d6dSopenharmony_ci // Check mapping of all indexes against a simple implementation 2422e5b6d6dSopenharmony_ci // that works on the expected changes. 2432e5b6d6dSopenharmony_ci // Iterate once forward, once backward, to cover more runtime conditions. 2442e5b6d6dSopenharmony_ci int32_t srcLength = expSrcIndex; 2452e5b6d6dSopenharmony_ci int32_t destLength = expDestIndex; 2462e5b6d6dSopenharmony_ci std::vector<int32_t> srcIndexes; 2472e5b6d6dSopenharmony_ci std::vector<int32_t> destIndexes; 2482e5b6d6dSopenharmony_ci srcIndexes.push_back(-1); 2492e5b6d6dSopenharmony_ci destIndexes.push_back(-1); 2502e5b6d6dSopenharmony_ci int32_t srcIndex = 0; 2512e5b6d6dSopenharmony_ci int32_t destIndex = 0; 2522e5b6d6dSopenharmony_ci for (int32_t i = 0; i < expLength; ++i) { 2532e5b6d6dSopenharmony_ci if (expected[i].oldLength > 0) { 2542e5b6d6dSopenharmony_ci srcIndexes.push_back(srcIndex); 2552e5b6d6dSopenharmony_ci if (expected[i].oldLength > 1) { 2562e5b6d6dSopenharmony_ci srcIndexes.push_back(srcIndex + 1); 2572e5b6d6dSopenharmony_ci if (expected[i].oldLength > 2) { 2582e5b6d6dSopenharmony_ci srcIndexes.push_back(srcIndex + expected[i].oldLength - 1); 2592e5b6d6dSopenharmony_ci } 2602e5b6d6dSopenharmony_ci } 2612e5b6d6dSopenharmony_ci } 2622e5b6d6dSopenharmony_ci if (expected[i].newLength > 0) { 2632e5b6d6dSopenharmony_ci destIndexes.push_back(destIndex); 2642e5b6d6dSopenharmony_ci if (expected[i].newLength > 1) { 2652e5b6d6dSopenharmony_ci destIndexes.push_back(destIndex + 1); 2662e5b6d6dSopenharmony_ci if (expected[i].newLength > 2) { 2672e5b6d6dSopenharmony_ci destIndexes.push_back(destIndex + expected[i].newLength - 1); 2682e5b6d6dSopenharmony_ci } 2692e5b6d6dSopenharmony_ci } 2702e5b6d6dSopenharmony_ci } 2712e5b6d6dSopenharmony_ci srcIndex += expected[i].oldLength; 2722e5b6d6dSopenharmony_ci destIndex += expected[i].newLength; 2732e5b6d6dSopenharmony_ci } 2742e5b6d6dSopenharmony_ci srcIndexes.push_back(srcLength); 2752e5b6d6dSopenharmony_ci destIndexes.push_back(destLength); 2762e5b6d6dSopenharmony_ci srcIndexes.push_back(srcLength + 1); 2772e5b6d6dSopenharmony_ci destIndexes.push_back(destLength + 1); 2782e5b6d6dSopenharmony_ci std::reverse(destIndexes.begin(), destIndexes.end()); 2792e5b6d6dSopenharmony_ci // Zig-zag across the indexes to stress next() <-> previous(). 2802e5b6d6dSopenharmony_ci static const int32_t ZIG_ZAG[] = { 0, 1, 2, 3, 2, 1 }; 2812e5b6d6dSopenharmony_ci for (auto i = 0; i < (int32_t)srcIndexes.size(); ++i) { 2822e5b6d6dSopenharmony_ci for (int32_t ij = 0; ij < UPRV_LENGTHOF(ZIG_ZAG); ++ij) { 2832e5b6d6dSopenharmony_ci int32_t j = ZIG_ZAG[ij]; 2842e5b6d6dSopenharmony_ci if ((i + j) < (int32_t)srcIndexes.size()) { 2852e5b6d6dSopenharmony_ci int32_t si = srcIndexes[i + j]; 2862e5b6d6dSopenharmony_ci test.assertEquals(name + u" destIndexFromSrc(" + si + u"):" + __LINE__, 2872e5b6d6dSopenharmony_ci destIndexFromSrc(expected, expLength, srcLength, destLength, si), 2882e5b6d6dSopenharmony_ci ei2.destinationIndexFromSourceIndex(si, errorCode)); 2892e5b6d6dSopenharmony_ci } 2902e5b6d6dSopenharmony_ci } 2912e5b6d6dSopenharmony_ci } 2922e5b6d6dSopenharmony_ci for (auto i = 0; i < (int32_t)destIndexes.size(); ++i) { 2932e5b6d6dSopenharmony_ci for (int32_t ij = 0; ij < UPRV_LENGTHOF(ZIG_ZAG); ++ij) { 2942e5b6d6dSopenharmony_ci int32_t j = ZIG_ZAG[ij]; 2952e5b6d6dSopenharmony_ci if ((i + j) < (int32_t)destIndexes.size()) { 2962e5b6d6dSopenharmony_ci int32_t di = destIndexes[i + j]; 2972e5b6d6dSopenharmony_ci test.assertEquals(name + u" srcIndexFromDest(" + di + u"):" + __LINE__, 2982e5b6d6dSopenharmony_ci srcIndexFromDest(expected, expLength, srcLength, destLength, di), 2992e5b6d6dSopenharmony_ci ei2.sourceIndexFromDestinationIndex(di, errorCode)); 3002e5b6d6dSopenharmony_ci } 3012e5b6d6dSopenharmony_ci } 3022e5b6d6dSopenharmony_ci } 3032e5b6d6dSopenharmony_ci} 304