blob: c5523e45e62da05442a14812c2a8555b0dec5d21 [file] [log] [blame]
/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "config.h"
#import "TestNavigationDelegate.h"
#import "Utilities.h"
#import <unicode/ubrk.h>
#import <wtf/RetainPtr.h>
#import <wtf/Vector.h>
#import <wtf/text/WTFString.h>
NSString *generateJavaScriptForTest(NSString *testContent, NSString *localeString, NSString *lineBreakValue)
{
return [NSString stringWithFormat:@"runTest('%@', '%@', '%@')", testContent, localeString, lineBreakValue];
}
Vector<unsigned> breakingLocationsFromICU(const Vector<UInt16>& testString, const String& locale, const String lineBreakValue)
{
constexpr int bufferSize = 100;
char buffer[bufferSize];
memset(buffer, 0, bufferSize);
auto utf8Locale = locale.utf8();
ASSERT(utf8Locale.length() < bufferSize);
memcpy(buffer, utf8Locale.data(), utf8Locale.length());
CString icuValue;
if (lineBreakValue != "auto"_s)
icuValue = lineBreakValue.utf8();
UErrorCode status = U_ZERO_ERROR;
uloc_setKeywordValue("lb", icuValue.data(), buffer, bufferSize, &status);
ASSERT(U_SUCCESS(status));
UBreakIterator* iterator = ubrk_open(UBRK_LINE, buffer, reinterpret_cast<const UChar*>(testString.data()), testString.size(), &status);
ASSERT(U_SUCCESS(status));
ASSERT(iterator);
Vector<unsigned> result;
int32_t position = 0;
for (; position != UBRK_DONE; position = ubrk_next(iterator)) {
if (position)
result.append(position);
}
ubrk_close(iterator);
return result;
}
static void testAFewStrings(Vector<Vector<UInt16>> testStrings)
{
Vector<String> locales = { "en", "ja", "ko", "zh" };
Vector<String> lineBreakValues = { "auto", "loose", "normal", "strict" };
RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
[webView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"LineBreaking" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]];
[webView _test_waitForDidFinishNavigation];
for (auto& testCodePoints : testStrings) {
NSString *testString = [NSString stringWithCharacters:testCodePoints.data() length:testCodePoints.size()];
for (auto& locale : locales) {
for (auto& lineBreakValue : lineBreakValues) {
__block bool didEvaluateJavaScript = false;
__block Vector<unsigned> webkitLocations;
[webView evaluateJavaScript:generateJavaScriptForTest(testString, locale, lineBreakValue) completionHandler:^(id value, NSError *error) {
for (NSNumber *v in (NSArray *)value)
webkitLocations.append(floor([v floatValue] + 0.5));
didEvaluateJavaScript = true;
}];
TestWebKitAPI::Util::run(&didEvaluateJavaScript);
const auto& icuLocations = breakingLocationsFromICU(testCodePoints, locale, lineBreakValue);
EXPECT_EQ(icuLocations.size(), webkitLocations.size());
if (icuLocations.size() != webkitLocations.size())
break;
for (size_t i = 0; i < icuLocations.size(); ++i)
EXPECT_EQ(icuLocations[i], webkitLocations[i]);
}
}
}
}
// Split up the tests because they take too long otherwise and people start thinking their computer is hung.
TEST(WebKit, LineBreaking1)
{
Vector<Vector<UInt16>> testStrings = {
{0x0024, 0x31, 0x32, 0x33},
{0x00a3, 0x31, 0x32, 0x33},
{0x00a5, 0x31, 0x32, 0x33},
{0x20ac, 0x31, 0x32, 0x33},
{0x2116, 0x31, 0x32, 0x33},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking2)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x2025, 0x2025},
{0x4e00, 0x2025, 0x2026},
{0x4e00, 0x2026, 0x2025},
{0x4e00, 0x2026, 0x2026},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x0021},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking3)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x0025},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x003a},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x003b},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x003f},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x00a2},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking4)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x00b0},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x2010},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x2013},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x2030},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x2032},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking5)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x2033},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x203c},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x2047},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x2048},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x2049},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking6)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x2103},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3005},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x301c},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x303b},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3041},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking7)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3043},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3045},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3047},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3049},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3063},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking8)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3083},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3085},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3087},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x308e},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3095},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking9)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x3096},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x309d},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x309e},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30a0},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30a1},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking10)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30a3},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30a5},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30a7},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30a9},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30c3},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking11)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30e3},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30e5},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30e7},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30ee},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30f5},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking12)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30f6},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30fb},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30fc},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30fd},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x30fe},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking13)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31f0},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31f1},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31f2},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31f3},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31f4},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking14)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31f5},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31f6},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31f7},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31f8},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31f9},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking15)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31fa},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31fb},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31fc},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31fd},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31fe},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking16)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0x31ff},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff01},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff05},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff1a},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff1b},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking17)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff1f},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff65},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff67},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff68},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff69},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking18)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff6a},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff6b},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff6c},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff6d},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff6e},
};
testAFewStrings(testStrings);
}
TEST(WebKit, LineBreaking19)
{
Vector<Vector<UInt16>> testStrings = {
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff6f},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xff70},
{0x4e00, 0x4e8c, 0x4e09, 0x56db, 0xffe0},
{0xff04, 0x31, 0x32, 0x33},
{0xffe1, 0x31, 0x32, 0x33},
{0xffe5, 0x31, 0x32, 0x33}
};
testAFewStrings(testStrings);
}