Line data Source code
1 : // Copyright 2017 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifdef V8_INTL_SUPPORT
6 :
7 : #include "src/lookup.h"
8 : #include "src/objects-inl.h"
9 : #include "src/objects/intl-objects.h"
10 : #include "src/objects/js-break-iterator.h"
11 : #include "src/objects/js-collator.h"
12 : #include "src/objects/js-date-time-format.h"
13 : #include "src/objects/js-list-format.h"
14 : #include "src/objects/js-number-format.h"
15 : #include "src/objects/js-plural-rules.h"
16 : #include "src/objects/js-relative-time-format.h"
17 : #include "src/objects/js-segmenter.h"
18 : #include "test/cctest/cctest.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 :
23 : // This operator overloading enables CHECK_EQ to be used with
24 : // std::vector<NumberFormatSpan>
25 0 : bool operator==(const NumberFormatSpan& lhs, const NumberFormatSpan& rhs) {
26 140 : return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
27 : }
28 : template <typename _CharT, typename _Traits>
29 : std::basic_ostream<_CharT, _Traits>& operator<<(
30 : std::basic_ostream<_CharT, _Traits>& self, const NumberFormatSpan& part) {
31 : return self << "{" << part.field_id << "," << part.begin_pos << ","
32 : << part.end_pos << "}";
33 : }
34 :
35 30 : void test_flatten_regions_to_parts(
36 : const std::vector<NumberFormatSpan>& regions,
37 : const std::vector<NumberFormatSpan>& expected_parts) {
38 30 : std::vector<NumberFormatSpan> mutable_regions = regions;
39 30 : std::vector<NumberFormatSpan> parts = FlattenRegionsToParts(&mutable_regions);
40 30 : CHECK_EQ(expected_parts, parts);
41 30 : }
42 :
43 26644 : TEST(FlattenRegionsToParts) {
44 10 : test_flatten_regions_to_parts(
45 : std::vector<NumberFormatSpan>{
46 : NumberFormatSpan(-1, 0, 10), NumberFormatSpan(1, 2, 8),
47 : NumberFormatSpan(2, 2, 4), NumberFormatSpan(3, 6, 8),
48 : },
49 : std::vector<NumberFormatSpan>{
50 : NumberFormatSpan(-1, 0, 2), NumberFormatSpan(2, 2, 4),
51 : NumberFormatSpan(1, 4, 6), NumberFormatSpan(3, 6, 8),
52 : NumberFormatSpan(-1, 8, 10),
53 5 : });
54 10 : test_flatten_regions_to_parts(
55 : std::vector<NumberFormatSpan>{
56 : NumberFormatSpan(0, 0, 1),
57 : },
58 : std::vector<NumberFormatSpan>{
59 : NumberFormatSpan(0, 0, 1),
60 5 : });
61 10 : test_flatten_regions_to_parts(
62 : std::vector<NumberFormatSpan>{
63 : NumberFormatSpan(-1, 0, 1), NumberFormatSpan(0, 0, 1),
64 : },
65 : std::vector<NumberFormatSpan>{
66 : NumberFormatSpan(0, 0, 1),
67 5 : });
68 10 : test_flatten_regions_to_parts(
69 : std::vector<NumberFormatSpan>{
70 : NumberFormatSpan(0, 0, 1), NumberFormatSpan(-1, 0, 1),
71 : },
72 : std::vector<NumberFormatSpan>{
73 : NumberFormatSpan(0, 0, 1),
74 5 : });
75 10 : test_flatten_regions_to_parts(
76 : std::vector<NumberFormatSpan>{
77 : NumberFormatSpan(-1, 0, 10), NumberFormatSpan(1, 0, 1),
78 : NumberFormatSpan(2, 0, 2), NumberFormatSpan(3, 0, 3),
79 : NumberFormatSpan(4, 0, 4), NumberFormatSpan(5, 0, 5),
80 : NumberFormatSpan(15, 5, 10), NumberFormatSpan(16, 6, 10),
81 : NumberFormatSpan(17, 7, 10), NumberFormatSpan(18, 8, 10),
82 : NumberFormatSpan(19, 9, 10),
83 : },
84 : std::vector<NumberFormatSpan>{
85 : NumberFormatSpan(1, 0, 1), NumberFormatSpan(2, 1, 2),
86 : NumberFormatSpan(3, 2, 3), NumberFormatSpan(4, 3, 4),
87 : NumberFormatSpan(5, 4, 5), NumberFormatSpan(15, 5, 6),
88 : NumberFormatSpan(16, 6, 7), NumberFormatSpan(17, 7, 8),
89 : NumberFormatSpan(18, 8, 9), NumberFormatSpan(19, 9, 10),
90 5 : });
91 :
92 : // : 4
93 : // : 22 33 3
94 : // : 11111 22
95 : // input regions: 0000000 111
96 : // : ------------
97 : // output parts: 0221340--231
98 10 : test_flatten_regions_to_parts(
99 : std::vector<NumberFormatSpan>{
100 : NumberFormatSpan(-1, 0, 12), NumberFormatSpan(0, 0, 7),
101 : NumberFormatSpan(1, 9, 12), NumberFormatSpan(1, 1, 6),
102 : NumberFormatSpan(2, 9, 11), NumberFormatSpan(2, 1, 3),
103 : NumberFormatSpan(3, 10, 11), NumberFormatSpan(3, 4, 6),
104 : NumberFormatSpan(4, 5, 6),
105 : },
106 : std::vector<NumberFormatSpan>{
107 : NumberFormatSpan(0, 0, 1), NumberFormatSpan(2, 1, 3),
108 : NumberFormatSpan(1, 3, 4), NumberFormatSpan(3, 4, 5),
109 : NumberFormatSpan(4, 5, 6), NumberFormatSpan(0, 6, 7),
110 : NumberFormatSpan(-1, 7, 9), NumberFormatSpan(2, 9, 10),
111 : NumberFormatSpan(3, 10, 11), NumberFormatSpan(1, 11, 12),
112 5 : });
113 5 : }
114 :
115 26644 : TEST(GetStringOption) {
116 5 : LocalContext env;
117 : Isolate* isolate = CcTest::i_isolate();
118 5 : v8::Isolate* v8_isolate = env->GetIsolate();
119 10 : v8::HandleScope handle_scope(v8_isolate);
120 :
121 5 : Handle<JSObject> options = isolate->factory()->NewJSObjectWithNullProto();
122 : {
123 : // No value found
124 : std::unique_ptr<char[]> result = nullptr;
125 : Maybe<bool> found =
126 : Intl::GetStringOption(isolate, options, "foo",
127 10 : std::vector<const char*>{}, "service", &result);
128 5 : CHECK(!found.FromJust());
129 5 : CHECK_NULL(result);
130 : }
131 :
132 5 : Handle<String> key = isolate->factory()->NewStringFromAsciiChecked("foo");
133 5 : v8::internal::LookupIterator it(isolate, options, key);
134 10 : CHECK(Object::SetProperty(&it, Handle<Smi>(Smi::FromInt(42), isolate),
135 : StoreOrigin::kMaybeKeyed,
136 : Just(ShouldThrow::kThrowOnError))
137 : .FromJust());
138 :
139 : {
140 : // Value found
141 : std::unique_ptr<char[]> result = nullptr;
142 : Maybe<bool> found =
143 : Intl::GetStringOption(isolate, options, "foo",
144 10 : std::vector<const char*>{}, "service", &result);
145 5 : CHECK(found.FromJust());
146 5 : CHECK_NOT_NULL(result);
147 5 : CHECK_EQ(0, strcmp("42", result.get()));
148 : }
149 :
150 : {
151 : // No expected value in values array
152 : std::unique_ptr<char[]> result = nullptr;
153 : Maybe<bool> found = Intl::GetStringOption(isolate, options, "foo",
154 : std::vector<const char*>{"bar"},
155 10 : "service", &result);
156 5 : CHECK(isolate->has_pending_exception());
157 5 : CHECK(found.IsNothing());
158 5 : CHECK_NULL(result);
159 : isolate->clear_pending_exception();
160 : }
161 :
162 : {
163 : // Expected value in values array
164 : std::unique_ptr<char[]> result = nullptr;
165 : Maybe<bool> found = Intl::GetStringOption(isolate, options, "foo",
166 : std::vector<const char*>{"42"},
167 10 : "service", &result);
168 5 : CHECK(found.FromJust());
169 5 : CHECK_NOT_NULL(result);
170 5 : CHECK_EQ(0, strcmp("42", result.get()));
171 : }
172 5 : }
173 :
174 26644 : TEST(GetBoolOption) {
175 5 : LocalContext env;
176 : Isolate* isolate = CcTest::i_isolate();
177 5 : v8::Isolate* v8_isolate = env->GetIsolate();
178 10 : v8::HandleScope handle_scope(v8_isolate);
179 :
180 5 : Handle<JSObject> options = isolate->factory()->NewJSObjectWithNullProto();
181 : {
182 5 : bool result = false;
183 : Maybe<bool> found =
184 5 : Intl::GetBoolOption(isolate, options, "foo", "service", &result);
185 5 : CHECK(!found.FromJust());
186 5 : CHECK(!result);
187 : }
188 :
189 5 : Handle<String> key = isolate->factory()->NewStringFromAsciiChecked("foo");
190 : {
191 5 : v8::internal::LookupIterator it(isolate, options, key);
192 : Handle<Object> false_value =
193 : handle(i::ReadOnlyRoots(isolate).false_value(), isolate);
194 5 : Object::SetProperty(isolate, options, key, false_value,
195 : StoreOrigin::kMaybeKeyed,
196 5 : Just(ShouldThrow::kThrowOnError))
197 : .Assert();
198 5 : bool result = false;
199 : Maybe<bool> found =
200 5 : Intl::GetBoolOption(isolate, options, "foo", "service", &result);
201 5 : CHECK(found.FromJust());
202 5 : CHECK(!result);
203 : }
204 :
205 : {
206 5 : v8::internal::LookupIterator it(isolate, options, key);
207 : Handle<Object> true_value =
208 : handle(i::ReadOnlyRoots(isolate).true_value(), isolate);
209 5 : Object::SetProperty(isolate, options, key, true_value,
210 : StoreOrigin::kMaybeKeyed,
211 5 : Just(ShouldThrow::kThrowOnError))
212 : .Assert();
213 5 : bool result = false;
214 : Maybe<bool> found =
215 5 : Intl::GetBoolOption(isolate, options, "foo", "service", &result);
216 5 : CHECK(found.FromJust());
217 5 : CHECK(result);
218 : }
219 5 : }
220 :
221 26644 : TEST(GetAvailableLocales) {
222 : std::set<std::string> locales;
223 :
224 5 : locales = JSV8BreakIterator::GetAvailableLocales();
225 15 : CHECK(locales.count("en-US"));
226 15 : CHECK(!locales.count("abcdefg"));
227 :
228 5 : locales = JSCollator::GetAvailableLocales();
229 15 : CHECK(locales.count("en-US"));
230 :
231 5 : locales = JSDateTimeFormat::GetAvailableLocales();
232 15 : CHECK(locales.count("en-US"));
233 :
234 5 : locales = JSListFormat::GetAvailableLocales();
235 15 : CHECK(locales.count("en-US"));
236 :
237 5 : locales = JSNumberFormat::GetAvailableLocales();
238 15 : CHECK(locales.count("en-US"));
239 :
240 5 : locales = JSPluralRules::GetAvailableLocales();
241 15 : CHECK(locales.count("en-US"));
242 :
243 5 : locales = JSRelativeTimeFormat::GetAvailableLocales();
244 15 : CHECK(locales.count("en-US"));
245 :
246 5 : locales = JSSegmenter::GetAvailableLocales();
247 15 : CHECK(locales.count("en-US"));
248 15 : CHECK(!locales.count("abcdefg"));
249 5 : }
250 :
251 : } // namespace internal
252 79917 : } // namespace v8
253 :
254 : #endif // V8_INTL_SUPPORT
|