/* * Copyright (c) 2022 Huawei Device Co., Ltd. * 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 "ecmascript/js_regexp_iterator.h" #include "ecmascript/builtins/builtins_regexp.h" #include "ecmascript/global_env.h" #include "ecmascript/js_regexp.h" #include "ecmascript/tests/test_helper.h" using namespace panda::ecmascript; using namespace panda::ecmascript::builtins; namespace panda::test { using BuiltinsRegExp = builtins::BuiltinsRegExp; class JSRegexpIteratorTest : public testing::Test { public: static void SetUpTestCase() { GTEST_LOG_(INFO) << "SetUpTestCase"; } static void TearDownTestCase() { GTEST_LOG_(INFO) << "TearDownCase"; } void SetUp() override { TestHelper::CreateEcmaVMWithScope(instance, thread, scope); } void TearDown() override { TestHelper::DestroyEcmaVMWithScope(instance, scope); } EcmaVM *instance {nullptr}; ecmascript::EcmaHandleScope *scope {nullptr}; JSThread *thread {nullptr}; }; static JSTaggedValue CreateJSRegexpByPatternAndFlags(JSThread *thread, const JSHandle &pattern, const JSHandle &flags) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle regexp(env->GetRegExpFunction()); JSHandle globalObject(thread, env->GetGlobalObject()); // 8 : test case auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*regexp), 8); ecmaRuntimeCallInfo->SetFunction(regexp.GetTaggedValue()); ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(0, pattern.GetTaggedValue()); ecmaRuntimeCallInfo->SetCallArg(1, flags.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo); // call RegExpConstructor method JSTaggedValue result = BuiltinsRegExp::RegExpConstructor(ecmaRuntimeCallInfo); TestHelper::TearDownFrame(thread, prev); return result; } HWTEST_F_L0(JSRegexpIteratorTest, CreateRegExpStringIterator) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle pattern = factory->NewFromASCII("\\w+"); JSHandle flags = factory->NewFromASCII("gim"); JSHandle matchHandle(thread, CreateJSRegexpByPatternAndFlags(thread, pattern, flags)); JSHandle inputStr = factory->NewFromASCII("g"); JSHandle regExpIterator = JSRegExpIterator::CreateRegExpStringIterator(thread, matchHandle, inputStr, true, false); EXPECT_TRUE(regExpIterator->IsJSRegExpIterator()); regExpIterator = JSRegExpIterator::CreateRegExpStringIterator(thread, matchHandle, inputStr, false, false); EXPECT_TRUE(regExpIterator->IsJSRegExpIterator()); } HWTEST_F_L0(JSRegexpIteratorTest, Next) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle pattern = factory->NewFromASCII("-[0-9]+"); JSHandle flags = factory->NewFromASCII("g"); JSHandle inputStr = factory->NewFromASCII("2016-01-02|2019-03-04"); JSHandle zero(factory->NewFromASCII("0")); JSHandle barZero(factory->NewFromASCII("-0")); JSTaggedValue jsRegExp = CreateJSRegexpByPatternAndFlags(thread, pattern, flags); JSHandle ObjValue(thread, reinterpret_cast(jsRegExp.GetRawData())); // create regExp iterator auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo1->SetThis(ObjValue.GetTaggedValue()); ecmaRuntimeCallInfo1->SetCallArg(0, inputStr.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); JSTaggedValue iteratorValue = BuiltinsRegExp::MatchAll(ecmaRuntimeCallInfo1); TestHelper::TearDownFrame(thread, prev); JSHandle regExpIterator(thread, reinterpret_cast(iteratorValue.GetRawData())); uint32_t matchLength = 4; // 4 : 4 Number of matches // traversal regExp iterator for (uint32_t i = 0; i <= matchLength; i++) { auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined()); ecmaRuntimeCallInfo2->SetThis(regExpIterator.GetTaggedValue()); prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2); JSTaggedValue result = JSRegExpIterator::Next(ecmaRuntimeCallInfo2); TestHelper::TearDownFrame(thread, prev); JSHandle matchObj(thread, result); if (i <= matchLength - 1) { JSHandle resultValue(thread, JSTaggedValue(i+1)); JSHandle compareVal = factory->ConcatFromString(JSHandle(barZero), JSTaggedValue::ToString(thread, resultValue)); JSHandle matchResult = JSIterator::IteratorValue(thread, matchObj); JSHandle zeroHandle(JSObject::GetProperty(thread, matchResult, zero).GetValue()); JSHandle outputZero = JSTaggedValue::ToString(thread, zeroHandle); EXPECT_EQ(EcmaStringAccessor::Compare(*outputZero, *compareVal), 0); EXPECT_FALSE(regExpIterator->GetDone()); } else { EXPECT_TRUE(regExpIterator->GetDone()); EXPECT_EQ(JSIterator::IteratorValue(thread, matchObj).GetTaggedValue(), JSTaggedValue::Undefined()); } } } } // namespace panda::test