diff --git a/base/test/benchmarktest/BUILD.gn b/base/test/benchmarktest/BUILD.gn index bc4afa2ea53083ebbb117de4870fb15bc1a74cc0..e2ba226ccca81583eda1bd9c79dc75fcc0017959 100644 --- a/base/test/benchmarktest/BUILD.gn +++ b/base/test/benchmarktest/BUILD.gn @@ -19,12 +19,15 @@ group("benchmarktest") { "ashemem_benchmark_test:AshememTest", "datatime_benchmark_test:DatatimeTest", "directory_benchmark_test:DirectoryTest", + "event_benchmark_test:EventTest", + "file_benchmark_test:FileTest", "mapped_benchmark_test:MappedTest", "observer_benchmark_test:ObserverTest", "parcel_benchmark_test:ParcelTest", "refbase_benchmark_test:RefbaseTest", "rwlock_benchmark_test:RwlockTest", "safe_map_benchmark_test:SafeMapTest", + "safe_queue_benchmark_test:SafeQueueTest", "singleton_benchmark_test:SingletonTest", "sorted_vector_benchmark_test:SortedVectorTest", "string_benchmark_test:StringTest", diff --git a/base/test/benchmarktest/event_benchmark_test/BUILD.gn b/base/test/benchmarktest/event_benchmark_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9f9a61e254bdef219d9b030d0b7103fb06d57377 --- /dev/null +++ b/base/test/benchmarktest/event_benchmark_test/BUILD.gn @@ -0,0 +1,37 @@ +# Copyright (c) 2023 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. + +import("//build/test.gni") + +module_output_path = "commonlibrary_c_utils/event" + +ohos_benchmarktest("EventTest") { + module_out_path = module_output_path + + include_dirs = [ "../../../include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "event_benchmark_test.cpp" ] + + deps = [ "//third_party/benchmark:benchmark" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog_base", + ] +} diff --git a/base/test/benchmarktest/event_benchmark_test/event_benchmark_test.cpp b/base/test/benchmarktest/event_benchmark_test/event_benchmark_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a1bd3f8d1f799b3c94defc84c4c127cdca387f3 --- /dev/null +++ b/base/test/benchmarktest/event_benchmark_test/event_benchmark_test.cpp @@ -0,0 +1,1442 @@ +/* + * Copyright (c) 2023 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 +#include +#include +#include +#include "unistd.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common_timer_errors.h" +#include "common_event_sys_errors.h" +#include "io_event_handler.h" +#include "io_event_reactor.h" +#include +#include "../log.h" +#include "../assert.h" +using namespace OHOS::Utils; + +namespace OHOS { +namespace { + +class BenchmarkEventTest : public benchmark::Fixture { +public: + BenchmarkEventTest() + { + Iterations(iterations); + Repetitions(repetitions); + ReportAggregatesOnly(); + } + + ~BenchmarkEventTest() override = default; + void SetUp(const ::benchmark::State& state) override + { + } + + void TearDown(const ::benchmark::State& state) override + { + } + +protected: + const int32_t repetitions = 3; + const int32_t iterations = 500; +}; + +int g_data = 0; +void TimerCallback1() +{ + g_data++; +} + +static const int MILLI_TO_BASE = 1000; +static const int NANO_TO_BASE = 1000000000; +static constexpr int MILLI_TO_NANO = NANO_TO_BASE / MILLI_TO_BASE; +const int INVALID_FD = -1; +const int SLEEP_SIXTEEN_MILLISECONDS = 16; +const int TIMER_INIT_DELAY = 15; +constexpr uint32_t TIMEOUT_ONE_MS = 1; +constexpr uint32_t TIMEOUT_TWO_MS = 2; + + +class TimerFdHandler : public IOEventHandler { +public: + using TimerEventCallback = std::function; + TimerFdHandler(int fd, const TimerEventCallback& cb); + ~TimerFdHandler() {} + bool Initialize(uint32_t interval); + void Uninitialize(); + void TimeOut(); + +private: + TimerEventCallback timerCallback_; +}; + +void TestCallback() +{ +} + +/* + * @tc.name: testIOEventHandler001 + * @tc.desc: test basic interfaces of IOEventHandler. + */ +BENCHMARK_F(BenchmarkEventTest, testIOEventHandler001)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testIOEventHandler001 start."); + while (state.KeepRunning()) { + g_data = 0; + // 1. Create io event handler + std::shared_ptr handler = std::make_shared(INVALID_FD); + + // 2. Set fd + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state); + handler->SetFd(fd); + AssertEqual(handler->GetFd(), fd, "handler->GetFd() did not equal fd as expected.", state); + + // 3. Set callback + handler->SetCallback(&TestCallback); + AssertUnequal(handler->GetCallback(), nullptr, + "handler->GetCallback() was not different from nullptr as expected.", state); + + // 4. Set interest events + handler->SetEvents(Events::EVENT_READ | Events::EVENT_WRITE); + AssertEqual(handler->GetEvents(), (Events::EVENT_READ | Events::EVENT_WRITE), + "handler->GetEvents() did not equal (Events::EVENT_READ | Events::EVENT_WRITE) as expected.", state); + + // 5. Check status + AssertEqual(handler->Prev(), nullptr, "handler->Prev() did not equal nullptr as expected.", state); + AssertEqual(handler->Next(), nullptr, "handler->Next() did not equal nullptr as expected.", state); + AssertEqual(handler->IsActive(), false, "handler->IsActive() did not equal false as expected.", state); + + // 6. disable events + handler->DisableAll(); + AssertEqual(handler->GetEvents(), Events::EVENT_NONE, + "handler->GetEvents() did not equal Events::EVENT_NONE as expected.", state); + + // 7. enable events + handler->EnableRead(); + handler->EnableWrite(); + AssertEqual(handler->GetEvents(), (Events::EVENT_READ | Events::EVENT_WRITE), + "handler->GetEvents() did not equal (Events::EVENT_READ | Events::EVENT_WRITE) as expected.", state); + + // 8. disable one of the events + handler->DisableWrite(); + AssertEqual(handler->GetEvents(), Events::EVENT_READ, + "handler->GetEvents() did not equal Events::EVENT_READ as expected.", state); + } + BENCHMARK_LOGD("EventTest testIOEventHandler001 end."); +} + +/* + * @tc.name: testIOEventHandler002 + * @tc.desc: test reactor-related interfaces of IOEventHandler. + */ +BENCHMARK_F(BenchmarkEventTest, testIOEventHandler002)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testIOEventHandler002 start."); + while (state.KeepRunning()) { + g_data = 0; + // 1. Create io event handler + std::shared_ptr handler = std::make_shared(INVALID_FD); + + // 2. Set fd + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state); + handler->SetFd(fd); + AssertEqual(handler->GetFd(), fd, "handler->GetFd() did not equal fd as expected.", state); + + // 3. Set callback + handler->SetCallback(&TestCallback); + AssertUnequal(handler->GetCallback(), nullptr, + "handler->GetCallback() was not different from nullptr as expected.", state); + + // 4. Set interest events + handler->EnableRead(); + AssertEqual(handler->GetEvents(), Events::EVENT_READ, + "handler->GetEvents() did not equal Events::EVENT_READ as expected.", state); + + // 5. Create a reactor but not run + std::shared_ptr reactor = std::make_shared(); + AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK, + "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 6. Start handler + handler->Start(reactor.get()); + AssertEqual(reactor->FindHandler(handler.get()), EVENT_SYS_ERR_OK, + "reactor->FindHandler(handler.get()) did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 7. Change setting and update handler to the reactor + handler->EnableWrite(); + AssertTrue((handler->Update(reactor.get())), + "handler->Update(reactor.get()) did not equal true as expected.", state); + + // 8. Remove the handler + handler->Stop(reactor.get()); + AssertEqual(reactor->FindHandler(handler.get()), EVENT_SYS_ERR_NOT_FOUND, + "reactor->FindHandler(handler.get()) did not equal EVENT_SYS_ERR_NOT_FOUND as expected.", state); + + // 9. Add handler, then delete handler. handler will remove itself from the reactor during deconstruction. + AssertTrue((handler->Start(reactor.get())), + "handler->Start(reactor.get()) did not equal true as expected.", state); + handler.reset(); + } + BENCHMARK_LOGD("EventTest testIOEventHandler002 end."); +} + +/* + * @tc.name: testIOEventReactor001 + * @tc.desc: test basic interfaces of IOEventReactor. + */ +BENCHMARK_F(BenchmarkEventTest, testIOEventReactor001)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testIOEventReactor001 start."); + while (state.KeepRunning()) { + g_data = 0; + // Get fd + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state); + + // 1. Create io event handlers + std::shared_ptr handler1 = std::make_shared(fd); + std::shared_ptr handler2 = std::make_shared(fd); + std::shared_ptr handler3 = std::make_shared(INVALID_FD); + std::shared_ptr handler4 = std::make_shared(fd); + + // 2. Create a reactor but not run + std::shared_ptr reactor = std::make_shared(); + AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK, + "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 3. Add handler + AssertEqual(reactor->AddHandler(handler1.get()), EVENT_SYS_ERR_OK, + "reactor->AddHandler(handler1.get()) did not equal EVENT_SYS_ERR_OK as expected.", state); + AssertEqual(reactor->AddHandler(handler2.get()), EVENT_SYS_ERR_OK, + "reactor->AddHandler(handler2.get()) did not equal EVENT_SYS_ERR_OK as expected.", state); + AssertUnequal(reactor->AddHandler(handler3.get()), EVENT_SYS_ERR_OK, + "reactor->AddHandler(handler3.get()) was not different from EVENT_SYS_ERR_OK as expected.", state); + AssertUnequal(reactor->AddHandler(nullptr), EVENT_SYS_ERR_OK, + "reactor->AddHandler(nullptr) was not different from EVENT_SYS_ERR_OK as expected.", state); + + // 4. Add handler from the handler side. + AssertUnequal(handler1->Start(reactor.get()), true, + "handler1->Start(reactor.get()) was not different from false as expected.", state); + AssertUnequal(handler3->Start(reactor.get()), true, + "handler3->Start(reactor.get()) was not different from false as expected.", state); + + // 5. Remove handler + AssertUnequal(reactor->RemoveHandler(nullptr), EVENT_SYS_ERR_OK, + "reactor->RemoveHandler(nullptr) was not different from EVENT_SYS_ERR_OK as expected.", state); + AssertUnequal(reactor->RemoveHandler(handler3.get()), EVENT_SYS_ERR_OK, + "reactor->RemoveHandler(handler3.get()) was not different from EVENT_SYS_ERR_OK as expected.", state); + AssertUnequal(reactor->RemoveHandler(handler4.get()), EVENT_SYS_ERR_OK, + "reactor->RemoveHandler(handler4.get()) was not different from EVENT_SYS_ERR_OK as expected.", state); + AssertEqual(reactor->RemoveHandler(handler2.get()), EVENT_SYS_ERR_OK, + "reactor->RemoveHandler(handler2.get()) did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 6. Remove handler from the handler side. + AssertUnequal(handler2->Stop(reactor.get()), true, + "handler2->Stop(reactor.get()) was not different from false as expected.", state); + + // 7. Update handler + AssertUnequal(reactor->UpdateHandler(nullptr), EVENT_SYS_ERR_OK, + "reactor->UpdateHandler(nullptr) was not different from EVENT_SYS_ERR_OK as expected.", state); + AssertUnequal(reactor->UpdateHandler(handler3.get()), EVENT_SYS_ERR_OK, + "reactor->UpdateHandler(handler3.get()) was not different from EVENT_SYS_ERR_OK as expected.", state); + AssertEqual(reactor->UpdateHandler(handler1.get()), EVENT_SYS_ERR_OK, + "reactor->UpdateHandler(handler1.get()) did not equal EVENT_SYS_ERR_OK as expected.", state); + AssertEqual(reactor->UpdateHandler(handler4.get()), EVENT_SYS_ERR_OK, + "reactor->UpdateHandler(handler4.get()) did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 8. Update handler from the handler side. + AssertEqual(handler2->Update(reactor.get()), true, + "handler2->Update(reactor.get()) was not different from false as expected.", state); + AssertUnequal(handler3->Update(reactor.get()), true, + "handler3->Update(reactor.get()) was not different from true as expected.", state); + + // 9. Find handler + AssertUnequal(reactor->FindHandler(nullptr), EVENT_SYS_ERR_OK, + "reactor->FindHandler(nullptr) was not different from EVENT_SYS_ERR_OK as expected.", state); + AssertUnequal(reactor->FindHandler(handler3.get()), EVENT_SYS_ERR_OK, + "reactor->FindHandler(handler3.get()) was not different from EVENT_SYS_ERR_OK as expected.", state); + + // 10. Clean handler + AssertUnequal(reactor->Clean(INVALID_FD), EVENT_SYS_ERR_OK, + "reactor->Clean(INVALID_FD) was not different from EVENT_SYS_ERR_OK as expected.", state); + AssertEqual(reactor->Clean(fd), EVENT_SYS_ERR_OK, + "reactor->Clean(fd) did not equal EVENT_SYS_ERR_OK as expected.", state); + } + BENCHMARK_LOGD("EventTest testIOEventReactor001 end."); +} + +/* + * @tc.name: testIOEventReactor002 + * @tc.desc: test change event but not update. + */ +BENCHMARK_F(BenchmarkEventTest, testIOEventReactor002)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testIOEventReactor002 start."); + while (state.KeepRunning()) { + g_data = 0; + // 1. Open timer + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state); + + // 2. Create io event handlers + std::shared_ptr handler1 = std::make_shared(fd); + std::shared_ptr handler2 = std::make_shared(fd); + + // 3. Create a reactor but not run + std::unique_ptr reactor = std::make_unique(); + AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK, + "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 4. Add handler + AssertEqual(reactor->AddHandler(handler1.get()), EVENT_SYS_ERR_OK, + "reactor->AddHandler(handler1.get()) did not equal EVENT_SYS_ERR_OK as expected.", state); + AssertEqual(reactor->AddHandler(handler2.get()), EVENT_SYS_ERR_OK, + "reactor->AddHandler(handler2.get()) did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 5. release one handler + handler2.reset(); // will be removed from the inner list. + } + BENCHMARK_LOGD("EventTest testIOEventReactor002 end."); +} + +TimerFdHandler::TimerFdHandler(int fd, const TimerEventCallback& cb) + : IOEventHandler(fd), timerCallback_(cb) +{ + BENCHMARK_LOGD("EventTest TimerFdHandler::TimerFdHandler is called."); +} + +bool TimerFdHandler::Initialize(uint32_t interval) +{ + BENCHMARK_LOGD("EventTest bool TimerFdHandler::Initialize is called."); + if ((GetFd() == INVALID_FD)) { + return false; + } + + struct itimerspec newValue = {{0, 0}, {0, 0}}; + timespec now{0, 0}; + if (clock_gettime(CLOCK_MONOTONIC, &now) == INVALID_FD) { + return false; + } + + // next time out time is now + interval + newValue.it_value.tv_sec = now.tv_sec + interval / MILLI_TO_BASE; + newValue.it_value.tv_nsec = now.tv_nsec + (interval % MILLI_TO_BASE) * MILLI_TO_NANO; + if (newValue.it_value.tv_nsec >= NANO_TO_BASE) { + newValue.it_value.tv_sec += 1; + newValue.it_value.tv_nsec = newValue.it_value.tv_nsec % NANO_TO_BASE; + } + + // interval + newValue.it_interval.tv_sec = interval / MILLI_TO_BASE; + newValue.it_interval.tv_nsec = (interval % MILLI_TO_BASE) * MILLI_TO_NANO; + + if (timerfd_settime(GetFd(), TFD_TIMER_ABSTIME, &newValue, nullptr) == INVALID_FD) { + BENCHMARK_LOGD("Set timerFd failed-%{public}s timer_fd:%{public}d, next_time:%{public}lld, "\ + "interval:%{public}lld", strerror(errno), GetFd(), newValue.it_value.tv_sec, newValue.it_interval.tv_sec); + return false; + } + + EnableRead(); + SetCallback(std::bind(&TimerFdHandler::TimeOut, this)); + + return true; +} + +void TimerFdHandler::Uninitialize() +{ + BENCHMARK_LOGD("EventTest void TimerFdHandler::Uninitialize is called."); + DisableAll(); +} + +void TimerFdHandler::TimeOut() +{ + BENCHMARK_LOGD("EventTest void TimerFdHandler::TimeOut is called."); + if (GetFd() == INVALID_FD) { + BENCHMARK_LOGD("Invalid timer_fd."); + return; + } + uint64_t expirations = 0; + ssize_t n = ::read(GetFd(), &expirations, sizeof(expirations)); + if (n != sizeof(expirations)) { + BENCHMARK_LOGD("reads %{public}d bytes instead of 8.", static_cast(n)); + } + + if (timerCallback_) { + timerCallback_(); + } +} + +/* + * @tc.name: testEvent001 + * @tc.desc: test handling event of timerfd. + */ +BENCHMARK_F(BenchmarkEventTest, testEvent001)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testEvent001 start."); + while (state.KeepRunning()) { + g_data = 0; + // 1. Open timer + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state); + // 2. Create timer event handler + std::shared_ptr handler = std::make_shared(fd, &TimerCallback1); + + // 3. Create reactor for event loop + std::unique_ptr reactor = std::make_unique(); + AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK, + "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state); + reactor->EnableHandling(); + + // 4. Initialize timer handler and add it to reactor + AssertTrue((handler->Initialize(10)), "handler->Initialize(10) did not equal true as expected.", state); + AssertTrue((handler->Start(reactor.get())), + "handler->Start(reactor.get()) did not equal true as expected.", state); + + // 5. Run event loop + std::thread loopThread([&reactor] { + reactor->Run(INVALID_FD); + }); + + // 6. Wait for event handling + std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_SIXTEEN_MILLISECONDS)); + + // 7. Check result, execute once at least + AssertGreaterThanOrEqual(g_data, 1, "g_data was not greater than or equal to 1 as expected.", state); + + // 8. terminate the event-loop (aka Run()) + reactor->Terminate(); + loopThread.join(); + } + BENCHMARK_LOGD("EventTest testEvent001 end."); +} + +/* + * @tc.name: testEvent002 + * @tc.desc: test changing event to EVENT_NONE. + */ +BENCHMARK_F(BenchmarkEventTest, testEvent002)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testEvent002 start."); + while (state.KeepRunning()) { + g_data = 0; + // 1. Open timer + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state); + // 2. Create timer event handler + std::shared_ptr handler = std::make_shared(fd, &TimerCallback1); + + // 3. Create reactor for event loop + std::unique_ptr reactor = std::make_unique(); + AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK, + "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 4. Initialize timer handler and add it to reactor + AssertTrue((handler->Initialize(10)), "handler->Initialize(10) did not equal true as expected.", state); + AssertTrue((handler->Start(reactor.get())), + "handler->Start(reactor.get()) did not equal true as expected.", state); + + // 5. Run event loop + std::thread loopThread([&reactor] { + reactor->Run(INVALID_FD); + }); + + // 6. Change settings + reactor->DisableHandling(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + reactor->EnableHandling(); + handler->SetEvents(Events::EVENT_NONE); + + // 7. Wait for event handling + std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_SIXTEEN_MILLISECONDS)); + + // 8. Check result, no execution + AssertEqual(g_data, 0, "g_data did not equal 0 as expected.", state); + + // 9. terminate the event-loop (aka Run()) + reactor->Terminate(); + loopThread.join(); + } + BENCHMARK_LOGD("EventTest testEvent002 end."); +} + +/* + * @tc.name: testEvent003 + * @tc.desc: test disable single event. + */ +BENCHMARK_F(BenchmarkEventTest, testEvent003)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testEvent003 start."); + while (state.KeepRunning()) { + g_data = 0; + // 1. Open timer + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state); + // 2. Create timer event handler + std::shared_ptr handler = std::make_shared(fd, &TimerCallback1); + + // 3. Create reactor for event loop + std::unique_ptr reactor = std::make_unique(); + AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK, + "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 4. Initialize timer handler and add it to reactor + AssertTrue((handler->Initialize(10)), "handler->Initialize(10) did not equal true as expected.", state); + AssertTrue((handler->Start(reactor.get())), + "handler->Start(reactor.get()) did not equal true as expected.", state); + + // 5. Run event loop + std::thread loopThread([&reactor] { + reactor->Run(INVALID_FD); + }); + + // 6. Change settings + reactor->EnableHandling(); + AssertTrue((handler->Stop(reactor.get())), + "handler->Stop(reactor.get()) did not equal true as expected.", state); + + // 7. Check result, no execution + AssertEqual(g_data, 0, "g_data did not equal 0 as expected.", state); + + // 8. terminate the event-loop (aka Run()) + reactor->Terminate(); + loopThread.join(); + } + BENCHMARK_LOGD("EventTest testEvent003 end."); +} + +/* + * @tc.name: testEvent004 + * @tc.desc: test removing callback. + */ +BENCHMARK_F(BenchmarkEventTest, testEvent004)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testEvent004 start."); + while (state.KeepRunning()) { + g_data = 0; + // 1. Open timer + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state); + // 2. Create timer event handler + std::shared_ptr handler = std::make_shared(fd, &TimerCallback1); + + // 3. Create reactor for event loop + std::unique_ptr reactor = std::make_unique(); + AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK, + "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 4. Initialize timer handler and add it to reactor + AssertTrue((handler->Initialize(10)), "handler->Initialize(10) did not equal true as expected.", state); + AssertTrue((handler->Start(reactor.get())), + "handler->Start(reactor.get()) did not equal true as expected.", state); + + // 5. Run event loop + std::thread loopThread([&reactor] { + reactor->Run(INVALID_FD); + }); + + // 6. Change settings + reactor->EnableHandling(); + handler->SetCallback(nullptr); + + // 7. Wait for event handling + std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_SIXTEEN_MILLISECONDS)); + + // 8. Check result, no execution + AssertEqual(g_data, 0, "g_data did not equal 0 as expected.", state); + + // 9. terminate the event-loop (aka Run()) + reactor->Terminate(); + loopThread.join(); + } + BENCHMARK_LOGD("EventTest testEvent004 end."); +} + +/* + * @tc.name: testEvent005 + * @tc.desc: test change event but not update. + */ +BENCHMARK_F(BenchmarkEventTest, testEvent005)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testEvent005 start."); + while (state.KeepRunning()) { + g_data = 0; + // 1. Open timer + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state); + // 2. Create timer event handler + std::shared_ptr handler = std::make_shared(fd, &TimerCallback1); + + // 3. Create reactor for event loop + std::unique_ptr reactor = std::make_unique(); + AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK, + "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 4. Initialize timer handler and add it to reactor + AssertTrue((handler->Initialize(TIMER_INIT_DELAY)), + "handler->Initialize(TIMER_INIT_DELAY) did not equal true as expected.", state); + AssertTrue((handler->Start(reactor.get())), + "handler->Start(reactor.get()) did not equal true as expected.", state); + + // 5. Run event loop + std::thread loopThread([&reactor] { + reactor->Run(INVALID_FD); + }); + + // 6. Change settings but not update + handler->SetEvents(Events::EVENT_WRITE); + reactor->EnableHandling(); + + // 7. Wait for event handling + std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_SIXTEEN_MILLISECONDS)); + + // 8. Check result, no execution + AssertEqual(g_data, 0, "g_data did not equal 0 as expected.", state); + + // 9. terminate the event-loop (aka Run()) + reactor->Terminate(); + loopThread.join(); + } + BENCHMARK_LOGD("EventTest testEvent005 end."); +} + +/* + * @tc.name: testEvent006 + * @tc.desc: test release the handler when started. + */ +BENCHMARK_F(BenchmarkEventTest, testEvent006)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testEvent006 start."); + while (state.KeepRunning()) { + g_data = 0; + // 1. Open timer + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); + AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state); + // 2. Create timer event handler + std::shared_ptr handler = std::make_shared(fd, &TimerCallback1); + + // 3. Create reactor for event loop + std::unique_ptr reactor = std::make_unique(); + AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK, + "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state); + + // 4. Initialize timer handler and add it to reactor + AssertTrue((handler->Initialize(TIMER_INIT_DELAY)), + "handler->Initialize(TIMER_INIT_DELAY) did not equal true as expected.", state); + AssertTrue((handler->Start(reactor.get())), + "handler->Start(reactor.get()) did not equal true as expected.", state); + + // 5. Run event loop + std::thread loopThread([&reactor] { + reactor->Run(INVALID_FD); + }); + + // 6. release eventhandler + handler.reset(); + reactor->EnableHandling(); + + // 7. Wait for event handling + std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_SIXTEEN_MILLISECONDS)); + + // 8. Check result, no execution + AssertEqual(g_data, 0, "g_data did not equal 0 as expected.", state); + + // 9. terminate the event-loop (aka Run()) + reactor->Terminate(); + loopThread.join(); + } + BENCHMARK_LOGD("EventTest testEvent006 end."); +} + +// Try to substitue underlying implementation of OHOS::UTILS::TIMER +class TimerEventHandler { +public: + using TimerEventCallback = std::function; + TimerEventHandler(int timerFd, uint32_t timeout, bool once); + TimerEventHandler(uint32_t timeout /* ms */, bool once); + ~TimerEventHandler(); + + TimerEventHandler(const TimerEventHandler&) = delete; + TimerEventHandler& operator=(const TimerEventHandler&) = delete; + TimerEventHandler(const TimerEventHandler&&) = delete; + TimerEventHandler& operator=(const TimerEventHandler&&) = delete; + + ErrCode Initialize(); + void Uninitialize(); + + bool Start(IOEventReactor* reactor); + bool Stop(IOEventReactor* reactor); + + inline void SetTimerEventCallback(const TimerEventCallback& callback) { timerEventCallback_ = callback; } + + inline void SetTimerId(const uint32_t& id) { timerId_ = id; } + + inline uint32_t GetInterval() const { return interval_; } + inline uint32_t GetTimerId() const { return timerId_; } + inline int GetTimerFd() const { return handler_->GetFd(); } + +private: + void TimeOut(); + +private: + bool once_; + uint32_t timerId_; + uint32_t interval_; + TimerEventCallback timerEventCallback_; + + std::unique_ptr handler_; + + friend class Timer; +}; + +class Timer { +public: + using TimerCallback = std::function; + using TimerCallbackPtr = std::shared_ptr; + using TimerEventCallback = TimerEventHandler::TimerEventCallback; + + explicit Timer(const std::string& name, int timeoutMs = 1000); + virtual ~Timer() {} + virtual uint32_t Setup(); + virtual void Shutdown(bool useJoin = true); + uint32_t Register(const TimerCallback& callback, uint32_t interval /* ms */, bool once = false); + void Unregister(uint32_t timerId); + +private: + void MainLoop(); + void OnTimer(TimerEventHandler* handler, const TimerCallback& callback); + uint32_t GetValidId() const; + int GetTimerFd(uint32_t interval /* ms */); + void EraseUnusedTimerId(uint32_t interval, const std::vector& unusedIds); + +private: + using TimerHandlerPtr = std::shared_ptr; + using TimerHandlerList = std::list; + + ErrCode ScheduleTimer(const TimerEventCallback& callback, uint32_t interval, uint32_t timerId, int& timerFd, + bool once); + ErrCode CancelTimer(TimerHandlerPtr target); + + std::map timerHandlers_; + std::map intervalToTimers_; + + std::string name_; + int timeoutMs_; + std::thread thread_; + std::unique_ptr reactor_; + std::mutex mutex_; +}; + +Timer::Timer(const std::string& name, int timeoutMs) : name_(name), timeoutMs_(timeoutMs), + reactor_(new IOEventReactor()) +{ + BENCHMARK_LOGD("EventTest Timer::Timer is called."); +} + +void Timer::MainLoop() +{ + prctl(PR_SET_NAME, name_.c_str(), 0, 0, 0); + + reactor_->Run(timeoutMs_); + BENCHMARK_LOGD("||%{public}d||Loop finished", gettid()); + BENCHMARK_LOGD("MainLoop timeoutMs_: %{public}d", timeoutMs_); + + if (reactor_->CleanUp() != EVENT_SYS_ERR_OK) { + BENCHMARK_LOGD("||%{public}d||Reactor Clean Failed. It will clean during deconstruction", gettid()); + } +} + +uint32_t Timer::Setup() +{ + BENCHMARK_LOGD("EventTest uint32_t Timer::Setup is called."); + if (thread_.joinable()) { // avoid double assign to an active thread + return TIMER_ERR_INVALID_VALUE; + } + + if (reactor_->SetUp() != EVENT_SYS_ERR_OK) { + BENCHMARK_LOGD("||%{public}d||Setup reactor failed.", gettid()); + return TIMER_ERR_DEAL_FAILED; + } + + reactor_->EnableHandling(); + + std::thread loopThread(std::bind(&Timer::MainLoop, this)); + thread_.swap(loopThread); + + return TIMER_ERR_OK; +} + +void Timer::Shutdown(bool useJoin) +{ + BENCHMARK_LOGD("EventTest void Timer::Shutdown is called."); + if (!thread_.joinable()) { + BENCHMARK_LOGD("||%{public}d||Invalid operation. Already shutdown.", gettid()); + return; + } + + BENCHMARK_LOGD("||%{public}d||Stop reactor.", gettid()); + reactor_->Terminate(); + + if (!useJoin) { + thread_.detach(); + return; + } + thread_.join(); +} + +ErrCode Timer::ScheduleTimer(const TimerEventCallback& callback, uint32_t interval, + uint32_t timerId, int& timerFd, bool once) +{ + BENCHMARK_LOGD("EventTest ErrCode Timer::ScheduleTimer is called."); + std::shared_ptr handler = std::make_shared(timerFd, interval, once); + BENCHMARK_LOGD("Timer::ScheduleTimer interval: %{public}u -- timerId: %{public}u -- timerFd: %{public}d", + interval, timerId, timerFd); + + handler->SetTimerId(timerId); + handler->SetTimerEventCallback(callback); + + uint32_t ret = handler->Initialize(); + if (ret != TIMER_ERR_OK) { + BENCHMARK_LOGD("||%{public}d||Init timer handler failed.", gettid()); + return ret; + } + if (!handler->Start(reactor_.get())) { + BENCHMARK_LOGD("||%{public}d||Start timer handler failed.", gettid()); + return TIMER_ERR_DEAL_FAILED; + } + timerHandlers_.emplace(timerId, handler); // Add to the id2handlers map + intervalToTimers_[interval].push_back(handler); // Add to interval2handlerlist map + timerFd = handler->GetTimerFd(); + return TIMER_ERR_OK; +} + + +uint32_t Timer::Register(const TimerCallback& callback, uint32_t interval /* ms */, bool once) +{ + BENCHMARK_LOGD("EventTest uint32_t Timer::Register is called."); + std::lock_guard lock(mutex_); + + // wrap the callback in OnTiner + TimerEventCallback wrappedCb = std::bind(&Timer::OnTimer, this, std::placeholders::_1, callback); + int timerFd = once ? IO_EVENT_INVALID_FD : GetTimerFd(interval); // Get timerFd + uint32_t timerId = GetValidId(); // Get timerId + + uint32_t ret = ScheduleTimer(wrappedCb, interval, timerId, timerFd, once); + if (ret != TIMER_ERR_OK) { + BENCHMARK_LOGD("||%{public}d||Try schedule task failed. timer-id:%{public}d, interval:%{public}d, "\ + "timer-fd:%{public}d", gettid(), timerId, interval, timerFd); + return TIMER_ERR_DEAL_FAILED; + } + + return timerId; +} + +ErrCode Timer::CancelTimer(TimerHandlerPtr target) +{ + BENCHMARK_LOGD("EventTest ErrCode Timer::CancelTimer is called."); + BENCHMARK_LOGD("||%{public}d||Cancle timer handler with fd:%{public}d", gettid(), target->GetTimerFd()); + target->Uninitialize(); + if (!target->Stop(reactor_.get())) { + BENCHMARK_LOGD("||%{public}d||Stop timer handler failed.", gettid()); + return TIMER_ERR_DEAL_FAILED; + } + + timerHandlers_.erase(target->timerId_); + + auto handlerList = intervalToTimers_[target->interval_]; + auto itor = std::find(handlerList.begin(), handlerList.end(), target); + if (itor != handlerList.end()) { + handlerList.erase(itor); + } + + if (handlerList.empty()) { + intervalToTimers_.erase(target->interval_); + } + + return TIMER_ERR_OK; +} + +void Timer::Unregister(uint32_t timerId) +{ + BENCHMARK_LOGD("EventTest void Timer::Unregister is called."); + std::lock_guard lock(mutex_); + + if (timerHandlers_.find(timerId) == timerHandlers_.end()) { + BENCHMARK_LOGD("||%{public}d||Unregister failed. timer-id:%{public}d not found.", gettid(), timerId); + return; + } + + auto entry = timerHandlers_[timerId]; + BENCHMARK_LOGD("||%{public}d||Try remove timer handler from reactor. timerId:%{public}d, interval:%{public}u", + gettid(), timerId, entry->interval_); + + if (CancelTimer(entry) != TIMER_ERR_OK) { + BENCHMARK_LOGD("||%{public}d||Unregister timer handler failed.", gettid()); + } +} + +void Timer::OnTimer(TimerEventHandler* handler, const TimerCallback& callback) +{ + BENCHMARK_LOGD("EventTest void Timer::OnTimer is called."); + callback(); + + if (handler->once_) { + Unregister(handler->timerId_); + } +} + +uint32_t Timer::GetValidId() const +{ + BENCHMARK_LOGD("EventTest uint32_t Timer::GetValidId is called."); + static std::atomic_uint32_t timerId = 1; + + while (timerHandlers_.find(timerId) != timerHandlers_.end()) { + timerId++; + if (timerId == UINT32_MAX) { + timerId = 1; + } + + if (timerId == TIMER_ERR_DEAL_FAILED) { + timerId++; + } + } + + return timerId; +} + +int Timer::GetTimerFd(uint32_t interval /* ms */) +{ + BENCHMARK_LOGD("EventTest int Timer::GetTimerFd is called."); + if (intervalToTimers_.find(interval) == intervalToTimers_.end()) { + return IO_EVENT_INVALID_FD; + } + auto &handlerList = intervalToTimers_[interval]; + for (const TimerHandlerPtr &ptr : handlerList) { + if (!ptr->once_) { + return ptr->GetTimerFd(); + } + } + return IO_EVENT_INVALID_FD; +} + +TimerEventHandler::TimerEventHandler(int timerFd, uint32_t timeout /* ms */, bool once) + : once_(once), interval_(timeout) +{ + BENCHMARK_LOGD("EventTest : once_(once), interval_ is called."); + if (timerFd == IO_EVENT_INVALID_FD) { + handler_ = std::make_unique(timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC)); + } else { + handler_ = std::make_unique(timerFd); + } +} + +TimerEventHandler::~TimerEventHandler() +{ + BENCHMARK_LOGD("EventTest TimerEventHandler::~TimerEventHandler is called."); + if (close(handler_->GetFd()) != 0) { + BENCHMARK_LOGD("||%{public}d||Close timer-fd failed. fd:%{public}d, interval:%{public}u, once:%{public}d", + gettid(), handler_->GetFd(), interval_, once_); + } + handler_->SetFd(IO_EVENT_INVALID_FD); +} + +ErrCode TimerEventHandler::Initialize() +{ + BENCHMARK_LOGD("EventTest ErrCode TimerEventHandler::Initialize is called."); + if (handler_->GetFd() == IO_EVENT_INVALID_FD) { + BENCHMARK_LOGD("||%{public}d||Invalid timer-fd:%{public}d, interval:%{public}u, once:%{public}d", + gettid(), handler_->GetFd(), interval_, once_); + return TIMER_ERR_INVALID_VALUE; + } + + struct itimerspec newValue = {{0, 0}, {0, 0}}; + timespec now{0, 0}; + if (clock_gettime(CLOCK_MONOTONIC, &now) == INVALID_FD) { + BENCHMARK_LOGD("||%{public}d||Get current time failed.", gettid()); + return TIMER_ERR_DEAL_FAILED; + } + + // next time out time is now + interval + newValue.it_value.tv_sec = now.tv_sec + interval_ / MILLI_TO_BASE; + newValue.it_value.tv_nsec = now.tv_nsec + (interval_ % MILLI_TO_BASE) * MILLI_TO_NANO; + if (newValue.it_value.tv_nsec >= NANO_TO_BASE) { + newValue.it_value.tv_sec += 1; + newValue.it_value.tv_nsec = newValue.it_value.tv_nsec % NANO_TO_BASE; + } + + if (once_) { + // interval, 0 means time out only once + newValue.it_interval.tv_sec = 0; + newValue.it_interval.tv_nsec = 0; + } else { + // interval + newValue.it_interval.tv_sec = interval_ / MILLI_TO_BASE; + newValue.it_interval.tv_nsec = (interval_ % MILLI_TO_BASE) * MILLI_TO_NANO; + } + + if (timerfd_settime(handler_->GetFd(), TFD_TIMER_ABSTIME, &newValue, nullptr) == INVALID_FD) { + BENCHMARK_LOGD("||%{public}d||Set timer-fd failed. next:%{public}lld, interval:%{public}lld", + gettid(), static_cast(newValue.it_value.tv_sec), + static_cast(newValue.it_interval.tv_sec)); + + return TIMER_ERR_DEAL_FAILED; + } + + handler_->SetCallback(std::bind(&TimerEventHandler::TimeOut, this)); + handler_->EnableRead(); + + return TIMER_ERR_OK; +} + +void TimerEventHandler::Uninitialize() +{ + BENCHMARK_LOGD("EventTest void TimerEventHandler::Uninitialize is called."); + handler_->DisableAll(); +} + +bool TimerEventHandler::Start(IOEventReactor* reactor) +{ + BENCHMARK_LOGD("EventTest bool TimerEventHandler::Start is called."); + if (handler_ == nullptr || !handler_->Start(reactor)) { + return false; + } + + return true; +} + +bool TimerEventHandler::Stop(IOEventReactor* reactor) +{ + BENCHMARK_LOGD("EventTest bool TimerEventHandler::Stop is called."); + if (handler_ == nullptr || !handler_->Stop(reactor)) { + return false; + } + + return true; +} + +void TimerEventHandler::TimeOut() +{ + if (handler_->GetFd() == IO_EVENT_INVALID_FD) { + BENCHMARK_LOGD("||%{public}d||Invalid timerfd.", gettid()); + return; + } + uint64_t expirations = 0; + const size_t expirationSize = sizeof(expirations); + ssize_t n = ::read(handler_->GetFd(), &expirations, expirationSize); + if (n != expirationSize) { + BENCHMARK_LOGD("||%{public}d||Reads %{public}d bytes instead of %{public}d from timer fd.", + gettid(), static_cast(n), expirationSize); + } + + if (timerEventCallback_) { + timerEventCallback_(this); + } +} + + +int64_t CurMs() +{ + struct timeval tpend; + gettimeofday(&tpend, nullptr); + return (tpend.tv_sec * 1000000 + tpend.tv_usec) / 1000; // 1000000: s to us, 1000: us to ms +} + +std::atomic g_data1(0); +void TimeOutCallback1() +{ + g_data1 += 1; +} + +std::atomic g_data2(0); +void TimeOutCallback2() +{ + g_data2 += 1; +} + +/* + * @tc.name: testNewTimer001 + * @tc.desc: test basic function of timer implemented by new event-system. + */ +BENCHMARK_F(BenchmarkEventTest, testNewTimer001)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testNewTimer001 start."); + const int sleepDurationMs = 15; + while (state.KeepRunning()) { + g_data1 = 0; + Timer timer("test_timer", 100); + uint32_t ret = timer.Setup(); + AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state); + timer.Register(TimeOutCallback1, 1, true); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs)); + timer.Shutdown(); + AssertEqual(1, g_data1, "1 did not equal g_data1 as expected.", state); + } + BENCHMARK_LOGD("EventTest testNewTimer001 end."); +} + +/* + * @tc.name: testNewTimer002 + * @tc.desc: test basic function of timer implemented by new event-system. + */ +BENCHMARK_F(BenchmarkEventTest, testNewTimer002)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testNewTimer002 start."); + constexpr uint32_t sleepDurationMs = 200; + constexpr uint32_t expectedData1 = 8; + constexpr uint32_t expectedData2 = 2; + while (state.KeepRunning()) { + g_data1 = 0; + g_data2 = 0; + Timer timer("test_timer", 50); + uint32_t ret = timer.Setup(); + AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state); + timer.Register(TimeOutCallback1, TIMEOUT_ONE_MS); + timer.Register(TimeOutCallback2, TIMEOUT_TWO_MS); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs)); + timer.Shutdown(); + AssertGreaterThanOrEqual(g_data1, expectedData1, + "g_data1 was not greater than or equal to expectedData1 as expected.", state); + AssertGreaterThanOrEqual(g_data2, expectedData2, + "g_data2 was not greater than or equal to expectedData2 as expected.", state); + } + BENCHMARK_LOGD("EventTest testNewTimer002 end."); +} + +/* + * @tc.name: testNewTimer003 + * @tc.desc: test basic function of timer implemented by new event-system. + */ +BENCHMARK_F(BenchmarkEventTest, testNewTimer003)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testNewTimer003 start."); + constexpr uint32_t sleepDurationMs = 30; + constexpr uint32_t expectedData = 5; + while (state.KeepRunning()) { + g_data1 = 0; + Timer timer("test_timer", 100); + uint32_t ret = timer.Setup(); + AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state); + timer.Register(TimeOutCallback1, TIMEOUT_ONE_MS); + timer.Register(TimeOutCallback1, TIMEOUT_TWO_MS); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs)); + timer.Shutdown(); + AssertGreaterThanOrEqual(g_data1, expectedData, + "g_data1 was not greater than or equal to expectedData as expected.", state); + } + BENCHMARK_LOGD("EventTest testNewTimer003 end."); +} + +class A { +public: + explicit A(int data) : data_(data), timer_("ATimer", 100) {} + ~A() = default; + bool Init(); + bool StartTimer(int milliseconds, bool once); + void StopTimer(); + int GetData() const {return data_;} +private: + void TimeOutProc() + { + data_ -= 1; + }; + int data_; + Timer timer_; +}; + +bool A::Init() +{ + BENCHMARK_LOGD("EventTest bool A::Init is called."); + return timer_.Setup() == Utils::TIMER_ERR_OK; +} + +bool A::StartTimer(int milliseconds, bool once) +{ + BENCHMARK_LOGD("EventTest bool A::StartTimer is called."); + uint32_t timerId = timer_.Register(std::bind(&A::TimeOutProc, this), milliseconds, once); + return timerId != Utils::TIMER_ERR_DEAL_FAILED; +} + +void A::StopTimer() +{ + BENCHMARK_LOGD("EventTest void A::StopTimer is called."); + timer_.Shutdown(); +} + +/* + * @tc.name: testNewTimer004 + * @tc.desc: test wrapper of the timer implemented by new event-system. + */ +BENCHMARK_F(BenchmarkEventTest, testNewTimer004)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testNewTimer004 start."); + constexpr int initialValue = 10; + constexpr int timeoutSeconds = 1; + constexpr int sleepDurationMs = 20; + constexpr int expectedData = 9; + while (state.KeepRunning()) { + A a(initialValue); + AssertTrue((a.Init()), "a.Init() did not equal true as expected.", state); + AssertTrue((a.StartTimer(timeoutSeconds, true)), + "a.StartTimer(timeoutSeconds, true) did not equal true as expected.", state); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs)); + a.StopTimer(); + AssertEqual(expectedData, a.GetData(), "expectedData did not equal a.GetData() as expected.", state); + } + BENCHMARK_LOGD("EventTest testNewTimer004 end."); +} + +/* + * @tc.name: testNewTimer005 + * @tc.desc: test abnormal case of timer implemented by new event-system. + */ +BENCHMARK_F(BenchmarkEventTest, testNewTimer005)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testNewTimer005 start."); + constexpr uint32_t loopCount = 10; + constexpr uint32_t timeoutSeconds = 7; + constexpr uint32_t sleepDurationMs = 10; + constexpr uint32_t expectedData = 5; + while (state.KeepRunning()) { + g_data1 = 0; + Timer timer("test_timer", INVALID_FD); + uint32_t ret = timer.Setup(); + AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state); + + uint32_t timerId = 0; + for (uint32_t i = 0; i < loopCount; i++) { + timerId = timer.Register(TimeOutCallback1, timeoutSeconds, true); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs)); + } + timer.Unregister(timerId); + timer.Unregister(timerId); + + timer.Shutdown(); + timer.Shutdown(false); + AssertGreaterThanOrEqual(g_data1, expectedData, + "g_data1 was not greater than or equal to expectedData as expected.", state); + } + BENCHMARK_LOGD("EventTest testNewTimer005 end."); +} + +BENCHMARK_F(BenchmarkEventTest, testNewTimer006)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testNewTimer006 start."); + constexpr uint32_t timeoutSeconds = 10; + constexpr int loopCount = 11; + constexpr int sleepDurationMs = 10; + constexpr int expectedTimeDiff = 10; + constexpr int expectedData = 10; + while (state.KeepRunning()) { + g_data1 = 0; + Timer timer("test_timer", 100); + uint32_t ret = timer.Setup(); + AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state); + timer.Register(TimeOutCallback1, timeoutSeconds); + + for (int i = 0; i < loopCount; i++) { + int64_t pre = CurMs(); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs)); + int64_t cur = CurMs(); + AssertGreaterThanOrEqual(cur - pre, expectedTimeDiff, + "cur - pre was not greater than or equal to expectedTimeDiff as expected.", state); + } + timer.Shutdown(); + AssertGreaterThanOrEqual(g_data1, expectedData, + "g_data1 was not greater than or equal to expectedData as expected.", state); + } + BENCHMARK_LOGD("EventTest testNewTimer006 end."); +} + +constexpr int RECURSION_DEPTH = 9; +constexpr int INTERVAL_SECONDS = 10; + +/* + * @tc.name: testNewTimer007 + * @tc.desc: recursive test of timer implemented by new event-system. + */ +void DoFunc(Timer &timer, int &count) +{ + BENCHMARK_LOGD("EventTest void DoFunc is called."); + (void)timer.Register( + [&timer, &count]() { + count += 1; + if (count > RECURSION_DEPTH) { + return; + } + DoFunc(timer, count); + }, + INTERVAL_SECONDS, true); + g_data1++; +} + +void DoFunc2(Timer &timer, int &count) +{ + BENCHMARK_LOGD("EventTest void DoFunc2 is called."); + (void)timer.Register( + [&timer, &count]() { + count += 1; + if (count > RECURSION_DEPTH) { + return; + } + DoFunc2(timer, count); + }, + INTERVAL_SECONDS, true); + g_data1++; +} + +BENCHMARK_F(BenchmarkEventTest, testNewTimer007)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testNewTimer007 start."); + constexpr int expectedMinData = 5; + constexpr int expectedMaxData = 14; + constexpr int expectedMinDataAfterShutdown = 10; + constexpr int sleepDurationMs = 50; + while (state.KeepRunning()) { + g_data1 = 0; + Timer timer("test_timer", 100); + uint32_t ret = timer.Setup(); + AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state); + + int cnt = 0, cnt1 = 0; + DoFunc(timer, cnt); + DoFunc2(timer, cnt1); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs)); + AssertGreaterThanOrEqual(g_data1, expectedMinData, + "g_data1 was not greater than or equal to expectedMinData as expected.", state); + AssertGreaterThanOrEqual(expectedMaxData, g_data1, + "expectedMaxData was not greater than or equal to g_data1 as expected.", state); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs)); + timer.Shutdown(); + AssertGreaterThanOrEqual(g_data1, expectedMinDataAfterShutdown, + "g_data1 was not greater than or equal to expectedMinDataAfterShutdown as expected.", state); + } + BENCHMARK_LOGD("EventTest testNewTimer007 end."); +} + +/* + * @tc.name: testNewTimer008 + * @tc.desc: test execute-once and execute-periodly tasks. + */ +BENCHMARK_F(BenchmarkEventTest, testNewTimer008)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testNewTimer008 start."); + constexpr int intervalSeconds = 10; + constexpr int sleepDurationMs = 52; + constexpr int expectedMinData = 8; + while (state.KeepRunning()) { + g_data1 = 0; + Timer timer("test_timer", 100); + uint32_t ret = timer.Setup(); + AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state); + timer.Register(TimeOutCallback1, intervalSeconds, true); + timer.Register(TimeOutCallback1, intervalSeconds); + timer.Register(TimeOutCallback1, intervalSeconds, true); + timer.Register(TimeOutCallback1, intervalSeconds); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs)); + timer.Shutdown(); + AssertGreaterThanOrEqual(g_data1, expectedMinData, + "g_data1 was not greater than or equal to expectedMinData as expected.", state); + } + BENCHMARK_LOGD("EventTest testNewTimer008 end."); +} + +/* + * @tc.name: testIOEventHandlerConstruction001 + * @tc.desc: test construction of IOEventHandler. + */ +BENCHMARK_F(BenchmarkEventTest, testIOEventHandlerConstruction001)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testIOEventHandlerConstruction001 start."); + while (state.KeepRunning()) { + // 1. Construct IOEventHandler + std::shared_ptr handler = std::make_shared(); + + // 2. Check initialization + AssertEqual(handler->GetFd(), IO_EVENT_INVALID_FD, + "handler->GetFd() did not equal IO_EVENT_INVALID_FD as expected.", state); + AssertEqual(handler->GetEvents(), Events::EVENT_NONE, + "handler->GetEvents() did not equal Events::EVENT_NONE as expected.", state); + AssertEqual(handler->GetCallback(), nullptr, + "handler->GetCallback() was not equal to nullptr as expected.", state); + AssertEqual(handler->Prev(), nullptr, "handler->Prev() was not equal to nullptr as expected.", state); + AssertEqual(handler->Next(), nullptr, "handler->Next() was not equal to nullptr as expected.", state); + AssertEqual(handler->IsActive(), false, "handler->IsActive() was not equal to false as expected.", state); + } + BENCHMARK_LOGD("EventTest testIOEventHandlerConstruction001 end."); +} + +/* + * @tc.name: testIOEventHandlerConstructionWithParameters001 + * @tc.desc: test construction of IOEventHandler with parameters. + */ +BENCHMARK_F(BenchmarkEventTest, testIOEventHandlerConstructionWithParameters001)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testIOEventHandlerConstructionWithParameters001 start."); + while (state.KeepRunning()) { + // 1. Define file descriptor and events + int fd = 10; + EventId events = Events::EVENT_READ; + + // 2. Construct IOEventHandler with parameters + std::shared_ptr handler = std::make_shared(fd, events); + + // 3. Check initialization + AssertEqual(handler->GetFd(), fd, "handler->GetFd() did not equal fd as expected.", state); + AssertEqual(handler->GetEvents(), events, "handler->GetEvents() did not equal events as expected.", state); + AssertEqual(handler->Prev(), nullptr, "handler->Prev() was not equal to nullptr as expected.", state); + AssertEqual(handler->Next(), nullptr, "handler->Next() was not equal to nullptr as expected.", state); + AssertEqual(handler->IsActive(), false, "handler->IsActive() was not equal to false as expected.", state); + } + BENCHMARK_LOGD("EventTest testIOEventHandlerConstructionWithParameters001 end."); +} + +/* + * @tc.name: testIOEventHandlerConstructor001 + * @tc.desc: test construction of IOEventHandler. + */ +BENCHMARK_F(BenchmarkEventTest, testIOEventHandlerConstructor001)(benchmark::State& state) +{ + BENCHMARK_LOGD("EventTest testIOEventHandlerConstructor001 start."); + while (state.KeepRunning()) { + // 1. Define file descriptor and events + int fd = 10; + EventId events = Events::EVENT_READ; + + // 2. Construct IOEventHandler with parameters and measure the time + std::shared_ptr handler = std::make_shared(fd, events); + + // 3. Check if the handler is constructed correctly + AssertEqual(handler->GetFd(), fd, "handler->GetFd() did not equal fd as expected.", state); + AssertEqual(handler->GetEvents(), events, "handler->GetEvents() did not equal events as expected.", state); + } + BENCHMARK_LOGD("EventTest testIOEventHandlerConstructor001 end."); +} +} // namespace +} // namespace OHOS +// Run the benchmark +BENCHMARK_MAIN(); diff --git a/base/test/benchmarktest/file_benchmark_test/BUILD.gn b/base/test/benchmarktest/file_benchmark_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..d9a79e2a77f82135c6a9182f2f3c955201b49e11 --- /dev/null +++ b/base/test/benchmarktest/file_benchmark_test/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2023 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. + +import("//build/test.gni") + +module_output_path = "commonlibrary_c_utils/file" + +ohos_benchmarktest("FileTest") { + module_out_path = module_output_path + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "file_benchmark_test.cpp" ] + + deps = [ "//third_party/benchmark:benchmark" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog_base", + ] +} diff --git a/base/test/benchmarktest/file_benchmark_test/file_benchmark_test.cpp b/base/test/benchmarktest/file_benchmark_test/file_benchmark_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..462b5c80339d8b8cc72c199d569e28b89b24e4d5 --- /dev/null +++ b/base/test/benchmarktest/file_benchmark_test/file_benchmark_test.cpp @@ -0,0 +1,1014 @@ +/* + * Copyright (c) 2023 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 +#include +#include +#include +#include +#include +#include +#include +#include "file_ex.h" +#include "../log.h" +#include "../assert.h" +using namespace std; + +namespace OHOS { +namespace { + +static constexpr char CONTENT_STR[] = "TTtt@#$%^&*()_+~`"; +static constexpr char FILE_PATH[] = "./tmp1.txt"; +static constexpr char NULL_STR[] = ""; +static constexpr int MAX_FILE_LENGTH = 1 * 1024 * 1024; +static constexpr int EXCEEDS_MAXIMUM_LENGTH = 32 * 1024 * 1024 + 1; + +class BenchmarkFileTest : public benchmark::Fixture { +public: + BenchmarkFileTest() + { + Iterations(iterations); + Repetitions(repetitions); + ReportAggregatesOnly(); + } + + ~BenchmarkFileTest() override = default; + void SetUp(const ::benchmark::State& state) override + { + } + + void TearDown(const ::benchmark::State& state) override + { + } + +protected: + const int32_t repetitions = 3; + const int32_t iterations = 1000; +}; + +bool CreateTestFile(const std::string& path, const std::string& content) +{ + ofstream out(path, ios_base::out | ios_base::trunc); + if (out.is_open()) { + out << content; + return true; + } + + BENCHMARK_LOGD("open file failed! %{public}s", path.c_str()); + return false; +} + +int RemoveTestFile(const std::string& path) +{ + return unlink(path.c_str()); +} + +/* + * @tc.name: testLoadStringFromFile001 + * @tc.desc: Test loading an existed file 'meminfo' + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFile001)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFile001 start."); + string filename = "/proc/meminfo"; + while (state.KeepRunning()) { + string str; + AssertTrue((LoadStringFromFile(filename, str)), + "LoadStringFromFile(filename, str) did not equal true as expected.", state); + + string str2; + int fd = open(filename.c_str(), O_RDONLY); + AssertTrue((LoadStringFromFd(fd, str2)), "LoadStringFromFd(fd, str2) did not equal true as expected.", state); + close(fd); + AssertEqual(str.size(), str2.size(), "str.size() did not equal str2.size() as expected.", state); + + vector buff; + bool ret = LoadBufferFromFile(filename, buff); + AssertTrue((ret), "ret did not equal true as expected.", state); + AssertEqual(str2.size(), buff.size(), "str2.size() did not equal buff.size() as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFile001 end."); +} + +/* + * @tc.name: testLoadStringFromFile002 + * @tc.desc: Test loading a non-existed file + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFile002)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFile002 start."); + string filename = NULL_STR; + while (state.KeepRunning()) { + string str; + AssertFalse((LoadStringFromFile(filename, str)), + "LoadStringFromFile(filename, str) did not equal false as expected.", state); + AssertTrue((str.empty()), "str.empty() did not equal true as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFile002 end."); +} + +/* + * @tc.name: testLoadStringFromFile003 + * @tc.desc: Test loading a newly created file with null contents + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFile003)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFile003 start."); + string filename = FILE_PATH; + string content = NULL_STR; + while (state.KeepRunning()) { + string str; + CreateTestFile(filename, content); + AssertTrue((LoadStringFromFile(filename, str)), + "LoadStringFromFile(filename, str) did not equal true as expected.", state); + RemoveTestFile(filename); + AssertEqual(str, content, "str == content did not equal true as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFile003 end."); +} + +/* + * @tc.name: testLoadStringFromFile004 + * @tc.desc: Test loading a newly created file with contents + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFile004)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFile004 start."); + string filename = FILE_PATH; + string content = CONTENT_STR; + while (state.KeepRunning()) { + string str; + CreateTestFile(filename, content); + AssertTrue((LoadStringFromFile(filename, str)), + "LoadStringFromFile(filename, str) did not equal true as expected.", state); + RemoveTestFile(filename); + AssertEqual(str, content, "str == content did not equal true as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFile004 end."); +} + +/* + * @tc.name: testLoadStringFromFile005 + * @tc.desc: Test loading a newly created file, whose contents are of maximum length + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFile005)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFile005 start."); + string content(MAX_FILE_LENGTH, 't'); + string filename = FILE_PATH; + while (state.KeepRunning()) { + string str; + CreateTestFile(filename, content); + AssertTrue((LoadStringFromFile(filename, str)), + "LoadStringFromFile(filename, str) did not equal true as expected.", state); + RemoveTestFile(filename); + AssertEqual(str, content, "str == content did not equal true as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFile005 end."); +} + +/* + * @tc.name: testLoadStringFromFile006 + * @tc.desc: Test loading a newly created file, whose contents exceeds maximum length + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFile006)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFile006 start."); + string content(EXCEEDS_MAXIMUM_LENGTH, 't'); + string filename = FILE_PATH; + while (state.KeepRunning()) { + string str; + CreateTestFile(filename, content); + AssertFalse((LoadStringFromFile(filename, str)), + "LoadStringFromFile(filename, str) did not equal false as expected.", state); + RemoveTestFile(filename); + AssertTrue((str.empty()), "str.empty() did not equal true as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFile006 end."); +} + +/* + * @tc.name: testLoadStringFromFd001 + * @tc.desc: Test loading a file by a invalid fd -1 + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFd001)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFd001 start."); + while (state.KeepRunning()) { + string result; + AssertFalse((LoadStringFromFd(-1, result)), + "LoadStringFromFd(-1, result) did not equal false as expected.", state); + AssertEqual(result, "", "result did not equal "" as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFd001 end."); +} + +/* + * @tc.name: testLoadStringFromFd002 + * @tc.desc: Test loading a newly created file without contents by its fd + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFd002)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFd002 start."); + string filename = FILE_PATH; + string content = NULL_STR; + while (state.KeepRunning()) { + string result; + CreateTestFile(filename, content); + int fd = open(filename.c_str(), O_RDONLY); + AssertTrue((LoadStringFromFd(fd, result)), + "LoadStringFromFd(fd, result) did not equal true as expected.", state); + close(fd); + RemoveTestFile(filename); + AssertEqual(result, content, "result == content did not equal true as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFd002 end."); +} + +/* + * @tc.name: testLoadStringFromFd003 + * @tc.desc: Test loading a newly created file with contents by its fd + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFd003)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFd003 start."); + string filename = FILE_PATH; + string content = CONTENT_STR; + while (state.KeepRunning()) { + string result; + CreateTestFile(filename, content); + int fd = open(filename.c_str(), O_RDONLY); + AssertTrue((LoadStringFromFd(fd, result)), + "LoadStringFromFd(fd, result) did not equal true as expected.", state); + close(fd); + RemoveTestFile(filename); + AssertEqual(result, content, "result == content did not equal true as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFd003 end."); +} + +/* + * @tc.name: testLoadStringFromFd004 + * @tc.desc: Test loading a newly created file by fd, whose contents are of maximum length + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFd004)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFd004 start."); + string content(MAX_FILE_LENGTH, 't'); + string filename = FILE_PATH; + while (state.KeepRunning()) { + string result; + CreateTestFile(filename, content); + int fd = open(filename.c_str(), O_RDONLY); + AssertTrue((LoadStringFromFd(fd, result)), + "LoadStringFromFd(fd, result) did not equal true as expected.", state); + close(fd); + RemoveTestFile(filename); + AssertEqual(result, content, "result == content did not equal true as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFd004 end."); +} + +/* + * @tc.name: testLoadStringFromFd005 + * @tc.desc: Test loading a newly created file by fd, whose contents exceeds maximum length + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFd005)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFd005 start."); + string content(EXCEEDS_MAXIMUM_LENGTH, 't'); + string filename = FILE_PATH; + while (state.KeepRunning()) { + string result; + CreateTestFile(filename, content); + int fd = open(filename.c_str(), O_RDONLY); + AssertFalse((LoadStringFromFd(fd, result)), + "LoadStringFromFd(fd, result) did not equal false as expected.", state); + close(fd); + RemoveTestFile(filename); + AssertUnequal(result, content, "result was not different from content as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFd005 end."); +} + +/* + * @tc.name: testLoadStringFromFd006 + * @tc.desc: Test loading a newly created file by fd, which is closed ahead of loading. + */ +BENCHMARK_F(BenchmarkFileTest, testLoadStringFromFd006)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadStringFromFd006 start."); + string filename = FILE_PATH; + string content = CONTENT_STR; + while (state.KeepRunning()) { + string result; + CreateTestFile(filename, content); + int fd = open(filename.c_str(), O_RDONLY); + close(fd); + AssertFalse((LoadStringFromFd(fd, result)), + "LoadStringFromFd(fd, result) did not equal false as expected.", state); + RemoveTestFile(filename); + AssertEqual(result, "", "result did not equal "" as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadStringFromFd006 end."); +} + +/* + * @tc.name: testSaveStringToFile001 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testSaveStringToFile001)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveStringToFile001 start."); + string path = FILE_PATH; + string content = CONTENT_STR; + while (state.KeepRunning()) { + string newContent; + CreateTestFile(path, content); + bool ret = SaveStringToFile(path, newContent); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + + string loadResult; + AssertTrue((LoadStringFromFile(path, loadResult)), + "LoadStringFromFile(path, loadResult) did not equal true as expected.", state); + RemoveTestFile(path); + AssertEqual(loadResult, content, "loadResult did not equal content as expected.", state); + } + BENCHMARK_LOGD("FileTest testSaveStringToFile001 end."); +} + +/* + * @tc.name: testSaveStringToFile002 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testSaveStringToFile002)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveStringToFile002 start."); + string path = FILE_PATH; + string content = "Before truncated!"; + while (state.KeepRunning()) { + CreateTestFile(path, content); + + string newContent = CONTENT_STR; + AssertTrue((SaveStringToFile(path, newContent)), + "SaveStringToFile(path, newContent) did not equal true as expected.", state); + + string loadResult; + AssertTrue((LoadStringFromFile(path, loadResult)), + "LoadStringFromFile(path, loadResult) did not equal true as expected.", state); + RemoveTestFile(path); + AssertEqual(loadResult, newContent, "loadResult did not equal newContent as expected.", state); + } + BENCHMARK_LOGD("FileTest testSaveStringToFile002 end."); +} + +/* + * @tc.name: testSaveStringToFile003 + * @tc.desc: Test writting an empty string to a file in truncate mode + */ +BENCHMARK_F(BenchmarkFileTest, testSaveStringToFile003)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveStringToFile003 start."); + string path = FILE_PATH; + string content = "Before truncated!"; + while (state.KeepRunning()) { + CreateTestFile(path, content); + + string newContent; + bool ret = SaveStringToFile(path, newContent, true); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + + string loadResult; + ret = LoadStringFromFile(path, loadResult); + RemoveTestFile(path); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + AssertEqual(strcmp(loadResult.c_str(), content.c_str()), 0, + "The two strings, loadResult.c_str() and content.c_str(), did not have the same content as expected.", + state); + } + BENCHMARK_LOGD("FileTest testSaveStringToFile003 end."); +} + +/* + * @tc.name: testSaveStringToFile004 + * @tc.desc: Test writting an empty string to a file in append mode + */ +BENCHMARK_F(BenchmarkFileTest, testSaveStringToFile004)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveStringToFile004 start."); + string path = FILE_PATH; + string content = "Before appended!"; + while (state.KeepRunning()) { + string newContent; + CreateTestFile(path, content); + bool ret = SaveStringToFile(path, newContent, false); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + + string loadResult; + ret = LoadStringFromFile(path, loadResult); + RemoveTestFile(path); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + AssertEqual(strcmp(loadResult.c_str(), content.c_str()), 0, + "The two strings, loadResult.c_str() and content.c_str(), did not have the same content as expected.", + state); + } + BENCHMARK_LOGD("FileTest testSaveStringToFile004 end."); +} + +/* + * @tc.name: testSaveStringToFile005 + * @tc.desc: Test writting a string to a file in append mode + */ +BENCHMARK_F(BenchmarkFileTest, testSaveStringToFile005)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveStringToFile005 start."); + string path = FILE_PATH; + string content = "Before appended!"; + while (state.KeepRunning()) { + CreateTestFile(path, content); + + string newContent = CONTENT_STR; + bool ret = SaveStringToFile(path, newContent, false); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + + string loadResult; + ret = LoadStringFromFile(path, loadResult); + RemoveTestFile(path); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + AssertEqual(loadResult, content + newContent, + "loadResult did not equal content + newContent as expected.", state); + } + BENCHMARK_LOGD("FileTest testSaveStringToFile005 end."); +} + +/* + * @tc.name: testSaveStringToFd001 + * @tc.desc: Test writting an empty string to files with invalid fds + */ +BENCHMARK_F(BenchmarkFileTest, testSaveStringToFd001)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveStringToFd001 start."); + while (state.KeepRunning()) { + string content; + bool ret = SaveStringToFd(0, content); + AssertEqual(ret, false, "ret did not equal false as expected.", state); + ret = SaveStringToFd(-1, content); + AssertEqual(ret, false, "ret did not equal false as expected.", state); + + content = CONTENT_STR; + ret = SaveStringToFd(0, content); + AssertEqual(ret, false, "ret did not equal false as expected.", state); + ret = SaveStringToFd(-1, content); + AssertEqual(ret, false, "ret did not equal false as expected.", state); + } + BENCHMARK_LOGD("FileTest testSaveStringToFd001 end."); +} + +/* + * @tc.name: testSaveStringToFd002 + * @tc.desc: Test writting an empty string to a file specified by its fd + */ +BENCHMARK_F(BenchmarkFileTest, testSaveStringToFd002)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveStringToFd002 start."); + string filename = FILE_PATH; + while (state.KeepRunning()) { + string content; + int fd = open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + bool ret = SaveStringToFd(fd, content); + close(fd); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + + string loadResult; + fd = open(filename.c_str(), O_RDONLY); + ret = LoadStringFromFd(fd, loadResult); + close(fd); + RemoveTestFile(filename); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + AssertEqual(loadResult, "", "loadResult did not equal "" as expected.", state); + } + BENCHMARK_LOGD("FileTest testSaveStringToFd002 end."); +} + +/* + * @tc.name: testSaveStringToFd003 + * @tc.desc: Test loading a non-empty string to a file specified by its fd + */ +BENCHMARK_F(BenchmarkFileTest, testSaveStringToFd003)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveStringToFd003 start."); + string content = CONTENT_STR; + string filename = FILE_PATH; + while (state.KeepRunning()) { + int fd = open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + bool ret = SaveStringToFd(fd, content); + close(fd); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + + string loadResult; + fd = open(filename.c_str(), O_RDONLY); + ret = LoadStringFromFd(fd, loadResult); + close(fd); + RemoveTestFile(filename); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + AssertEqual(loadResult, content, "loadResult did not equal content as expected.", state); + } + BENCHMARK_LOGD("FileTest testSaveStringToFd003 end."); +} + +/* + * @tc.name: testSaveStringToFd004 + * @tc.desc: Test loading a non-empty string to a file without write-authority specified by its fd + */ +BENCHMARK_F(BenchmarkFileTest, testSaveStringToFd004)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveStringToFd004 start."); + string content = CONTENT_STR; + string filename = FILE_PATH; + while (state.KeepRunning()) { + int fd = open(filename.c_str(), O_RDONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + bool ret = SaveStringToFd(fd, content); + close(fd); + AssertEqual(ret, false, "ret did not equal false as expected.", state); + + string loadResult; + fd = open(filename.c_str(), O_RDONLY); + ret = LoadStringFromFd(fd, loadResult); + close(fd); + RemoveTestFile(filename); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + AssertEqual(loadResult, "", "loadResult did not equal "" as expected.", state); + } + BENCHMARK_LOGD("FileTest testSaveStringToFd004 end."); +} + +/* + * @tc.name: testLoadBufferFromFile001 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testLoadBufferFromFile001)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadBufferFromFile001 start."); + string filename = ""; + while (state.KeepRunning()) { + vector buff; + bool ret = LoadBufferFromFile(filename, buff); + AssertFalse((ret), "ret did not equal false as expected.", state); + AssertEqual(0, static_cast(buff.size()), + "static_cast(buff.size()) did not equal 0 as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadBufferFromFile001 end."); +} + +/* + * @tc.name: testLoadBufferFromFile002 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testLoadBufferFromFile002)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadBufferFromFile002 start."); + string filename = FILE_PATH; + while (state.KeepRunning()) { + vector buff; + string content; + CreateTestFile(filename, content); + bool ret = LoadBufferFromFile(filename, buff); + RemoveTestFile(filename); + AssertTrue((ret), "ret did not equal true as expected.", state); + AssertEqual(0, static_cast(buff.size()), + "static_cast(buff.size()) did not equal 0 as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadBufferFromFile002 end."); +} + +/* + * @tc.name: testLoadBufferFromFile003 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testLoadBufferFromFile003)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadBufferFromFile003 start."); + string filename = FILE_PATH; + string content = "TXB"; + while (state.KeepRunning()) { + vector buff; + CreateTestFile(filename, content); + bool ret = LoadBufferFromFile(filename, buff); + RemoveTestFile(filename); + AssertTrue((ret), "ret did not equal true as expected.", state); + AssertEqual(3, (int)buff.size(), "3 did not equal (int)buff.size() as expected.", state); + AssertEqual('T', buff[0], "'T' did not equal buff[0] as expected.", state); + AssertEqual('X', buff[1], "'X' did not equal buff[1] as expected.", state); + AssertEqual('B', buff[2], "'B' did not equal buff[2] as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadBufferFromFile003 end."); +} + +/* + * @tc.name: testLoadBufferFromFile004 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testLoadBufferFromFile004)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testLoadBufferFromFile004 start."); + string content(EXCEEDS_MAXIMUM_LENGTH, 't'); + string filename = FILE_PATH; + while (state.KeepRunning()) { + vector buff; + CreateTestFile(filename, content); + bool ret = LoadBufferFromFile(filename, buff); + RemoveTestFile(filename); + AssertEqual(ret, false, "ret did not equal false as expected.", state); + AssertEqual(0, static_cast(buff.size()), + "static_cast(buff.size()) did not equal 0 as expected.", state); + } + BENCHMARK_LOGD("FileTest testLoadBufferFromFile004 end."); +} + +/* + * @tc.name: testSaveBufferToFile001 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testSaveBufferToFile001)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveBufferToFile001 start."); + string path = FILE_PATH; + string content = "ttxx"; + while (state.KeepRunning()) { + vector buff; + CreateTestFile(path, content); + bool ret = SaveBufferToFile(path, buff, false); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + + string loadResult; + ret = LoadStringFromFile(path, loadResult); + RemoveTestFile(path); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + AssertEqual(loadResult, content, "loadResult did not equal content as expected.", state); + } + BENCHMARK_LOGD("FileTest testSaveBufferToFile001 end."); +} + +/* + * @tc.name: testSaveBufferToFile002 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testSaveBufferToFile002)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveBufferToFile002 start."); + string path = FILE_PATH; + string content = "ttxx"; + while (state.KeepRunning()) { + CreateTestFile(path, content); + + vector newContent = {'x', 'x', 't', 't'}; + bool ret = SaveBufferToFile(path, newContent); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + + string loadResult; + ret = LoadStringFromFile(path, loadResult); + RemoveTestFile(path); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + AssertEqual(loadResult, std::string(newContent.begin(), newContent.end()), + "loadResult did not equal std::string(newContent.begin(), newContent.end()) as expected.", state); + } + BENCHMARK_LOGD("FileTest testSaveBufferToFile002 end."); +} + +/* + * @tc.name: testSaveBufferToFile003 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testSaveBufferToFile003)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testSaveBufferToFile003 start."); + string path = FILE_PATH; + string content = "ttxx"; + while (state.KeepRunning()) { + CreateTestFile(path, content); + + vector newContent = {'x', 'x', 't', 't'}; + bool ret = SaveBufferToFile(path, newContent, false); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + + string loadResult; + ret = LoadStringFromFile(path, loadResult); + RemoveTestFile(path); + AssertEqual(ret, true, "ret did not equal true as expected.", state); + AssertEqual(loadResult, content + std::string(newContent.begin(), newContent.end()), + "loadResult did not equal content + std::string(newContent.begin(), newContent.end()).", state); + } + BENCHMARK_LOGD("FileTest testSaveBufferToFile003 end."); +} + +/* + * @tc.name: testStringExistsInFile001 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testStringExistsInFile001)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testStringExistsInFile001 start."); + string str = "abc"; + string filename = ""; + while (state.KeepRunning()) { + AssertFalse((StringExistsInFile(filename, str, true)), + "StringExistsInFile(filename, str, true) did not equal false as expected.", state); + AssertFalse((str.empty()), "str.empty() did not equal false as expected.", state); + } + BENCHMARK_LOGD("FileTest testStringExistsInFile001 end."); +} + +/* + * @tc.name: testStringExistsInFile002 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testStringExistsInFile002)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testStringExistsInFile002 start."); + string str = NULL_STR; + string filename = FILE_PATH; + string content = "hello world!"; + while (state.KeepRunning()) { + CreateTestFile(filename, content); + AssertFalse((StringExistsInFile(filename, str, true)), + "StringExistsInFile(filename, str, true) did not equal false as expected.", state); + RemoveTestFile(filename); + } + BENCHMARK_LOGD("FileTest testStringExistsInFile002 end."); +} + +/* + * @tc.name: testStringExistsInFile003 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testStringExistsInFile003)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testStringExistsInFile003 start."); + string str = "world"; + string filename = FILE_PATH; + string content = "hello world!"; + while (state.KeepRunning()) { + CreateTestFile(filename, content); + AssertTrue((StringExistsInFile(filename, str, true)), + "StringExistsInFile(filename, str, true) did not equal true as expected.", state); + RemoveTestFile(filename); + } + BENCHMARK_LOGD("FileTest testStringExistsInFile003 end."); +} + +/* + * @tc.name: testStringExistsInFile004 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testStringExistsInFile004)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testStringExistsInFile004 start."); + string str1(MAX_FILE_LENGTH + 1, 't'); + string str2(MAX_FILE_LENGTH, 't'); + string content(MAX_FILE_LENGTH, 't'); + string filename = FILE_PATH; + while (state.KeepRunning()) { + CreateTestFile(filename, content); + AssertFalse((StringExistsInFile(filename, str1, true)), + "StringExistsInFile(filename, str1, true) did not equal false as expected.", state); + AssertTrue((StringExistsInFile(filename, str2, true)), + "StringExistsInFile(filename, str2, true) did not equal true as expected.", state); + RemoveTestFile(filename); + } + BENCHMARK_LOGD("FileTest testStringExistsInFile004 end."); +} + +/* + * @tc.name: testStringExistsInFile005 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testStringExistsInFile005)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testStringExistsInFile005 start."); + string str = "woRld"; + string filename = FILE_PATH; + string content = "hello world!"; + while (state.KeepRunning()) { + CreateTestFile(filename, content); + AssertTrue((StringExistsInFile(filename, str, false)), + "StringExistsInFile(filename, str, false) did not equal true as expected.", state); + AssertFalse((StringExistsInFile(filename, str, true)), + "StringExistsInFile(filename, str, true) did not equal false as expected.", state); + RemoveTestFile(filename); + } + BENCHMARK_LOGD("FileTest testStringExistsInFile005 end."); +} + +/* + * @tc.name: testStringExistsInFile006 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testStringExistsInFile006)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testStringExistsInFile006 start."); + string str1 = "woRld!"; + string str2 = "123"; + string str3 = "llo "; + string str4 = "123 w"; + string str5 = "hi"; + string filename = FILE_PATH; + string content = "Test, hello 123 World!"; + while (state.KeepRunning()) { + CreateTestFile(filename, content); + AssertTrue((StringExistsInFile(filename, str1, false)), + "StringExistsInFile(filename, str1, false) did not equal true as expected.", state); + AssertFalse((StringExistsInFile(filename, str1, true)), + "StringExistsInFile(filename, str1, true) did not equal false as expected.", state); + + AssertTrue((StringExistsInFile(filename, str2, false)), + "StringExistsInFile(filename, str2, false) did not equal true as expected.", state); + AssertTrue((StringExistsInFile(filename, str2, true)), + "StringExistsInFile(filename, str2, true) did not equal true as expected.", state); + + AssertTrue((StringExistsInFile(filename, str3, false)), + "StringExistsInFile(filename, str3, false) did not equal true as expected.", state); + AssertTrue((StringExistsInFile(filename, str3, true)), + "StringExistsInFile(filename, str3, true) did not equal true as expected.", state); + + AssertTrue((StringExistsInFile(filename, str4, false)), + "StringExistsInFile(filename, str4, false) did not equal true as expected.", state); + AssertFalse((StringExistsInFile(filename, str4, true)), + "StringExistsInFile(filename, str4, true) did not equal false as expected.", state); + + AssertFalse((StringExistsInFile(filename, str5, false)), + "StringExistsInFile(filename, str5, false) did not equal false as expected.", state); + AssertFalse((StringExistsInFile(filename, str5, true)), + "StringExistsInFile(filename, str5, true) did not equal false as expected.", state); + RemoveTestFile(filename); + } + BENCHMARK_LOGD("FileTest testStringExistsInFile006 end."); +} + +/* + * @tc.name: testStringExistsInFile007 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testStringExistsInFile007)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testStringExistsInFile007 start."); + string str1 = "is"; + string str2 = "\n\ris"; + string filename = FILE_PATH; + string content = "Test, special string\n\ris ok"; + while (state.KeepRunning()) { + CreateTestFile(filename, content); + AssertTrue((StringExistsInFile(filename, str1, false)), + "StringExistsInFile(filename, str1, false) did not equal true as expected.", state); + AssertTrue((StringExistsInFile(filename, str1, true)), + "StringExistsInFile(filename, str1, true) did not equal true as expected.", state); + + AssertTrue((StringExistsInFile(filename, str2, false)), + "StringExistsInFile(filename, str2, false) did not equal true as expected.", state); + AssertTrue((StringExistsInFile(filename, str2, true)), + "StringExistsInFile(filename, str2, true) did not equal true as expected.", state); + RemoveTestFile(filename); + } + BENCHMARK_LOGD("FileTest testStringExistsInFile007 end."); +} + +/* + * @tc.name: testFileExist001 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testFileExist001)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testFileExist001 start."); + string filepath = "/proc/meminfo"; + string filepath1 = "/proc/meminfo1"; + while (state.KeepRunning()) { + AssertTrue((FileExists(filepath)), "FileExists(filepath) did not equal true as expected.", state); + AssertFalse((FileExists(filepath1)), "FileExists(filepath1) did not equal false as expected.", state); + } + BENCHMARK_LOGD("FileTest testFileExist001 end."); +} + +/* + * @tc.name: testCountStrInFile001 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testCountStrInFile001)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testCountStrInFile001 start."); + string str = "abc"; + string filename = ""; + while (state.KeepRunning()) { + AssertEqual(CountStrInFile(filename, str, true), -1, + "CountStrInFile(filename, str, true) did not equal -1 as expected.", state); + AssertFalse((str.empty()), "str.empty() did not equal false as expected.", state); + } + BENCHMARK_LOGD("FileTest testCountStrInFile001 end."); +} + +/* + * @tc.name: testCountStrInFile002 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testCountStrInFile002)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testCountStrInFile002 start."); + string str = NULL_STR; + string filename = FILE_PATH; + string content = "hello world!"; + while (state.KeepRunning()) { + CreateTestFile(filename, content); + AssertEqual(CountStrInFile(filename, str, true), -1, + "CountStrInFile(filename, str, true) did not equal -1 as expected.", state); + RemoveTestFile(filename); + } + BENCHMARK_LOGD("FileTest testCountStrInFile002 end."); +} + +/* + * @tc.name: testCountStrInFile003 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testCountStrInFile003)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testCountStrInFile003 start."); + string str1(MAX_FILE_LENGTH + 1, 't'); + string str2(MAX_FILE_LENGTH, 't'); + string content(MAX_FILE_LENGTH, 't'); + string filename = FILE_PATH; + while (state.KeepRunning()) { + CreateTestFile(filename, content); + AssertEqual(CountStrInFile(filename, str1, true), 0, + "CountStrInFile(filename, str1, true) did not equal 0 as expected.", state); + AssertEqual(CountStrInFile(filename, str2, true), 1, + "CountStrInFile(filename, str2, true) did not equal 1 as expected.", state); + RemoveTestFile(filename); + } + BENCHMARK_LOGD("FileTest testCountStrInFile003 end."); +} + +/* + * @tc.name: testCountStrInFile004 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testCountStrInFile004)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testCountStrInFile004 start."); + string str1 = "very"; + string str2 = "VERY"; + string str3 = "abc"; + string filename = FILE_PATH; + string content = "This is very very long string for test.\n Very Good,\r VERY HAPPY."; + while (state.KeepRunning()) { + CreateTestFile(filename, content); + AssertEqual(CountStrInFile(filename, str1, true), 2, + "CountStrInFile(filename, str1, true) did not equal 2 as expected.", state); + AssertEqual(CountStrInFile(filename, str1, false), 4, + "CountStrInFile(filename, str1, false) did not equal 4 as expected.", state); + + AssertEqual(CountStrInFile(filename, str2, true), 1, + "CountStrInFile(filename, str2, true) did not equal 1 as expected.", state); + AssertEqual(CountStrInFile(filename, str2, false), 4, + "CountStrInFile(filename, str2, false) did not equal 4 as expected.", state); + + AssertEqual(CountStrInFile(filename, str3, true), 0, + "CountStrInFile(filename, str3, true) did not equal 0 as expected.", state); + RemoveTestFile(filename); + } + BENCHMARK_LOGD("FileTest testCountStrInFile004 end."); +} + +/* + * @tc.name: testCountStrInFile005 + * @tc.desc: singleton template + */ +BENCHMARK_F(BenchmarkFileTest, testCountStrInFile005)(benchmark::State& state) +{ + BENCHMARK_LOGD("FileTest testCountStrInFile005 start."); + string str1 = "aba"; + string filename = FILE_PATH; + string content = "This is abababaBABa."; + while (state.KeepRunning()) { + CreateTestFile(filename, content); + AssertEqual(CountStrInFile(filename, str1, true), 2, + "CountStrInFile(filename, str1, true) did not equal 2 as expected.", state); + AssertEqual(CountStrInFile(filename, str1, false), 3, + "CountStrInFile(filename, str1, false) did not equal 3 as expected.", state); + RemoveTestFile(filename); + } + BENCHMARK_LOGD("FileTest testCountStrInFile005 end."); +} +} // namespace +} // namespace OHOS +// Run the benchmark +BENCHMARK_MAIN(); \ No newline at end of file diff --git a/base/test/benchmarktest/safe_queue_benchmark_test/BUILD.gn b/base/test/benchmarktest/safe_queue_benchmark_test/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..eaa16e832c89cf41ae8032ab93708063d02f7f49 --- /dev/null +++ b/base/test/benchmarktest/safe_queue_benchmark_test/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2023 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. + +import("//build/test.gni") + +module_output_path = "commonlibrary_c_utils/safe_queue" + +ohos_benchmarktest("SafeQueueTest") { + module_out_path = module_output_path + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "safe_queue_benchmark_test.cpp" ] + + deps = [ "//third_party/benchmark:benchmark" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog_base", + ] +} diff --git a/base/test/benchmarktest/safe_queue_benchmark_test/safe_queue_benchmark_test.cpp b/base/test/benchmarktest/safe_queue_benchmark_test/safe_queue_benchmark_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eccd810568745b15c8067fc7427ae153c328dc4f --- /dev/null +++ b/base/test/benchmarktest/safe_queue_benchmark_test/safe_queue_benchmark_test.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2023 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 +#include "safe_queue.h" +#include +#include +#include +#include +#include +#include "../log.h" +#include "../assert.h" +using namespace std; + +namespace OHOS { +namespace { + +const unsigned int QUEUE_SLOTS = 10; +const unsigned int THREAD_NUM = QUEUE_SLOTS + 1; +const int TIME_INCREMENT = 2; +const int SLEEP_FOR_TWO_SECONDS = 2; +const int SLEEP_FOR_THREE_SECONDS = 3; +const int SLEEP_FOR_FOUR_SECONDS = 4; + +class BenchmarkSafeQueue : public benchmark::Fixture { +public: + BenchmarkSafeQueue() + { + Iterations(iterations); + Repetitions(repetitions); + ReportAggregatesOnly(); + } + + ~BenchmarkSafeQueue() override = default; + void SetUp(const ::benchmark::State& state) override + { + } + + void TearDown(const ::benchmark::State& state) override + { + } + +protected: + const int32_t repetitions = 3; + const int32_t iterations = 50; +}; + +class DemoThreadData { +public: + DemoThreadData() + { + putStatus = false; + getStatus = false; + eraseStatus = false; + emptyStatus = false; + } + static SafeQueue shareQueue; + bool putStatus; + bool getStatus; + bool eraseStatus; + bool emptyStatus; + + void Put(int i) + { + shareQueue.Push(i); + putStatus = true; + } + + void Get(int &i) + { + shareQueue.Pop(i); + getStatus = true; + } + + void Erase(int &i) + { + shareQueue.Erase(i); + eraseStatus = true; + } + + void Empty() + { + shareQueue.Empty(); + emptyStatus = true; + } +}; + +SafeQueue DemoThreadData::shareQueue; + +void PutHandleThreadDataTime(DemoThreadData &q, int i, std::chrono::system_clock::time_point absTime) +{ + BENCHMARK_LOGD("SafeQueue PutHandleThreadDataTime is called i:%{public}d .", i); + std::this_thread::sleep_until(absTime); + + q.Put(i); +} + +void GetHandleThreadDataTime(DemoThreadData &q, int i, std::chrono::system_clock::time_point absTime) +{ + BENCHMARK_LOGD("SafeQueue GetHandleThreadDataTime is called i:%{public}d.", i); + std::this_thread::sleep_until(absTime); + int t = 0; + q.Get(t); +} + +void EraseHandleThreadDataTime(DemoThreadData &q, int i, std::chrono::system_clock::time_point absTime) +{ + BENCHMARK_LOGD("SafeQueue EraseHandleThreadDataTime is called i:%{public}d.", i); + std::this_thread::sleep_until(absTime); + + q.Erase(i); +} + +void EmptyHandleThreadDataTime(DemoThreadData &q, std::chrono::system_clock::time_point absTime) +{ + BENCHMARK_LOGD("SafeQueue EmptyHandleThreadDataTime is called."); + std::this_thread::sleep_until(absTime); + + q.Empty(); +} + +class TestThreading { +public: + TestThreading() + { + demoDatas.fill(DemoThreadData()); + } + + void AllThreadPut(std::time_t &timeT) + { + using std::chrono::system_clock; + for (unsigned int i = 0; i < THREAD_NUM; i++) { + threads[i] = std::thread(PutHandleThreadDataTime, + std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT)); + } + } + void AllThreadGet(std::time_t &timeT) + { + using std::chrono::system_clock; + for (unsigned int i = 0; i < THREAD_NUM; i++) { + threads[i] = std::thread(GetHandleThreadDataTime, + std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT)); + } + } + + void AllThreadErase(std::time_t &timeT) + { + using std::chrono::system_clock; + for (unsigned int i = 0; i < THREAD_NUM; i++) { + threads[i] = std::thread(EraseHandleThreadDataTime, + std::ref(demoDatas[i]), i, system_clock::from_time_t(timeT)); + } + } + + void AllThreadEmpty(std::time_t &timeT) + { + using std::chrono::system_clock; + for (unsigned int i = 0; i < THREAD_NUM; i++) { + threads[i] = std::thread(EmptyHandleThreadDataTime, + std::ref(demoDatas[i]), system_clock::from_time_t(timeT)); + } + } + + void GetThreadDatePushedStatus(unsigned int &pushedIn, unsigned int &unpushedIn) + { + pushedIn = 0; + unpushedIn = 0; + for (auto &t : demoDatas) { + if (t.putStatus) { + pushedIn++; + } else { + unpushedIn++; + } + } + BENCHMARK_LOGD("SafeQueue GetThreadDatePushedStatus pIn:%{public}d upIn:%{public}d.", pushedIn, unpushedIn); + } + + void GetThreadDateGetedStatus(unsigned int &getedOut, unsigned int &ungetedOut) + { + BENCHMARK_LOGD("SafeQueue void GetThreadDateGetedStatus is called."); + getedOut = 0; + ungetedOut = 0; + for (auto &t : demoDatas) { + if (t.getStatus) { + getedOut++; + } else { + ungetedOut++; + } + } + BENCHMARK_LOGD("SafeQueue GetThreadDateGetedStatus gOut:%{public}d uOut:%{public}d.", getedOut, ungetedOut); + } + + void GetThreadDateEraseStatus(unsigned int &erase, unsigned int &unErase) + { + erase = 0; + unErase = 0; + for (auto &t : demoDatas) { + if (t.eraseStatus) { + erase++; + } else { + unErase++; + } + } + BENCHMARK_LOGD("SafeQueue GetThreadDateEraseStatus erase:%{public}d unErase:%{public}d.", erase, unErase); + } + + void GetThreadDateEmptyStatus(unsigned int &empty, unsigned int &unEmpty) + { + empty = 0; + unEmpty = 0; + for (auto &t : demoDatas) { + if (t.emptyStatus) { + empty++; + } else { + unEmpty++; + } + } + BENCHMARK_LOGD("SafeQueue GetThreadDateEmptyStatus empty:%{public}d unEmpty:%{public}d.", empty, unEmpty); + } + + void ResetStatus() + { + BENCHMARK_LOGD("SafeQueue void ResetStatus is called."); + for (auto &t : threads) { + t.join(); + } + + DemoThreadData::shareQueue.Clear(); + } + + std::thread threads[THREAD_NUM]; + std::array demoDatas; +}; + +/* +* Feature: SafeBlockQueue +* Function:put +* SubFunction: NA +* FunctionPoints: +* EnvConditions: NA +* CaseDescription: Multiple threads put, one thread gets, all threads finish running normally +*/ +BENCHMARK_F(BenchmarkSafeQueue, testMutilthreadPutAndOneThreadGetOnemptyQueue)(benchmark::State& state) +{ + BENCHMARK_LOGD("SafeQueue testMutilthreadPutAndOneThreadGetOnemptyQueue start."); + while (state.KeepRunning()) { + TestThreading testThread; + using std::chrono::system_clock; + std::time_t timeT = system_clock::to_time_t(system_clock::now()); + timeT += TIME_INCREMENT; + testThread.AllThreadPut(timeT); + + // 1. queue is full and some threads is blocked + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_FOR_THREE_SECONDS)); + AssertTrue((DemoThreadData::shareQueue.Size() > 0), + "DemoThreadData::shareQueue.Size() > 0 did not equal true as expected.", state); + + unsigned int pushedIn = 0; + unsigned int unpushedIn = 0; + + testThread.GetThreadDatePushedStatus(pushedIn, unpushedIn); + AssertEqual(pushedIn, THREAD_NUM, "pushedIn did not equal THREAD_NUM as expected.", state); + + //2. get one out and wait some put in + for (unsigned int i = 0; i < THREAD_NUM; i++) { + int t = 0; + testThread.demoDatas[0].Get(t); + } + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_FOR_TWO_SECONDS)); + // queue is full and some threads is blocked and is not joined + AssertTrue((DemoThreadData::shareQueue.Size() == 0), + "DemoThreadData::shareQueue.Size() == 0 did not equal true as expected.", state); + + // here means all thread end ok or if some operation blocked and the testcase blocked + testThread.ResetStatus(); + } + BENCHMARK_LOGD("SafeQueue testMutilthreadPutAndOneThreadGetOnemptyQueue end."); +} + +/* +* Feature: SafeBlockQueue +* Function:put +* SubFunction: NA +* FunctionPoints: +* EnvConditions: NA +* CaseDescription: Multi-threaded put() and Multi-threaded get() on the empty queue. +* When all threads are waiting to reach a certain +* time-point, everyone run concurrently to see the status of the queue and the state of the thread. +*/ +BENCHMARK_F(BenchmarkSafeQueue, testMutilthreadPutAndGetConcurrently)(benchmark::State& state) +{ + BENCHMARK_LOGD("SafeQueue testMutilthreadPutAndGetConcurrently start."); + while (state.KeepRunning()) { + using std::chrono::system_clock; + std::time_t timeT = system_clock::to_time_t(system_clock::now()); + timeT += TIME_INCREMENT; + + TestThreading putInTestThread; + putInTestThread.AllThreadPut(timeT); + + TestThreading getOutTestThread; + getOutTestThread.AllThreadGet(timeT); + + // 1. queue is full and some threads is blocked + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_FOR_FOUR_SECONDS)); + + unsigned int pushedIn = 0; + unsigned int unpushedIn = 0; + unsigned int getedOut = 0; + unsigned int ungetedOut = 0; + putInTestThread.GetThreadDatePushedStatus(pushedIn, unpushedIn); + getOutTestThread.GetThreadDateGetedStatus(getedOut, ungetedOut); + AssertEqual(pushedIn, THREAD_NUM, "pushedIn did not equal THREAD_NUM as expected.", state); + AssertEqual(getedOut, THREAD_NUM, "getedOut did not equal THREAD_NUM as expected.", state); + + putInTestThread.ResetStatus(); + getOutTestThread.ResetStatus(); + } + BENCHMARK_LOGD("SafeQueue testMutilthreadPutAndGetConcurrently end."); +} + +/* +* Feature: SafeBlockQueue +* Function:put +* SubFunction: NA +* FunctionPoints: +* EnvConditions: NA +* CaseDescription: Multi-threaded put() and Multi-threaded get() on the not empty queue. +* When all threads are waiting to reach a certain +* time-point, everyone run concurrently to see the status of the queue and the state of the thread. +*/ +BENCHMARK_F(BenchmarkSafeQueue, testMutilthreadConcurrentGetAndPopInNotEmptyQueue)(benchmark::State& state) +{ + BENCHMARK_LOGD("SafeQueue testMutilthreadConcurrentGetAndPopInNotEmptyQueue start."); + while (state.KeepRunning()) { + //1. prepare + using std::chrono::system_clock; + std::time_t timeT = system_clock::to_time_t(system_clock::now()); + timeT += TIME_INCREMENT; + + AssertTrue((DemoThreadData::shareQueue.Size() == 0), + "DemoThreadData::shareQueue.Size() == 0 did not equal true as expected.", state); + + int t = 1; + for (unsigned int i = 0; i < THREAD_NUM; i++) { + DemoThreadData::shareQueue.Push(t); + } + + AssertTrue((DemoThreadData::shareQueue.Size() == THREAD_NUM), + "DemoThreadData::shareQueue.Size() == THREAD_NUM did not equal true as expected.", state); + + //2. start thread put in not full queue + TestThreading putInTestThread; + putInTestThread.AllThreadPut(timeT); + + TestThreading getOutTestThread; + getOutTestThread.AllThreadGet(timeT); + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_FOR_THREE_SECONDS)); + AssertTrue((DemoThreadData::shareQueue.Size() == THREAD_NUM), + "DemoThreadData::shareQueue.Size() == THREAD_NUM did not equal true as expected.", state); + + unsigned int getedOut = 0; + unsigned int ungetedOut = 0; + unsigned int pushedIn = 0; + unsigned int unpushedIn = 0; + getOutTestThread.GetThreadDateGetedStatus(getedOut, ungetedOut); + putInTestThread.GetThreadDatePushedStatus(pushedIn, unpushedIn); + AssertEqual(pushedIn, THREAD_NUM, "pushedIn did not equal THREAD_NUM as expected.", state); + AssertEqual(getedOut, THREAD_NUM, "getedOut did not equal THREAD_NUM as expected.", state); + + // 3. reset status + putInTestThread.ResetStatus(); + getOutTestThread.ResetStatus(); + } + BENCHMARK_LOGD("SafeQueue testMutilthreadConcurrentGetAndPopInNotEmptyQueue end."); +} + +/* +* Feature: SafeBlockQueue +* Function:erase empty +* SubFunction: NA +* FunctionPoints: +* EnvConditions: NA +* CaseDescription: Multi-threaded erase() and Multi-threaded empty() on the empty queue. +* When all threads are waiting to reach a certain +* time-point, everyone run concurrently to see the status of the queue and the state of the thread. +*/ +BENCHMARK_F(BenchmarkSafeQueue, testMutilthreadEraseAndEmptyConcurrently)(benchmark::State& state) +{ + BENCHMARK_LOGD("SafeQueue testMutilthreadEraseAndEmptyConcurrently start."); + while (state.KeepRunning()) { + using std::chrono::system_clock; + std::time_t timeT = system_clock::to_time_t(system_clock::now()); + timeT += TIME_INCREMENT; + + TestThreading putThread; + putThread.AllThreadPut(timeT); + + TestThreading eraseThread; + eraseThread.AllThreadErase(timeT); + + TestThreading emptyThread; + emptyThread.AllThreadEmpty(timeT); + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_FOR_FOUR_SECONDS)); + + unsigned int pushedIn = 0; + unsigned int unpushedIn = 0; + unsigned int erase = 0; + unsigned int unerase = 0; + unsigned int empty = 0; + unsigned int unempty = 0; + putThread.GetThreadDatePushedStatus(pushedIn, unpushedIn); + eraseThread.GetThreadDateEraseStatus(erase, unerase); + emptyThread.GetThreadDateEmptyStatus(empty, unempty); + AssertEqual(pushedIn, THREAD_NUM, "pushedIn did not equal THREAD_NUM as expected.", state); + AssertEqual(erase, THREAD_NUM, "erase did not equal THREAD_NUM as expected.", state); + AssertEqual(empty, THREAD_NUM, "empty did not equal THREAD_NUM as expected.", state); + + putThread.ResetStatus(); + eraseThread.ResetStatus(); + emptyThread.ResetStatus(); + } + BENCHMARK_LOGD("SafeQueue testMutilthreadEraseAndEmptyConcurrently end."); +} +} // namespace +} // namespace OHOS +// Run the benchmark +BENCHMARK_MAIN(); \ No newline at end of file