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/base/number_helper.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/napi/jsnapi_helper.h"
20 #include "ecmascript/tests/test_helper.h"
21
22 using namespace panda::ecmascript;
23 using namespace panda::ecmascript::base;
24
25 namespace panda::test {
26 class JSRelativeTimeFormatTest : public testing::Test {
27 public:
SetUpTestCase()28 static void SetUpTestCase()
29 {
30 GTEST_LOG_(INFO) << "SetUpTestCase";
31 }
32
TearDownTestCase()33 static void TearDownTestCase()
34 {
35 GTEST_LOG_(INFO) << "TearDownCase";
36 }
37
SetUp()38 void SetUp() override
39 {
40 JSRuntimeOptions options;
41 #if PANDA_TARGET_LINUX
42 // for consistency requirement, use ohos_icu4j/data/icudt67l.dat as icu-data-path
43 options.SetIcuDataPath(ICU_PATH);
44 #endif
45 options.SetEnableForceGC(true);
46 instance = JSNApi::CreateEcmaVM(options);
47 instance->SetEnableForceGC(true);
48 ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
49 thread = instance->GetJSThread();
50 scope = new EcmaHandleScope(thread);
51 }
52
TearDown()53 void TearDown() override
54 {
55 TestHelper::DestroyEcmaVMWithScope(instance, scope);
56 }
57
58 EcmaVM *instance {nullptr};
59 ecmascript::EcmaHandleScope *scope {nullptr};
60 JSThread *thread {nullptr};
61 };
62
HWTEST_F_L0(JSRelativeTimeFormatTest,InitializeRelativeTimeFormat)63 HWTEST_F_L0(JSRelativeTimeFormatTest, InitializeRelativeTimeFormat)
64 {
65 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
66 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
67
68 JSHandle<JSTaggedValue> ctor = env->GetRelativeTimeFormatFunction();
69 JSHandle<JSRelativeTimeFormat> relativeTimeFormat =
70 JSHandle<JSRelativeTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
71 EXPECT_TRUE(*relativeTimeFormat != nullptr);
72
73 JSHandle<JSTaggedValue> locales(factory->NewFromASCII("en"));
74 JSHandle<JSTaggedValue> undefinedOptions(thread, JSTaggedValue::Undefined());
75 JSRelativeTimeFormat::InitializeRelativeTimeFormat(thread, relativeTimeFormat, locales, undefinedOptions);
76 // Initialize attribute comparison
77 JSHandle<EcmaString> numberingSystemStr(thread, relativeTimeFormat->GetNumberingSystem().GetTaggedObject());
78 EXPECT_STREQ("latn", EcmaStringAccessor(numberingSystemStr).ToCString().c_str());
79 JSHandle<EcmaString> localeStr(thread, relativeTimeFormat->GetLocale().GetTaggedObject());
80 EXPECT_STREQ("en", EcmaStringAccessor(localeStr).ToCString().c_str());
81 EXPECT_EQ(NumericOption::ALWAYS, relativeTimeFormat->GetNumeric());
82 EXPECT_EQ(RelativeStyleOption::LONG, relativeTimeFormat->GetStyle());
83 }
84
HWTEST_F_L0(JSRelativeTimeFormatTest,GetIcuRTFFormatter)85 HWTEST_F_L0(JSRelativeTimeFormatTest, GetIcuRTFFormatter)
86 {
87 double value = base::NAN_VALUE;
88 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
89 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
90
91 JSHandle<JSTaggedValue> ctor = env->GetRelativeTimeFormatFunction();
92 JSHandle<JSRelativeTimeFormat> relativeTimeFormat =
93 JSHandle<JSRelativeTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
94 // Create Icu RelativeDateTimeFormatter
95 icu::Locale icuLocale("en", "US");
96 UErrorCode status = U_ZERO_ERROR;
97 icu::NumberFormat *icuNumberFormat = icu::NumberFormat::createInstance(icuLocale, UNUM_DECIMAL, status);
98 icu::RelativeDateTimeFormatter rtfFormatter(icuLocale, icuNumberFormat, UDAT_STYLE_LONG,
99 UDISPCTX_CAPITALIZATION_NONE, status);
100 icu::UnicodeString result1 = rtfFormatter.formatNumericToValue(value, UDAT_REL_UNIT_YEAR, status).toString(status);
101 JSHandle<EcmaString> stringValue1 = JSLocale::IcuToString(thread, result1);
102 // Set Icu RelativeDateTimeFormatter to Icu Field
103 factory->NewJSIntlIcuData(relativeTimeFormat, rtfFormatter, JSRelativeTimeFormat::FreeIcuRTFFormatter);
104 // Get Icu Field
105 icu::RelativeDateTimeFormatter *resultRelativeDateTimeFormatter = relativeTimeFormat->GetIcuRTFFormatter();
106 icu::UnicodeString result2 =
107 resultRelativeDateTimeFormatter->formatNumericToValue(value, UDAT_REL_UNIT_YEAR, status).toString(status);
108 JSHandle<EcmaString> stringValue2 = JSLocale::IcuToString(thread, result2);
109 EXPECT_EQ(EcmaStringAccessor::StringsAreEqual(*stringValue1, *stringValue2), true);
110 }
111
HWTEST_F_L0(JSRelativeTimeFormatTest,UnwrapRelativeTimeFormat)112 HWTEST_F_L0(JSRelativeTimeFormatTest, UnwrapRelativeTimeFormat)
113 {
114 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
115 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
116 EcmaVM *vm = thread->GetEcmaVM();
117
118 JSHandle<JSTaggedValue> relativeTimeFormatFunc = env->GetRelativeTimeFormatFunction();
119 JSHandle<JSTaggedValue> relativeTimeFormat(
120 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(relativeTimeFormatFunc), relativeTimeFormatFunc));
121
122 Local<FunctionRef> relativeTimeFormatLocal = JSNApiHelper::ToLocal<FunctionRef>(relativeTimeFormatFunc);
123 JSHandle<JSTaggedValue> disPlayNamesFunc = env->GetDisplayNamesFunction();
124 Local<FunctionRef> disPlayNamesLocal = JSNApiHelper::ToLocal<FunctionRef>(disPlayNamesFunc);
125 // displaynames Inherit relativeTimeFormat
126 disPlayNamesLocal->Inherit(vm, relativeTimeFormatLocal);
127 JSHandle<JSTaggedValue> disPlayNamesHandle = JSNApiHelper::ToJSHandle(disPlayNamesLocal);
128 JSHandle<JSTaggedValue> disPlayNamesObj(
129 factory->NewJSObjectByConstructor(JSHandle<JSFunction>::Cast(disPlayNamesHandle), disPlayNamesHandle));
130 // object has no Instance
131 JSHandle<JSTaggedValue> unwrapNumberFormat1 =
132 JSRelativeTimeFormat::UnwrapRelativeTimeFormat(thread, relativeTimeFormat);
133 EXPECT_TRUE(JSTaggedValue::SameValue(relativeTimeFormat, unwrapNumberFormat1));
134 // object has Instance
135 JSHandle<JSTaggedValue> unwrapNumberFormat2 =
136 JSRelativeTimeFormat::UnwrapRelativeTimeFormat(thread, disPlayNamesObj);
137 EXPECT_TRUE(unwrapNumberFormat2->IsUndefined());
138 }
139 } // namespace panda::test