1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/js_relative_time_format.h"
17 #include "ecmascript/intl/locale_helper.h"
18 #include "ecmascript/base/number_helper.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/napi/jsnapi_helper.h"
21 #include "ecmascript/tests/test_helper.h"
22
23 using namespace panda::ecmascript;
24 using namespace panda::ecmascript::base;
25
26 namespace panda::test {
27 class JSRelativeTimeFormatTest : public testing::Test {
28 public:
SetUpTestCase()29 static void SetUpTestCase()
30 {
31 GTEST_LOG_(INFO) << "SetUpTestCase";
32 }
33
TearDownTestCase()34 static void TearDownTestCase()
35 {
36 GTEST_LOG_(INFO) << "TearDownCase";
37 }
38
SetUp()39 void SetUp() override
40 {
41 JSRuntimeOptions options;
42 #if PANDA_TARGET_LINUX
43 // for consistency requirement, use ohos_icu4j/data/icudt67l.dat as icu-data-path
44 options.SetIcuDataPath(ICU_PATH);
45 #endif
46 options.SetEnableForceGC(true);
47 instance = JSNApi::CreateEcmaVM(options);
48 instance->SetEnableForceGC(true);
49 ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
50 thread = instance->GetJSThread();
51 scope = new EcmaHandleScope(thread);
52 }
53
TearDown()54 void TearDown() override
55 {
56 TestHelper::DestroyEcmaVMWithScope(instance, scope);
57 }
58
59 EcmaVM *instance {nullptr};
60 ecmascript::EcmaHandleScope *scope {nullptr};
61 JSThread *thread {nullptr};
62 };
63
HWTEST_F_L0(JSRelativeTimeFormatTest,InitializeRelativeTimeFormat)64 HWTEST_F_L0(JSRelativeTimeFormatTest, InitializeRelativeTimeFormat)
65 {
66 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
67 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
68
69 JSHandle<JSTaggedValue> ctor = env->GetRelativeTimeFormatFunction();
70 JSHandle<JSRelativeTimeFormat> relativeTimeFormat =
71 JSHandle<JSRelativeTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
72 EXPECT_TRUE(*relativeTimeFormat != nullptr);
73
74 JSHandle<JSTaggedValue> locales(factory->NewFromASCII("en"));
75 JSHandle<JSTaggedValue> undefinedOptions(thread, JSTaggedValue::Undefined());
76 JSRelativeTimeFormat::InitializeRelativeTimeFormat(thread, relativeTimeFormat, locales, undefinedOptions);
77 // Initialize attribute comparison
78 JSHandle<EcmaString> numberingSystemStr(thread, relativeTimeFormat->GetNumberingSystem().GetTaggedObject());
79 EXPECT_STREQ("latn", EcmaStringAccessor(numberingSystemStr).ToCString().c_str());
80 JSHandle<EcmaString> localeStr(thread, relativeTimeFormat->GetLocale().GetTaggedObject());
81 EXPECT_STREQ("en", EcmaStringAccessor(localeStr).ToCString().c_str());
82 EXPECT_EQ(NumericOption::ALWAYS, relativeTimeFormat->GetNumeric());
83 EXPECT_EQ(RelativeStyleOption::LONG, relativeTimeFormat->GetStyle());
84 }
85
HWTEST_F_L0(JSRelativeTimeFormatTest,GetIcuRTFFormatter)86 HWTEST_F_L0(JSRelativeTimeFormatTest, GetIcuRTFFormatter)
87 {
88 double value = base::NAN_VALUE;
89 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
90 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
91
92 JSHandle<JSTaggedValue> ctor = env->GetRelativeTimeFormatFunction();
93 JSHandle<JSRelativeTimeFormat> relativeTimeFormat =
94 JSHandle<JSRelativeTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
95 // Create Icu RelativeDateTimeFormatter
96 icu::Locale icuLocale("en", "US");
97 UErrorCode status = U_ZERO_ERROR;
98 icu::NumberFormat *icuNumberFormat = icu::NumberFormat::createInstance(icuLocale, UNUM_DECIMAL, status);
99 icu::RelativeDateTimeFormatter rtfFormatter(icuLocale, icuNumberFormat, UDAT_STYLE_LONG,
100 UDISPCTX_CAPITALIZATION_NONE, status);
101 icu::UnicodeString result1 = rtfFormatter.formatNumericToValue(value, UDAT_REL_UNIT_YEAR, status).toString(status);
102 JSHandle<EcmaString> stringValue1 = intl::LocaleHelper::UStringToString(thread, result1);
103 // Set Icu RelativeDateTimeFormatter to Icu Field
104 factory->NewJSIntlIcuData(relativeTimeFormat, rtfFormatter, JSRelativeTimeFormat::FreeIcuRTFFormatter);
105 // Get Icu Field
106 icu::RelativeDateTimeFormatter *resultRelativeDateTimeFormatter = relativeTimeFormat->GetIcuRTFFormatter();
107 icu::UnicodeString result2 =
108 resultRelativeDateTimeFormatter->formatNumericToValue(value, UDAT_REL_UNIT_YEAR, status).toString(status);
109 JSHandle<EcmaString> stringValue2 = intl::LocaleHelper::UStringToString(thread, result2);
110 EXPECT_EQ(EcmaStringAccessor::StringsAreEqual(*stringValue1, *stringValue2), true);
111 }
112
HWTEST_F_L0(JSRelativeTimeFormatTest,UnwrapRelativeTimeFormat)113 HWTEST_F_L0(JSRelativeTimeFormatTest, UnwrapRelativeTimeFormat)
114 {
115 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
116 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
117 EcmaVM *vm = thread->GetEcmaVM();
118
119 JSHandle<JSTaggedValue> relativeTimeFormatFunc = env->GetRelativeTimeFormatFunction();
120 JSHandle<JSTaggedValue> relativeTimeFormat(
121 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(relativeTimeFormatFunc), relativeTimeFormatFunc));
122
123 Local<FunctionRef> relativeTimeFormatLocal = JSNApiHelper::ToLocal<FunctionRef>(relativeTimeFormatFunc);
124 JSHandle<JSTaggedValue> disPlayNamesFunc = env->GetDisplayNamesFunction();
125 Local<FunctionRef> disPlayNamesLocal = JSNApiHelper::ToLocal<FunctionRef>(disPlayNamesFunc);
126 // displaynames Inherit relativeTimeFormat
127 disPlayNamesLocal->Inherit(vm, relativeTimeFormatLocal);
128 JSHandle<JSTaggedValue> disPlayNamesHandle = JSNApiHelper::ToJSHandle(disPlayNamesLocal);
129 JSHandle<JSTaggedValue> disPlayNamesObj(
130 factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(disPlayNamesHandle), disPlayNamesHandle));
131 // object has no Instance
132 JSHandle<JSTaggedValue> unwrapNumberFormat1 =
133 JSRelativeTimeFormat::UnwrapRelativeTimeFormat(thread, relativeTimeFormat);
134 EXPECT_TRUE(JSTaggedValue::SameValue(relativeTimeFormat, unwrapNumberFormat1));
135 // object has Instance
136 JSHandle<JSTaggedValue> unwrapNumberFormat2 =
137 JSRelativeTimeFormat::UnwrapRelativeTimeFormat(thread, disPlayNamesObj);
138 EXPECT_TRUE(unwrapNumberFormat2->IsUndefined());
139 }
140 } // namespace panda::test