blob: 9885823dca8ca68d117b95f0e523b22919a3e470 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "PhoneticStringUtils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <utils/String8.h>
using namespace android;
class TestExecutor {
public:
TestExecutor() : m_total_count(0), m_success_count(0), m_success(true) {}
bool DoAllTests();
private:
void DoOneTest(void (TestExecutor::*test)());
void testUtf32At();
void testGetUtf8FromUtf32();
void testGetNormalizedString();
void testLongString();
// Note: When adding a test, do not forget to add it to DoOneTest().
int m_total_count;
int m_success_count;
bool m_success;
};
#define ASSERT_EQ_VALUE(input, expected) \
({ \
if ((expected) != (input)) { \
printf("0x%X(result) != 0x%X(expected)\n", input, expected); \
m_success = false; \
return; \
} \
})
#define EXPECT_EQ_VALUE(input, expected) \
({ \
if ((expected) != (input)) { \
printf("0x%X(result) != 0x%X(expected)\n", input, expected); \
m_success = false; \
} \
})
bool TestExecutor::DoAllTests() {
DoOneTest(&TestExecutor::testUtf32At);
DoOneTest(&TestExecutor::testGetUtf8FromUtf32);
DoOneTest(&TestExecutor::testGetNormalizedString);
DoOneTest(&TestExecutor::testLongString);
printf("Test total: %d\nSuccess: %d\nFailure: %d\n",
m_total_count, m_success_count, m_total_count - m_success_count);
bool success = m_total_count == m_success_count;
printf("\n%s\n", success ? "Success" : "Failure");
return success;
}
void TestExecutor::DoOneTest(void (TestExecutor::*test)()) {
m_success = true;
(this->*test)();
++m_total_count;
m_success_count += m_success ? 1 : 0;
}
#define TEST_GET_UTF32AT(src, index, expected_next, expected_value) \
({ \
size_t next; \
int32_t ret = utf32_from_utf8_at(src, strlen(src), index, &next); \
if (ret < 0) { \
printf("getUtf32At() returned negative value (src: %s, index: %d)\n", \
(src), (index)); \
m_success = false; \
} else if (next != (expected_next)) { \
printf("next is unexpected value (src: %s, actual: %u, expected: %u)\n", \
(src), next, (expected_next)); \
} else { \
EXPECT_EQ_VALUE(ret, (expected_value)); \
} \
})
void TestExecutor::testUtf32At() {
printf("testUtf32At()\n");
TEST_GET_UTF32AT("a", 0, 1, 97);
// Japanese hiragana "a"
TEST_GET_UTF32AT("\xE3\x81\x82", 0, 3, 0x3042);
// Japanese fullwidth katakana "a" with ascii a
TEST_GET_UTF32AT("a\xE3\x82\xA2", 1, 4, 0x30A2);
// 2 PUA
TEST_GET_UTF32AT("\xF3\xBE\x80\x80\xF3\xBE\x80\x88", 0, 4, 0xFE000);
TEST_GET_UTF32AT("\xF3\xBE\x80\x80\xF3\xBE\x80\x88", 4, 8, 0xFE008);
}
#define EXPECT_EQ_CODEPOINT_UTF8(codepoint, expected) \
({ \
char32_t codepoints[1] = {codepoint}; \
status_t ret = string8.setTo(codepoints, 1); \
if (ret != NO_ERROR) { \
printf("GetUtf8FromCodePoint() returned false at 0x%04X\n", codepoint); \
m_success = false; \
} else { \
const char* string = string8.string(); \
if (strcmp(string, expected) != 0) { \
printf("Failed at codepoint 0x%04X\n", codepoint); \
for (const char *ch = string; *ch != '\0'; ++ch) { \
printf("0x%X ", *ch); \
} \
printf("!= "); \
for (const char *ch = expected; *ch != '\0'; ++ch) { \
printf("0x%X ", *ch); \
} \
printf("\n"); \
m_success = false; \
} \
} \
})
void TestExecutor::testGetUtf8FromUtf32() {
printf("testGetUtf8FromUtf32()\n");
String8 string8;
EXPECT_EQ_CODEPOINT_UTF8('a', "\x61");
// Armenian capital letter AYB (2 bytes in UTF8)
EXPECT_EQ_CODEPOINT_UTF8(0x0530, "\xD4\xB0");
// Japanese 'a' (3 bytes in UTF8)
EXPECT_EQ_CODEPOINT_UTF8(0x3042, "\xE3\x81\x82");
// Kanji
EXPECT_EQ_CODEPOINT_UTF8(0x65E5, "\xE6\x97\xA5");
// PUA (4 byets in UTF8)
EXPECT_EQ_CODEPOINT_UTF8(0xFE016, "\xF3\xBE\x80\x96");
EXPECT_EQ_CODEPOINT_UTF8(0xFE972, "\xF3\xBE\xA5\xB2");
}
#define EXPECT_EQ_UTF8_UTF8(src, expected) \
({ \
if (!GetNormalizedString(src, &dst, &len)) { \
printf("GetNormalizedSortableString() returned false.\n"); \
m_success = false; \
} else { \
if (strcmp(dst, expected) != 0) { \
for (const char *ch = dst; *ch != '\0'; ++ch) { \
printf("0x%X ", *ch); \
} \
printf("!= "); \
for (const char *ch = expected; *ch != '\0'; ++ch) { \
printf("0x%X ", *ch); \
} \
printf("\n"); \
m_success = false; \
} \
free(dst); \
} \
})
void TestExecutor::testGetNormalizedString() {
printf("testGetNormalizedString()\n");
char *dst;
size_t len;
// halfwidth alphabets/symbols -> keep it as is.
EXPECT_EQ_UTF8_UTF8("ABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%^&'()",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%^&'()");
EXPECT_EQ_UTF8_UTF8("abcdefghijklmnopqrstuvwxyz[]{}\\@/",
"abcdefghijklmnopqrstuvwxyz[]{}\\@/");
// halfwidth/fullwidth-katakana -> hiragana
EXPECT_EQ_UTF8_UTF8(
"\xE3\x81\x82\xE3\x82\xA4\xE3\x81\x86\xEF\xBD\xB4\xE3\x82\xAA",
"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A");
// whitespace -> keep it as is.
EXPECT_EQ_UTF8_UTF8(" \t", " \t");
}
void TestExecutor::testLongString() {
printf("testLongString()\n");
char * dst;
size_t len;
EXPECT_EQ_UTF8_UTF8("Qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtttttttttttttttttttttttttttttttttttttttttttttttttgggggggggggggggggggggggggggggggggggggggbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"Qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqtttttttttttttttttttttttttttttttttttttttttttttttttggggggggggggggggggggggggggggggggggg");
}
int main() {
TestExecutor executor;
if(executor.DoAllTests()) {
return 0;
} else {
return 1;
}
}