add cpu and application trace profiler

Signed-off-by: chuxuezhe11 <hanjixiao@huawei.com>
This commit is contained in:
chuxuezhe11 2021-09-18 04:58:18 -07:00
parent a9c998f416
commit 7490667f64
1174 changed files with 104141 additions and 67677 deletions

11
OAT.xml Executable file → Normal file
View File

@ -59,9 +59,13 @@ Note:If the text contains special characters, please escape them according to th
<filefilterlist>
<filefilter name="defaultPolicyFilter" desc="Filters for compatibilitylicense header policies">
<filteritem type="filepath" name="device/plugins/memory_plugin/test/utresources/proc/.*" desc="test resource file, no license header"/>
<filteritem type="filepath" name="device/plugins/cpu_plugin/test/resources/.*" desc="test resource file, no license header"/>
<filteritem type="filepath" name="trace_analyzer/prebuilts/mac/trace_streamer.app/Contents/Resources/empty.lproj" desc="auto generated resource file for mac app, no license header"/>
</filefilter>
<filefilter name="copyrightPolicyFilter" desc="Filters for copyright header policies" >
<filteritem type="filepath" name="device/plugins/memory_plugin/test/utresources/proc/.*" desc="test resource file, no copyright header"/>
<filteritem type="filepath" name="device/plugins/cpu_plugin/test/resources/.*" desc="test resource file, no copyright header"/>
<filteritem type="filepath" name="trace_analyzer/prebuilts/mac/trace_streamer.app/Contents/Resources/empty.lproj" desc="auto generated resource file for mac app, no copyright header"/>
</filefilter>
<filefilter name="binaryFileTypePolicyFilter" desc="Filters for binary file policies" >
<filteritem type="filepath" name="host/ohosprofiler/src/main/resources/trace.db" desc="the binary file for host, the file is self-developed"/>
@ -70,6 +74,13 @@ Note:If the text contains special characters, please escape them according to th
<filteritem type="filepath" name="host/ohosprofiler/src/main/resources/.*.png" desc="the png file for host, the file is self-developed"/>
<filteritem type="filepath" name="host/ohosprofiler/src/main/resources/.*.gif" desc="the gif file for host, the file is self-developed"/>
<filteritem type="filepath" name="figures/zh-cn_image_0000001162598155.png" desc="the png file for readme, the file is self-developed"/>
<filteritem type="filepath" name="trace_analyzer/prebuilts/trace_streamer.exe" desc="the trace_streamer.exe executable file, the file is self-developed"/>
<filteritem type="filepath" name="trace_analyzer/test/resource/htrace.bin" desc="the trace_streamer test file, the file is self-developed"/>
<filteritem type="filepath" name="trace_analyzer/prebuilts/windows/trace_streamer.exe" desc="the trace_streamer.exe executable file, the file is self-developed"/>
<filteritem type="filepath" name="trace_analyzer/test/resource/htrace_gold.db" desc="the trace_streamer test file, the file is self-developed"/>
<filteritem type="filepath" name="trace_analyzer/prebuilts/mac/trace_streamer.app/Contents/MacOS/trace_streamer" desc="the trace_streamer executable file for mac, the file is self-developed"/>
<filteritem type="filepath" name="trace_analyzer/test/resource/ut_bytrace_input_thread_gold.db" desc="the trace_streamer test file, the file is self-developed"/>
<filteritem type="filepath" name="trace_analyzer/test/resource/ut_bytrace_input_full_gold.db" desc="the trace_streamer test file, the file is self-developed"/>
</filefilter>
</filefilterlist>
</oatconfig>

View File

@ -14,8 +14,7 @@
OHOS_PROFILER_DIR = get_path_info("..", "abspath")
OHOS_PROFILER_3RDPARTY_DIR = get_path_info("../../../third_party/", "abspath")
OHOS_PROFILER_3RDPARTY_GRPC_DIR = "${OHOS_PROFILER_3RDPARTY_DIR}/grpc"
OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR =
"${OHOS_PROFILER_3RDPARTY_DIR}/protobuf"
OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = "${OHOS_PROFILER_3RDPARTY_DIR}/protobuf"
OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR =
"${OHOS_PROFILER_3RDPARTY_DIR}/googletest"
@ -31,5 +30,7 @@ print("build_l2 =", build_l2)
print("OHOS_PROFILER_DIR = ", OHOS_PROFILER_DIR)
print("OHOS_PROFILER_3RDPARTY_DIR = ", OHOS_PROFILER_3RDPARTY_DIR)
print("OHOS_PROFILER_3RDPARTY_GRPC_DIR = ", OHOS_PROFILER_3RDPARTY_GRPC_DIR)
print("OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = ", OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR)
print("OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR", OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR)
print("OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = ",
OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR)
print("OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR",
OHOS_PROFILER_3RDPARTY_GOOGLETEST_DIR)

5
device/BUILD.gn Executable file → Normal file
View File

@ -17,10 +17,12 @@ group("hiprofiler_targets") {
deps = [
"cmds:hiprofiler_cmd",
"plugins/api:hiprofiler_plugins",
"plugins/bytrace_plugin:bytraceplugin",
"plugins/cpu_plugin:cpudataplugin",
"plugins/cpu_plugin:cpudataplugintest",
"plugins/memory_plugin:memdataplugin",
"services/profiler_service:hiprofilerd",
"services/shared_memory:shared_memory",
"plugins/bytrace_plugin:bytraceplugin",
]
}
@ -29,6 +31,7 @@ group("unittest") {
deps = [
"base/test:unittest",
"plugins/api/test:unittest",
"plugins/cpu_plugin/test:unittest",
"plugins/memory_plugin/test:unittest",
"services/ipc/test:unittest",
"services/plugin_service/test:unittest",

11
device/base/BUILD.gn Executable file → Normal file
View File

@ -21,7 +21,7 @@ config("hiprofiler_test_config") {
cflags += [ "-g" ]
}
if (enable_coverage && current_toolchain == host_toolchain) {
if (enable_coverage) {
cflags += [
# clang coverage options:
"--coverage",
@ -36,19 +36,26 @@ config("hiprofiler_test_config") {
config("hiprofiler_base_config") {
include_dirs = [
"include",
"//utils/native/base/include"
"//utils/native/base/include",
]
}
ohos_source_set("hiprofiler_base") {
sources = [
"src/epoll_event_poller.cpp",
"src/event_notifier.cpp",
"src/i_semaphore.cpp",
"src/posix_semaphore.cpp",
"src/pthread_semaphore.cpp",
"src/schedule_task_manager.cpp",
"src/std_semaphore.cpp",
]
public_configs = [
":hiprofiler_test_config",
":hiprofiler_base_config",
]
public_deps = [ "//utils/native/base:utilsecurec" ]
if (current_toolchain != host_toolchain) {
defines = [ "HAVE_HILOG" ]
if (build_l2) {

0
device/base/config.gni Executable file → Normal file
View File

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2021 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.
*/
#ifndef EPOLL_EVENT_POLLER_H
#define EPOLL_EVENT_POLLER_H
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <unordered_map>
#include <vector>
#include "nocopyable.h"
class EpollEventPoller {
public:
explicit EpollEventPoller(int timeOut);
~EpollEventPoller();
using OnReadableCallback = std::function<void(void)>;
using OnWritableCallback = std::function<void(void)>;
bool AddFileDescriptor(int fd, const OnReadableCallback& onReadable, const OnWritableCallback& onWritable = {});
bool RemoveFileDescriptor(int fd);
bool Init();
bool Start();
bool Stop();
bool Finalize();
private:
enum State {
INITIAL,
INITIED,
STARTED,
};
static constexpr int INVALID_FD = -1;
struct EventContext {
int fd = INVALID_FD;
OnReadableCallback onReadable;
OnWritableCallback onWritable;
};
using EventContextPtr = std::shared_ptr<EventContext>;
void Run();
bool UpdateEvent(int op, const EventContextPtr& ctx);
void HandleEvent(int events, const EventContext& ctx);
bool AddContextLocked(const EventContextPtr& ctx);
bool RemoveContextLocked(const EventContextPtr& ctx);
void OnNotify();
bool Notify(uint64_t value = 1);
private:
std::mutex mutex_;
std::mutex vecMutex_;
std::thread pollThread_;
int timeOut_ = 0;
int epollFd_ = INVALID_FD;
int eventFd_ = INVALID_FD;
std::atomic<int> state_ = INITIAL;
std::atomic<bool> running_ = false;
std::vector<int> fileDescriptors_;
std::unordered_map<int, EventContextPtr> context_;
DISALLOW_COPY_AND_MOVE(EpollEventPoller);
};
#endif // EPOLL_EVENT_POLLER_H

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2021 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.
*/
#ifndef EVENT_NOTIFIER_H
#define EVENT_NOTIFIER_H
#include <cstdint>
#include <memory>
#include "nocopyable.h"
class EventNotifier;
using EventNotifierPtr = std::shared_ptr<EventNotifier>;
class EventNotifier {
public:
enum {
NONBLOCK = (1u << 0),
SEMAPHORE = (1u << 1),
};
static EventNotifierPtr Create(unsigned int initValue = 0, unsigned int mask = 0);
static EventNotifierPtr CreateWithFd(int fd);
int GetFd() const;
bool IsNonBlocking() const;
bool IsSemaphore() const;
uint64_t Take() const;
bool Post(uint64_t value) const;
EventNotifier(unsigned int initValue, unsigned int mask);
EventNotifier(int fd);
~EventNotifier();
private:
int fd_;
int flags_;
DISALLOW_COPY_AND_MOVE(EventNotifier);
};
#endif // EVENT_NOTIFIER_H

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2021 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.
*/
#ifndef OHOS_PROFILER_ABSTRACT_SEMAPHORE_H
#define OHOS_PROFILER_ABSTRACT_SEMAPHORE_H
#include <memory>
#include <string>
class ISemaphore {
public:
virtual ~ISemaphore() {}
virtual bool Wait() = 0;
virtual bool TryWait() = 0;
bool TimedWait(int seconds)
{
return TimedWait(seconds, 0);
}
virtual bool TimedWait(int seconds, int nanoSeconds) = 0;
virtual bool Post() = 0;
virtual unsigned int Value() const = 0;
};
using SemaphorePtr = std::shared_ptr<ISemaphore>;
enum SemaphoreFactoryType : int { STD_SEMAPHORE_FACTORY, POSIX_SEMAPHORE_FACTORY, PTHREAD_SEMAPHORE_FACTORY };
class ISemaphoreFactory {
public:
virtual SemaphorePtr Create(unsigned int value) = 0;
};
ISemaphoreFactory& GetSemaphoreFactory(SemaphoreFactoryType type = STD_SEMAPHORE_FACTORY);
#endif // OHOS_PROFILER_ABSTRACT_SEMAPHORE_H

168
device/base/include/logging.h Executable file → Normal file
View File

@ -13,44 +13,52 @@
* limitations under the License.
*/
#ifndef LOGGING_H
#define LOGGING_H
#ifndef OHOS_PROFILER_LOGGING_H
#define OHOS_PROFILER_LOGGING_H
#undef NDEBUG
#ifndef LOG_TAG
#define LOG_TAG ""
#define LOG_TAG "Hiprofiler"
#endif
#define PROFILER_SUBSYSTEM 0x0000
#ifndef LOG_DOMAIN
#define LOG_DOMAIN PROFILER_SUBSYSTEM
#endif
#ifndef UNUSED_PARAMETER
#define UNUSED_PARAMETER(x) ((void)x)
#endif
#ifdef HAVE_HILOG
#include "hilog/log.h"
#undef LOG_TAG
#define LOG_TAG "Hiprofiler"
#else
#include <string>
#else // HAVE_HILOG
#include <mutex>
#include <string>
#include <securec.h>
#include <sys/syscall.h>
#include <stdarg.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
#include <vector>
static inline long GetTid()
static inline long GetTid(void)
{
return syscall(SYS_gettid);
}
enum {
HILOG_UNKNOWN = 0,
HILOG_DEFAULT,
HILOG_VERBOSE,
HILOG_DEBUG,
HILOG_INFO,
HILOG_WARN,
HILOG_ERROR,
HILOG_FATAL,
HILOG_SILENT,
LOG_UNKNOWN = 0,
LOG_DEFAULT,
LOG_VERBOSE,
LOG_DEBUG,
LOG_INFO,
LOG_WARN,
LOG_ERROR,
LOG_FATAL,
LOG_SILENT,
};
namespace {
@ -66,60 +74,136 @@ static inline std::string GetTimeStr()
localtime_r(&ts.tv_sec, &tmStruct);
size_t used = strftime(timeStr, sizeof(timeStr), "%m-%d %H:%M:%S", &tmStruct);
snprintf_s(&timeStr[used], sizeof(timeStr) - used, sizeof(timeStr) - used - 1, ".%03ld",
ts.tv_nsec / NS_PER_MS_LOG);
ts.tv_nsec / NS_PER_MS_LOG);
return timeStr;
}
typedef const char *ConstCharPtr;
typedef const char* ConstCharPtr;
static inline int HiLogPrintArgs(int prio, ConstCharPtr tag, ConstCharPtr fmt, va_list vargs)
static inline int HiLogPrintArgs(int prio, int domain, ConstCharPtr tag, ConstCharPtr fmt, va_list vargs)
{
static std::mutex mtx;
static std::vector<std::string> prioNames = {"U", " ", "V", "D", "I", "W", "E", "F", "S"};
std::unique_lock<std::mutex> lock(mtx);
int count =
fprintf(stderr, "%s %7d %7ld %5s %s ", GetTimeStr().c_str(), getpid(), GetTid(), prioNames[prio].c_str(), tag);
int count = fprintf(stderr, "%04x %s %7d %7ld %5s %s ", domain, GetTimeStr().c_str(), getpid(), GetTid(),
prioNames[prio].c_str(), tag);
if (count < 0) {
return 0;
}
count += vfprintf(stderr, fmt, vargs);
count += fprintf(stderr, "\n");
fflush(stderr);
return count;
}
static inline int __hilog_log_print(int prio, ConstCharPtr tag, ConstCharPtr fmt, ...)
static inline int HiLogPrint(int type, int prio, int domain, ConstCharPtr tag, ConstCharPtr fmt, ...)
{
int count;
int count = 0;
va_list vargs;
UNUSED_PARAMETER(type);
va_start(vargs, fmt);
count = HiLogPrintArgs(prio, tag, fmt, vargs);
count = HiLogPrintArgs(prio, domain, tag, fmt, vargs);
va_end(vargs);
return count;
}
#define HILOG_DEBUG(LOG_CORE, fmt, ...) __hilog_log_print(HILOG_DEBUG, LOG_TAG, fmt, ##__VA_ARGS__)
#define HILOG_INFO(LOG_CORE, fmt, ...) __hilog_log_print(HILOG_INFO, LOG_TAG, fmt, ##__VA_ARGS__)
#define HILOG_WARN(LOG_CORE, fmt, ...) __hilog_log_print(HILOG_WARN, LOG_TAG, fmt, ##__VA_ARGS__)
#define HILOG_ERROR(LOG_CORE, fmt, ...) __hilog_log_print(HILOG_ERROR, LOG_TAG, fmt, ##__VA_ARGS__)
#ifndef LOG_CORE
#define LOG_CORE 0
#endif
#define HILOG_DEBUG(LOG_CORE, fmt, ...) HiLogPrint(LOG_CORE, LOG_DEBUG, LOG_DOMAIN, LOG_TAG, fmt, ##__VA_ARGS__)
#define HILOG_INFO(LOG_CORE, fmt, ...) HiLogPrint(LOG_CORE, LOG_INFO, LOG_DOMAIN, LOG_TAG, fmt, ##__VA_ARGS__)
#define HILOG_WARN(LOG_CORE, fmt, ...) HiLogPrint(LOG_CORE, LOG_WARN, LOG_DOMAIN, LOG_TAG, fmt, ##__VA_ARGS__)
#define HILOG_ERROR(LOG_CORE, fmt, ...) HiLogPrint(LOG_CORE, LOG_ERROR, LOG_DOMAIN, LOG_TAG, fmt, ##__VA_ARGS__)
#endif // HAVE_HILOG
#ifndef NDEBUG
#include <securec.h>
namespace logging {
inline void StringReplace(std::string& str, const std::string& oldStr, const std::string& newStr)
{
std::string::size_type pos = 0u;
while ((pos = str.find(oldStr, pos)) != std::string::npos) {
str.replace(pos, oldStr.length(), newStr);
pos += newStr.length();
}
}
static inline std::string StringFormat(const char* fmt, ...)
{
va_list vargs;
char buf[1024] = {0};
std::string format(fmt);
StringReplace(format, "%{public}", "%");
va_start(vargs, fmt);
if (vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format.c_str(), vargs) < 0) {
return nullptr;
}
va_end(vargs);
return buf;
}
} // logging
#ifdef HILOG_DEBUG
#undef HILOG_DEBUG
#endif
#ifdef HILOG_INFO
#undef HILOG_INFO
#endif
#ifdef HILOG_WARN
#undef HILOG_WARN
#endif
#ifdef HILOG_ERROR
#undef HILOG_ERROR
#endif
#ifdef HILOG_PRINT
#undef HILOG_PRINT
#endif
#ifdef HAVE_HILOG
#define HILOG_PRINT(type, level, fmt, ...) \
HiLogPrint(type, level, LOG_DOMAIN, LOG_TAG, "%{public}s", logging::StringFormat(fmt, ##__VA_ARGS__).c_str())
#else
#define HILOG_PRINT(type, level, fmt, ...) \
HiLogPrint(type, level, LOG_DOMAIN, LOG_TAG, "%s", logging::StringFormat(fmt, ##__VA_ARGS__).c_str())
#endif
#define HILOG_DEBUG(type, fmt, ...) HILOG_PRINT(type, LOG_DEBUG, fmt, ##__VA_ARGS__)
#define HILOG_INFO(type, fmt, ...) HILOG_PRINT(type, LOG_INFO, fmt, ##__VA_ARGS__)
#define HILOG_WARN(type, fmt, ...) HILOG_PRINT(type, LOG_WARN, fmt, ##__VA_ARGS__)
#define HILOG_ERROR(type, fmt, ...) HILOG_PRINT(type, LOG_ERROR, fmt, ##__VA_ARGS__)
#endif // NDEBUG
#define STD_PTR(K, T) std::K##_ptr<T>
#define CHECK_NOTNULL(ptr, retval, fmt, ...) \
do { \
if (ptr == nullptr) { \
HILOG_WARN(LOG_CORE, "CHECK_NOTNULL(%s) in %s:%d FAILED, " fmt, #ptr, __func__, __LINE__, ##__VA_ARGS__); \
return retval; \
} \
} while (0)
#define NO_RETVAL /* retval */
#define CHECK_TRUE(expr, retval, fmt, ...) \
#define CHECK_NOTNULL(ptr, retval, fmt, ...) \
do { \
if (!(expr)) { \
HILOG_WARN(LOG_CORE, "CHECK_TRUE(%s) in %s:%d FAILED, " fmt, #expr, __func__, __LINE__, ##__VA_ARGS__); \
if (ptr == nullptr) { \
HILOG_WARN(LOG_CORE, "CHECK_NOTNULL(%{public}s) in %{public}s:%{public}d FAILED, " fmt, #ptr, __func__, \
__LINE__, ##__VA_ARGS__); \
return retval; \
} \
} while (0)
#define CHECK_TRUE(expr, retval, fmt, ...) \
do { \
if (!(expr)) { \
HILOG_WARN(LOG_CORE, "CHECK_TRUE(%{public}s) in %{public}s:%{public}d FAILED, " fmt, #expr, __func__, \
__LINE__, ##__VA_ARGS__); \
return retval; \
} \
} while (0)
#define RETURN_IF(expr, retval, fmt, ...) \
do { \
if ((expr)) { \

View File

@ -13,11 +13,12 @@
* limitations under the License.
*/
#ifndef SCHEDULE_TASK_MANAGER_H
#define SCHEDULE_TASK_MANAGER_H
#ifndef OHOS_PROFILER_SCHEDULE_TASK_MANAGER_H
#define OHOS_PROFILER_SCHEDULE_TASK_MANAGER_H
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <functional>
#include <map>
#include <memory>
@ -26,6 +27,7 @@
#include <unordered_map>
#include "logging.h"
#include "nocopyable.h"
class ScheduleTaskManager {
public:
@ -58,7 +60,7 @@ private:
std::function<void(void)> callback;
std::chrono::milliseconds repeatInterval;
std::chrono::milliseconds initialDelay;
TimePoint lastRunTime;
TimePoint nextRunTime;
};
using SharedTask = STD_PTR(shared, Task);
using WeakTask = STD_PTR(weak, Task);
@ -69,15 +71,17 @@ private:
void ScheduleThread();
bool TakeFront(TimePoint& time, WeakTask& task);
WeakTask TakeFront();
private:
mutable std::mutex taskMutex_;
std::condition_variable taskCv_;
std::atomic<bool> runScheduleThread_ = true;
std::multimap<TimePoint, WeakTask> timeMap_;
std::unordered_map<std::string, SharedTask> taskMap_;
std::multimap<TimePoint, WeakTask> timeMap_; // schedule list
std::unordered_map<std::string, SharedTask> taskMap_; // task details
std::thread scheduleThread_;
DISALLOW_COPY_AND_MOVE(ScheduleTaskManager);
};
#endif // !SCHEDULE_TASK_MANAGER_H
#endif // !OHOS_PROFILER_SCHEDULE_TASK_MANAGER_H

View File

@ -0,0 +1,248 @@
/*
* Copyright (c) 2021 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 "epoll_event_poller.h"
#include <algorithm>
#include <cerrno>
#include <csignal>
#include <cstring>
#include <fcntl.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <unistd.h>
#include "logging.h"
EpollEventPoller::EpollEventPoller(int timeOut) : timeOut_(timeOut), epollFd_(INVALID_FD), eventFd_(INVALID_FD) {}
EpollEventPoller::~EpollEventPoller()
{
if (state_ == STARTED) {
HILOG_INFO(LOG_CORE, "need Stop in destructor!");
Stop();
}
if (state_ == INITIED) {
HILOG_INFO(LOG_CORE, "need Finalize in dtor!");
Finalize();
}
}
bool EpollEventPoller::AddFileDescriptor(int fd,
const OnReadableCallback& onReadable,
const OnWritableCallback& onWritable)
{
auto ctx = std::make_shared<EventContext>();
CHECK_NOTNULL(ctx, false, "create EventContext FAILED!");
ctx->fd = fd;
ctx->onReadable = onReadable;
ctx->onWritable = onWritable;
std::unique_lock<std::mutex> lock(mutex_);
CHECK_TRUE(AddContextLocked(ctx), false, "add context for %d failed!", fd);
return Notify();
}
bool EpollEventPoller::RemoveFileDescriptor(int fd)
{
std::unique_lock<std::mutex> lock(mutex_);
auto it = context_.find(fd);
CHECK_TRUE(it != context_.end(), false, "fd %d not found in poll set!", fd);
auto ctx = it->second;
CHECK_NOTNULL(ctx, false, "ctx null!");
CHECK_TRUE(RemoveContextLocked(ctx), false, "remove context for %d failed!", fd);
return Notify();
}
bool EpollEventPoller::AddContextLocked(const EventContextPtr& ctx)
{
context_[ctx->fd] = ctx;
return UpdateEvent(EPOLL_CTL_ADD, ctx);
}
bool EpollEventPoller::RemoveContextLocked(const EventContextPtr& ctx)
{
context_.erase(ctx->fd);
CHECK_TRUE(UpdateEvent(EPOLL_CTL_DEL, ctx), false, "update fd %d ctx FAILED!", ctx->fd);
return true;
}
static std::string EpollOpName(int op)
{
if (op == EPOLL_CTL_ADD) {
return "ADD";
}
if (op == EPOLL_CTL_DEL) {
return "DEL";
}
if (op == EPOLL_CTL_MOD) {
return "MOD";
}
return "";
}
bool EpollEventPoller::UpdateEvent(int op, const EventContextPtr& ctx)
{
struct epoll_event event = {};
if (ctx->onReadable) {
event.events |= EPOLLIN;
}
if (ctx->onWritable) {
event.events |= EPOLLOUT;
}
event.data.ptr = ctx.get();
std::string name = EpollOpName(op).c_str();
HILOG_DEBUG(LOG_CORE, "poll set %s %d %x start!", name.c_str(), ctx->fd, event.events);
int retval = epoll_ctl(epollFd_, op, ctx->fd, &event);
CHECK_TRUE(retval == 0, false, "epoll_ctl %s failed, %s", name.c_str(), strerror(errno));
HILOG_DEBUG(LOG_CORE, "poll set %s %d %x done!", name.c_str(), ctx->fd, event.events);
return true;
}
void EpollEventPoller::Run()
{
pthread_setname_np(pthread_self(), "EventPoller");
std::vector<struct epoll_event> eventVec;
while (running_) {
{
std::unique_lock<std::mutex> lock(mutex_);
eventVec.resize(context_.size());
}
int retval = TEMP_FAILURE_RETRY(epoll_wait(epollFd_, eventVec.data(), eventVec.size(), timeOut_));
CHECK_TRUE(retval >= 0, NO_RETVAL, "epoll_wait failed, %s!", strerror(errno));
if (retval == 0) {
HILOG_INFO(LOG_CORE, "epoll_wait %dms timeout!", timeOut_);
continue;
}
for (int i = 0; i < retval; i++) {
auto ctx = reinterpret_cast<EventContext*>(eventVec[i].data.ptr);
if (ctx != nullptr) {
HandleEvent(eventVec[i].events, *ctx);
}
}
}
}
void EpollEventPoller::HandleEvent(int events, const EventContext& ctx)
{
if (events & EPOLLIN) {
if (ctx.onReadable) {
ctx.onReadable();
}
} else if (events & EPOLLOUT) {
if (ctx.onWritable) {
ctx.onWritable();
}
}
}
void EpollEventPoller::OnNotify()
{
uint64_t value = 0;
CHECK_TRUE(read(eventFd_, &value, sizeof(value)) == sizeof(value), NO_RETVAL, "read eventfd FAILED!");
HILOG_DEBUG(LOG_CORE, "OnNotify %llu done!", static_cast<unsigned long long>(value));
}
bool EpollEventPoller::Notify(uint64_t value)
{
auto nbytes = write(eventFd_, &value, sizeof(value));
CHECK_TRUE(static_cast<size_t>(nbytes) == sizeof(value), false, "write eventfd FAILED!");
HILOG_DEBUG(LOG_CORE, "Notify %llu done!", static_cast<unsigned long long>(value));
return true;
}
bool EpollEventPoller::Init()
{
HILOG_INFO(LOG_CORE, "Init %d", state_.load());
CHECK_TRUE(state_ == INITIAL, false, "Init FAIL %d", state_.load());
int epollFd = epoll_create1(EPOLL_CLOEXEC);
CHECK_TRUE(epollFd >= 0, false, "epoll_create failed, %s!", strerror(errno));
fileDescriptors_.push_back(epollFd);
int eventFd = eventfd(0, O_CLOEXEC | O_NONBLOCK);
CHECK_TRUE(eventFd >= 0, false, "create event fd failed, %s", strerror(errno));
fileDescriptors_.push_back(eventFd);
auto eventFdCtx = std::make_shared<EventContext>();
CHECK_NOTNULL(eventFdCtx, false, "create EventContext failed!");
eventFdCtx->fd = eventFd;
eventFdCtx->onReadable = std::bind(&EpollEventPoller::OnNotify, this);
std::unique_lock<std::mutex> lock(mutex_);
epollFd_ = epollFd;
eventFd_ = eventFd;
AddContextLocked(eventFdCtx);
HILOG_INFO(LOG_CORE, "EpollEventPoller::Init %d done!", state_.load());
state_ = INITIED;
return true;
}
bool EpollEventPoller::Finalize()
{
if (state_ == STARTED) {
HILOG_INFO(LOG_CORE, "need Stop in Finalize!");
Stop();
}
HILOG_INFO(LOG_CORE, "Finalize %d", state_.load());
CHECK_TRUE(state_ == INITIED, false, "Finalize FAIL %d", state_.load());
std::unique_lock<std::mutex> lock(mutex_);
std::vector<EventContextPtr> contextVec;
for (auto& ctxPair : context_) {
contextVec.push_back(ctxPair.second);
}
for (auto ctxPtr : contextVec) {
HILOG_DEBUG(LOG_CORE, "remove context for %d", ctxPtr->fd);
RemoveContextLocked(ctxPtr);
}
for (int fd : fileDescriptors_) {
close(fd);
}
fileDescriptors_.clear();
epollFd_ = INVALID_FD;
eventFd_ = INVALID_FD;
state_ = INITIAL;
return true;
}
bool EpollEventPoller::Start()
{
HILOG_INFO(LOG_CORE, "%s %d", __func__, state_.load());
CHECK_TRUE(state_ == INITIED, false, "Start FAIL %d", state_.load());
running_ = true;
pollThread_ = std::thread(&EpollEventPoller::Run, this);
state_ = STARTED;
return true;
}
bool EpollEventPoller::Stop()
{
CHECK_TRUE(state_ == STARTED, false, "Stop FAIL %d", state_.load());
running_ = false;
Notify();
if (pollThread_.joinable()) {
pollThread_.join();
}
state_ = INITIED;
return true;
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2021 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 "event_notifier.h"
#include <cerrno>
#include <climits>
#include <cstring>
#include <fcntl.h>
#include <sys/eventfd.h>
#include <unistd.h>
#include "logging.h"
#ifndef EFD_SEMAPHORE
#define EFD_SEMAPHORE 1
#endif
EventNotifierPtr EventNotifier::Create(unsigned int initValue, unsigned int mask)
{
return std::make_shared<EventNotifier>(initValue, mask);
}
EventNotifierPtr EventNotifier::CreateWithFd(int fd)
{
return std::make_shared<EventNotifier>(fd);
}
EventNotifier::EventNotifier(unsigned int initValue, unsigned int mask) : fd_(-1), flags_(O_CLOEXEC)
{
if (mask & NONBLOCK) {
flags_ |= O_NONBLOCK;
}
if (mask & SEMAPHORE) {
flags_ |= EFD_SEMAPHORE;
}
fd_ = eventfd(initValue, flags_);
CHECK_TRUE(fd_ >= 0, NO_RETVAL, "create eventfd FAILED, %s", strerror(errno));
HILOG_DEBUG(LOG_CORE, "EventNotifier create eventfd %d done!", fd_);
}
EventNotifier::EventNotifier(int fd) : fd_(fd)
{
int flags = fcntl(fd_, F_GETFL);
CHECK_TRUE(flags >= 0, NO_RETVAL, "get flags of fd %d FAILED, %s", fd, strerror(errno));
HILOG_DEBUG(LOG_CORE, "EventNotifier bind eventfd %d done!", fd_);
}
EventNotifier::~EventNotifier()
{
HILOG_DEBUG(LOG_CORE, "EventNotifier close eventfd %d", fd_);
close(fd_);
}
int EventNotifier::GetFd() const
{
return fd_;
}
bool EventNotifier::IsNonBlocking() const
{
return flags_ & O_NONBLOCK;
}
bool EventNotifier::IsSemaphore() const
{
return flags_ & EFD_SEMAPHORE;
}
uint64_t EventNotifier::Take() const
{
uint64_t value = UINT64_MAX;
int retval = TEMP_FAILURE_RETRY(read(fd_, &value, sizeof(value)));
CHECK_TRUE(retval == sizeof(value), false, "read value from eventfd %d failed, %s!", fd_, strerror(errno));
return value;
}
bool EventNotifier::Post(uint64_t value) const
{
int retval = TEMP_FAILURE_RETRY(write(fd_, &value, sizeof(value)));
CHECK_TRUE(retval == sizeof(value), false, "write value to eventfd %d failed, %s!", fd_, strerror(errno));
return true;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2021 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 "i_semaphore.h"
#include "posix_semaphore.h"
#include "pthread_semaphore.h"
#include "std_semaphore.h"
ISemaphoreFactory& GetSemaphoreFactory(SemaphoreFactoryType type)
{
static StdSemaphoreFactory stdFactory;
if (type == STD_SEMAPHORE_FACTORY) {
return stdFactory;
} else if (type == POSIX_SEMAPHORE_FACTORY) {
static PosixSemaphoreFactory posxiFactory;
return posxiFactory;
} else if (type == PTHREAD_SEMAPHORE_FACTORY) {
// static PthreadSemaphoreFactory pthreadFactory;
return stdFactory;
}
return stdFactory;
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2021 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 "posix_semaphore.h"
#include <ctime>
namespace {
constexpr int NS_PER_SEC = 1000 * 1000 * 1000;
}
PosixSemaphore::PosixSemaphore(unsigned int value)
{
sem_init(&sem_, 0, value);
}
PosixSemaphore::~PosixSemaphore()
{
sem_destroy(&sem_);
}
bool PosixSemaphore::Wait()
{
return sem_wait(&sem_) == 0;
}
bool PosixSemaphore::TryWait()
{
return sem_trywait(&sem_) == 0;
}
bool PosixSemaphore::TimedWait(int seconds, int nanoSeconds)
{
struct timespec ts = { 0, 0 };
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += seconds;
ts.tv_nsec += nanoSeconds;
ts.tv_sec += ts.tv_nsec / NS_PER_SEC;
ts.tv_nsec %= NS_PER_SEC;
return sem_timedwait(&sem_, &ts) == 0;
}
bool PosixSemaphore::Post()
{
return sem_post(&sem_) == 0;
}
unsigned PosixSemaphore::Value() const
{
int value = 0;
sem_getvalue(&sem_, &value);
return value;
}
SemaphorePtr PosixSemaphoreFactory::Create(unsigned int value)
{
return std::make_shared<PosixSemaphore>(value);
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2021 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.
*/
#ifndef OHOS_PROFILER_POSIX_SEMAPHORE_H
#define OHOS_PROFILER_POSIX_SEMAPHORE_H
#include <memory>
#include <semaphore.h>
#include "i_semaphore.h"
class PosixSemaphore : public ISemaphore {
public:
explicit PosixSemaphore(unsigned int value);
~PosixSemaphore();
bool Wait() override;
bool TryWait() override;
bool TimedWait(int seconds, int nanoSeconds) override;
bool Post() override;
unsigned Value() const override;
private:
mutable sem_t sem_ = {};
};
class PosixSemaphoreFactory : public ISemaphoreFactory {
public:
SemaphorePtr Create(unsigned int value) override;
};
#endif // OHOS_PROFILER_POSIX_SEMAPHORE_H

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2021 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 "pthread_semaphore.h"
#include <ctime>
namespace {
constexpr int NS_PER_SEC = 1000 * 1000 * 1000;
}
PthreadSemaphore::PthreadSemaphore(unsigned int value) : value_(value)
{
pthread_mutex_init(&mutex_, nullptr);
pthread_cond_init(&cond_, nullptr);
}
PthreadSemaphore::~PthreadSemaphore()
{
pthread_cond_destroy(&cond_);
pthread_mutex_destroy(&mutex_);
}
bool PthreadSemaphore::Wait()
{
pthread_mutex_lock(&mutex_);
while (value_ == 0) {
pthread_cond_wait(&cond_, &mutex_);
}
--value_;
pthread_mutex_unlock(&mutex_);
return true;
}
bool PthreadSemaphore::TryWait()
{
pthread_mutex_lock(&mutex_);
bool retval = TryWaitLocked();
pthread_mutex_unlock(&mutex_);
return retval;
}
bool PthreadSemaphore::TimedWait(int seconds, int nanoSeconds)
{
pthread_mutex_lock(&mutex_);
if (value_) {
struct timespec ts = { 0, 0 };
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += seconds;
ts.tv_nsec += nanoSeconds;
ts.tv_sec += ts.tv_nsec / NS_PER_SEC;
ts.tv_nsec %= NS_PER_SEC;
pthread_cond_timedwait(&cond_, &mutex_, &ts);
}
bool retval = TryWaitLocked();
pthread_mutex_unlock(&mutex_);
return retval;
}
bool PthreadSemaphore::TryWaitLocked()
{
if (value_ == 0) {
return false;
}
--value_;
return true;
}
bool PthreadSemaphore::Post()
{
pthread_mutex_lock(&mutex_);
++value_;
pthread_mutex_unlock(&mutex_);
pthread_cond_broadcast(&cond_);
return true;
}
unsigned int PthreadSemaphore::Value() const
{
pthread_mutex_lock(&mutex_);
unsigned int val = value_;
pthread_mutex_unlock(&mutex_);
return val;
}
SemaphorePtr PthreadSemaphoreFactory::Create(unsigned int value)
{
return std::make_shared<PthreadSemaphore>(value);
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2021 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.
*/
#ifndef OHOS_PROFILER_PTHREAD_SEMAPHORE_H
#define OHOS_PROFILER_PTHREAD_SEMAPHORE_H
#include <memory>
#include <pthread.h>
#include "i_semaphore.h"
class PthreadSemaphore : public ISemaphore {
public:
explicit PthreadSemaphore(unsigned int value);
~PthreadSemaphore();
bool Wait() override;
bool TryWait() override;
bool TimedWait(int seconds, int nanoSeconds) override;
bool Post() override;
unsigned int Value() const override;
private:
bool TryWaitLocked();
mutable pthread_mutex_t mutex_ {};
mutable pthread_cond_t cond_ {};
volatile unsigned int value_ = 0;
};
class PthreadSemaphoreFactory : public ISemaphoreFactory {
public:
SemaphorePtr Create(unsigned int value) override;
};
#endif // OHOS_PROFILER_PTHREAD_SEMAPHORE_H

View File

@ -18,6 +18,7 @@
#include <ctime>
#include <iostream>
#include <mutex>
#include <pthread.h>
#include "logging.h"
#include "securec.h"
@ -36,22 +37,27 @@ ScheduleTaskManager& ScheduleTaskManager::GetInstance()
ScheduleTaskManager::ScheduleTaskManager()
{
runScheduleThread_ = true;
scheduleThread_ = std::thread(&ScheduleTaskManager::ScheduleThread, this);
}
ScheduleTaskManager::~ScheduleTaskManager()
{
Shutdown();
if (scheduleThread_.joinable()) {
scheduleThread_.join();
}
}
void ScheduleTaskManager::Shutdown()
{
std::lock_guard<std::mutex> guard(taskMutex_);
runScheduleThread_ = false;
bool expect = true;
if (!runScheduleThread_.compare_exchange_strong(expect, false)) {
return;
}
taskCv_.notify_one();
if (scheduleThread_.joinable()) {
scheduleThread_.join();
}
taskMap_.clear();
timeMap_.clear();
}
std::chrono::milliseconds ScheduleTaskManager::NormalizeInterval(std::chrono::milliseconds interval)
@ -77,12 +83,14 @@ bool ScheduleTaskManager::ScheduleTask(const std::string& name,
const std::chrono::milliseconds& repeatInterval,
std::chrono::milliseconds initialDelay)
{
auto currentTime = Clock::now();
auto task = std::make_shared<Task>();
task->name = name;
task->callback = callback;
task->initialDelay = initialDelay;
task->repeatInterval = NormalizeInterval(repeatInterval);
task->nextRunTime = currentTime + initialDelay;
std::lock_guard<std::mutex> guard(taskMutex_);
if (taskMap_.count(name) > 0) {
@ -91,26 +99,28 @@ bool ScheduleTaskManager::ScheduleTask(const std::string& name,
}
taskMap_[name] = task;
timeMap_.insert(std::make_pair(Clock::now() + initialDelay, task));
timeMap_.insert(std::make_pair(task->nextRunTime, task));
taskCv_.notify_one();
HILOG_DEBUG(LOG_CORE, "add schedule %s, total: %zu ", name.c_str(), taskMap_.size());
HILOG_DEBUG(LOG_CORE, "add schedule %s done, total: %zu", name.c_str(), taskMap_.size());
return true;
}
bool ScheduleTaskManager::UnscheduleTask(const std::string& name)
{
HILOG_DEBUG(LOG_CORE, "del schedule %s, total: %zu", name.c_str(), taskMap_.size());
std::unique_lock<std::mutex> lck(taskMutex_);
HILOG_DEBUG(LOG_CORE, "del schedule %s start, total: %zu", name.c_str(), taskMap_.size());
auto it = taskMap_.find(name);
if (it != taskMap_.end()) {
taskMap_.erase(it);
HILOG_DEBUG(LOG_CORE, "del schedule %s done, remain: %zu", name.c_str(), taskMap_.size());
return true;
}
HILOG_DEBUG(LOG_CORE, "del schedule %s pass, total: %zu", name.c_str(), taskMap_.size());
return false;
}
bool ScheduleTaskManager::TakeFront(TimePoint& time, WeakTask& task)
ScheduleTaskManager::WeakTask ScheduleTaskManager::TakeFront()
{
std::unique_lock<std::mutex> lck(taskMutex_);
@ -120,54 +130,68 @@ bool ScheduleTaskManager::TakeFront(TimePoint& time, WeakTask& task)
}
if (!runScheduleThread_) {
return false;
return {};
}
time = timeMap_.begin()->first;
task = timeMap_.begin()->second;
auto task = timeMap_.begin()->second;
timeMap_.erase(timeMap_.begin());
return true;
return task;
}
void ScheduleTaskManager::DumpTask(const SharedTask& task)
{
if (task) {
long msecs = std::chrono::duration_cast<ms>(task->lastRunTime.time_since_epoch()).count();
HILOG_DEBUG(LOG_CORE, "{name = %s, interval = %lld, delay = %lld, lastRun = %ld}",
task->name.c_str(), task->repeatInterval.count(), task->initialDelay.count(), msecs);
long msecs = std::chrono::duration_cast<ms>(task->nextRunTime.time_since_epoch()).count();
HILOG_DEBUG(LOG_CORE,
"{name = %{public}s, interval = %{public}lld, delay = %{public}lld, nextRunTime = %{public}ld}",
task->name.c_str(), task->repeatInterval.count(), task->initialDelay.count(), msecs);
}
}
void ScheduleTaskManager::ScheduleThread()
{
while (true) {
pthread_setname_np(pthread_self(), "SchedTaskMgr");
while (runScheduleThread_) {
// take front task from task queue
TimePoint targetTime;
WeakTask targetTask;
if (!TakeFront(targetTime, targetTask)) {
WeakTask weakTask = TakeFront();
if (!runScheduleThread_) {
break;
}
TimePoint targetTime;
{
auto taskTime = weakTask.lock(); // promote to shared_ptr
if (!taskTime) {
// task cancelled with UnschduleTask or not a repeat task
continue;
}
targetTime = taskTime->nextRunTime;
}
// delay to target time
auto currentTime = Clock::now();
if (targetTime >= currentTime) {
std::this_thread::sleep_for(targetTime - currentTime);
}
// promote to shared_ptr
auto task = targetTask.lock();
DumpTask(task);
auto taskRepeat = weakTask.lock();
if (!taskRepeat) {
// task cancelled with UnschduleTask or not a repeat task
continue;
}
if (task != nullptr) {
// call task callback
task->callback();
task->lastRunTime = currentTime;
// call task callback
taskRepeat->callback();
taskRepeat->nextRunTime = targetTime + taskRepeat->repeatInterval;
// re-insert task to map if it's a repeat task
if (task->repeatInterval.count() != 0) {
std::unique_lock<std::mutex> guard(taskMutex_);
timeMap_.insert(std::make_pair(targetTime + task->repeatInterval, task));
}
if (taskRepeat->repeatInterval.count() != 0) {
// repeat task, re-insert task to timeMap
std::unique_lock<std::mutex> guard(taskMutex_);
timeMap_.insert(std::make_pair(taskRepeat->nextRunTime, taskRepeat));
} else {
// not a repeat task.
std::unique_lock<std::mutex> guard(taskMutex_);
taskMap_.erase(taskRepeat->name);
}
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2021 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 "std_semaphore.h"
StdSemaphore::StdSemaphore(unsigned int value) : value_(value) {}
StdSemaphore::~StdSemaphore() {}
bool StdSemaphore::Wait()
{
std::unique_lock<std::mutex> lock(mutex_);
while (value_ == 0) {
condVar_.wait(lock);
}
--value_;
return true;
}
bool StdSemaphore::TryWait()
{
std::unique_lock<std::mutex> lock(mutex_);
return TryWaitLocked();
}
bool StdSemaphore::TryWaitLocked()
{
if (value_ == 0) {
return false;
}
--value_;
return true;
}
bool StdSemaphore::TimedWait(int seconds, int nanoSeconds)
{
std::unique_lock<std::mutex> lock(mutex_);
if (value_ == 0) {
auto timePoint = std::chrono::steady_clock::now();
timePoint += std::chrono::seconds(seconds);
timePoint += std::chrono::nanoseconds(nanoSeconds);
condVar_.wait_until(lock, timePoint);
}
return TryWaitLocked();
}
bool StdSemaphore::Post()
{
{
std::unique_lock<std::mutex> lock(mutex_);
++value_;
}
condVar_.notify_all();
return true;
}
unsigned StdSemaphore::Value() const
{
return value_;
}
SemaphorePtr StdSemaphoreFactory::Create(unsigned int value)
{
return std::make_shared<StdSemaphore>(value);
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2021 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.
*/
#ifndef OHOS_PROFILER_STD_SEMAPHORE_H
#define OHOS_PROFILER_STD_SEMAPHORE_H
#include <condition_variable>
#include <mutex>
#include "i_semaphore.h"
#include "nocopyable.h"
class StdSemaphore : public ISemaphore {
public:
explicit StdSemaphore(unsigned int value);
~StdSemaphore();
bool Wait() override;
bool TryWait() override;
bool TimedWait(int seconds, int nanoSeconds) override;
bool Post() override;
unsigned int Value() const override;
private:
bool TryWaitLocked();
mutable std::mutex mutex_;
std::condition_variable condVar_;
volatile unsigned int value_;
DISALLOW_COPY_AND_MOVE(StdSemaphore);
};
class StdSemaphoreFactory : public ISemaphoreFactory {
public:
SemaphorePtr Create(unsigned int value) override;
};
#endif // OHOS_PROFILER_STD_SEMAPHORE_H

18
device/base/test/BUILD.gn Executable file → Normal file
View File

@ -16,7 +16,7 @@ import("../../base/config.gni")
module_output_path = "${OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH}/device"
config("module_private_config") {
visibility = [":*"]
visibility = [ ":*" ]
if (current_toolchain != host_toolchain) {
defines = [ "HAVE_HILOG" ]
}
@ -28,26 +28,22 @@ ohos_unittest("hiprofiler_base_ut") {
"../:hiprofiler_base",
"//third_party/googletest:gtest",
]
configs = [
":module_private_config"
]
configs = [ ":module_private_config" ]
include_dirs = [ "//third_party/googletest/googletest/include/gtest" ]
sources = [
"unittest/epoll_event_poller_test.cpp",
"unittest/schedule_task_manager_test.cpp",
"unittest/semaphore_test.cpp",
]
cflags = [
"-Wno-inconsistent-missing-override",
"-Dprivate=public", #allow test code access private members
]
external_deps = [
"hiviewdfx_hilog_native:libhilog",
"-Dprivate=public", #allow test code access private members
]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
}
group("unittest") {
testonly = true
deps = [
":hiprofiler_base_ut",
]
deps = [ ":hiprofiler_base_ut" ]
}

View File

@ -0,0 +1,217 @@
/*
* Copyright (c) 2021 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 <atomic>
#include <chrono>
#include <cinttypes>
#include <fcntl.h>
#include <hwext/gtest-ext.h>
#include <hwext/gtest-tag.h>
#include <memory>
#include <sys/eventfd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <thread>
#include <unistd.h>
#include "epoll_event_poller.h"
#include "event_notifier.h"
#include "logging.h"
using namespace testing::ext;
namespace {
constexpr int DEFAULT_POLL_INTERVAL = 1000;
}
namespace {
class EpollEventPollerTest : public testing::Test {
protected:
std::unique_ptr<EpollEventPoller> eventPoller;
void SetUp() override
{
eventPoller = std::make_unique<EpollEventPoller>(DEFAULT_POLL_INTERVAL);
}
void TearDown() override {}
};
/**
* @tc.name: EpollEventPollerTest
* @tc.desc: CtorDtor.
* @tc.type: FUNC
*/
HWTEST_F(EpollEventPollerTest, CtorDtor, TestSize.Level1)
{
ASSERT_NE(eventPoller, nullptr);
}
/**
* @tc.name: EpollEventPollerTest
* @tc.desc: InitFinalize.
* @tc.type: FUNC
*/
HWTEST_F(EpollEventPollerTest, InitFinalize, TestSize.Level1)
{
ASSERT_NE(eventPoller, nullptr);
HILOG_INFO(LOG_CORE, "EpollEventPollerTest.InitFinalize start!");
EXPECT_TRUE(eventPoller->Init());
EXPECT_TRUE(eventPoller->Finalize());
}
/**
* @tc.name: EpollEventPollerTest
* @tc.desc: InitFinalize.
* @tc.type: FUNC
*/
HWTEST_F(EpollEventPollerTest, InitOnly, TestSize.Level1)
{
ASSERT_NE(eventPoller, nullptr);
HILOG_INFO(LOG_CORE, "EpollEventPollerTest.InitOnly start!");
EXPECT_TRUE(eventPoller->Init());
}
/**
* @tc.name: EpollEventPollerTest
* @tc.desc: Init 2 times Finalize 1 time.
* @tc.type: FUNC
*/
HWTEST_F(EpollEventPollerTest, Init2Finalize1, TestSize.Level1)
{
ASSERT_NE(eventPoller, nullptr);
HILOG_INFO(LOG_CORE, "EpollEventPollerTest.Init2Finalize1 start!");
EXPECT_TRUE(eventPoller->Init());
EXPECT_FALSE(eventPoller->Init());
EXPECT_TRUE(eventPoller->Finalize());
}
/**
* @tc.name: EpollEventPollerTest
* @tc.desc: InitStartStopFinalize.
* @tc.type: FUNC
*/
HWTEST_F(EpollEventPollerTest, InitStartStopFinalize, TestSize.Level1)
{
ASSERT_NE(eventPoller, nullptr);
HILOG_INFO(LOG_CORE, "EpollEventPollerTest.InitStartStopFinalize start!");
EXPECT_TRUE(eventPoller->Init());
EXPECT_TRUE(eventPoller->Start());
EXPECT_TRUE(eventPoller->Stop());
EXPECT_TRUE(eventPoller->Finalize());
}
/**
* @tc.name: EpollEventPollerTest
* @tc.desc: InitStartStop.
* @tc.type: FUNC
*/
HWTEST_F(EpollEventPollerTest, InitStartStop, TestSize.Level1)
{
ASSERT_NE(eventPoller, nullptr);
HILOG_INFO(LOG_CORE, "EpollEventPollerTest.InitStartStop start!");
EXPECT_TRUE(eventPoller->Init());
EXPECT_TRUE(eventPoller->Start());
EXPECT_TRUE(eventPoller->Stop());
}
/**
* @tc.name: EpollEventPollerTest
* @tc.desc: InitStart.
* @tc.type: FUNC
*/
HWTEST_F(EpollEventPollerTest, InitStart, TestSize.Level1)
{
ASSERT_NE(eventPoller, nullptr);
HILOG_INFO(LOG_CORE, "EpollEventPollerTest.InitStart start!");
EXPECT_TRUE(eventPoller->Init());
EXPECT_TRUE(eventPoller->Start());
}
/**
* @tc.name: EpollEventPollerTest
* @tc.desc: AddFd.
* @tc.type: FUNC
*/
HWTEST_F(EpollEventPollerTest, InitStartAddFd, TestSize.Level1)
{
ASSERT_NE(eventPoller, nullptr);
HILOG_INFO(LOG_CORE, "EpollEventPollerTest.InitStartAddFd start!");
EXPECT_TRUE(eventPoller->Init());
EXPECT_TRUE(eventPoller->Start());
int eventFd = eventfd(0, O_CLOEXEC | O_NONBLOCK);
uint64_t readValue = 0;
auto onReadable = [&readValue, &eventFd]() {
read(eventFd, &readValue, sizeof(readValue));
HILOG_INFO(LOG_CORE, "EpollEventPollerTest.InitStartAddFd read %" PRIu64, readValue);
};
EXPECT_TRUE(eventPoller->AddFileDescriptor(eventFd, onReadable));
uint64_t writeValue = 1234;
int writeSize = sizeof(writeValue); // run -t UT -ss developtools
EXPECT_EQ(write(eventFd, &writeValue, writeSize), writeSize);
std::this_thread::yield();
usleep(15 * 1000);
EXPECT_EQ(readValue, writeValue);
EXPECT_TRUE(eventPoller->Stop());
EXPECT_TRUE(eventPoller->Finalize());
close(eventFd);
}
HWTEST_F(EpollEventPollerTest, InitStartAddEventFd, TestSize.Level1)
{
ASSERT_NE(eventPoller, nullptr);
HILOG_INFO(LOG_CORE, "EpollEventPollerTest.InitStartAddFd start!");
EXPECT_TRUE(eventPoller->Init());
EXPECT_TRUE(eventPoller->Start());
auto notifier = EventNotifier::Create(0, EventNotifier::NONBLOCK);
uint64_t readValue = 0;
auto onReadable = [&readValue, &notifier]() {
readValue = notifier->Take();
HILOG_INFO(LOG_CORE, "EpollEventPollerTest.InitStartAddFd read %" PRIu64, readValue);
};
EXPECT_TRUE(eventPoller->AddFileDescriptor(notifier->GetFd(), onReadable));
uint64_t writeValue = 1234;
pid_t pid = fork();
EXPECT_GE(pid, 0);
if (pid == 0) {
int evFd = dup(notifier->GetFd());
auto evNotifier = EventNotifier::CreateWithFd(evFd);
evNotifier->Post(writeValue);
_exit(0);
} else if (pid > 0) {
int wstatus = 0;
waitpid(pid, &wstatus, 0);
}
std::this_thread::yield();
usleep(15 * 1000);
EXPECT_EQ(readValue, writeValue);
EXPECT_TRUE(eventPoller->Stop());
EXPECT_TRUE(eventPoller->Finalize());
}
} // namespace

View File

@ -16,6 +16,7 @@
#include <chrono>
#include <hwext/gtest-ext.h>
#include <hwext/gtest-tag.h>
#include <sys/time.h>
#include <thread>
#include "schedule_task_manager.h"
@ -26,7 +27,10 @@ namespace {
class ScheduleTaskManagerTest : public testing::Test {
protected:
static void SetUpTestCase() {}
static void TearDownTestCase() {}
static void TearDownTestCase()
{
ScheduleTaskManager::GetInstance().Shutdown();
}
};
/**
@ -55,6 +59,8 @@ HWTEST_F(ScheduleTaskManagerTest, ScheduleTaskOneshot, TestSize.Level1)
std::this_thread::sleep_for(initalDelay + initalDelay);
EXPECT_EQ(count.load(), 1);
scheduleTaskManager.Shutdown();
}
/**
@ -72,15 +78,27 @@ HWTEST_F(ScheduleTaskManagerTest, ScheduleTaskRepeated, TestSize.Level1)
ScheduleTaskManager scheduleTaskManager;
EXPECT_TRUE(scheduleTaskManager.ScheduleTask(
"task-2", [&]() { count++; }, repeatInterval, initalDelay));
"task-2",
[&]() {
count++;
struct timeval tv;
gettimeofday(&tv, nullptr);
printf("[%ld.%06ld] count: %d\n", tv.tv_sec, tv.tv_usec, count.load());
},
repeatInterval, initalDelay));
int expected = 0;
std::this_thread::sleep_for(initalDelay + initalDelay);
for (int i = 0; i < cnt; i++) {
expected++;
struct timeval tv = { 0, 0 };
gettimeofday(&tv, nullptr);
printf("[%ld.%06ld] expected: %d\n", tv.tv_sec, tv.tv_usec, expected);
EXPECT_EQ(count.load(), expected);
std::this_thread::sleep_for(repeatInterval);
}
scheduleTaskManager.Shutdown();
}
/**
@ -99,19 +117,27 @@ HWTEST_F(ScheduleTaskManagerTest, UnscheduleTask, TestSize.Level1)
ScheduleTaskManager scheduleTaskManager;
EXPECT_TRUE(scheduleTaskManager.ScheduleTask(
taskName, [&]() { count++; }, repeatInterval));
taskName,
[&]() {
count++;
struct timeval tv;
gettimeofday(&tv, nullptr);
printf("[%ld.%06ld] count: %d\n", tv.tv_sec, tv.tv_usec, count.load());
},
repeatInterval));
int expected = 0;
std::this_thread::sleep_for(initalDelay);
for (int i = 0; i < cnt; i++) {
std::this_thread::sleep_for(repeatInterval);
expected++;
struct timeval tv = { 0, 0 };
gettimeofday(&tv, nullptr);
printf("[%ld.%06ld] expected: %d\n", tv.tv_sec, tv.tv_usec, expected);
EXPECT_EQ(count.load(), expected);
}
EXPECT_TRUE(scheduleTaskManager.UnscheduleTask(taskName));
scheduleTaskManager.Shutdown();
EXPECT_EQ(count.load(), expected);
}
} // namespace

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2021 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 <atomic>
#include <chrono>
#include <hwext/gtest-ext.h>
#include <hwext/gtest-tag.h>
#include <thread>
#include "i_semaphore.h"
namespace {
using namespace testing::ext;
class SemaphoreTest : public testing::Test {
protected:
static void SetUpTestCase() {}
static void TearDownTestCase() {}
};
/**
* @tc.name: SemaphoreTest
* @tc.desc: CtorDtor.
* @tc.type: FUNC
*/
HWTEST_F(SemaphoreTest, CtorDtor, TestSize.Level1)
{
auto semaphore = GetSemaphoreFactory().Create(0);
EXPECT_NE(semaphore, nullptr);
}
/**
* @tc.name: SemaphoreTest
* @tc.desc: Wait.
* @tc.type: FUNC
*/
HWTEST_F(SemaphoreTest, Wait, TestSize.Level1)
{
auto semaphore = GetSemaphoreFactory().Create(1);
ASSERT_NE(semaphore, nullptr);
EXPECT_TRUE(semaphore->Wait());
}
/**
* @tc.name: SemaphoreTest
* @tc.desc: Post.
* @tc.type: FUNC
*/
HWTEST_F(SemaphoreTest, Post, TestSize.Level1)
{
auto semaphore = GetSemaphoreFactory().Create(0);
ASSERT_NE(semaphore, nullptr);
EXPECT_TRUE(semaphore->Post());
}
/**
* @tc.name: SemaphoreTest
* @tc.desc: Post.
* @tc.type: FUNC
*/
HWTEST_F(SemaphoreTest, WaitPost, TestSize.Level1)
{
auto readySem = GetSemaphoreFactory().Create(0);
auto finishSem = GetSemaphoreFactory().Create(0);
ASSERT_NE(readySem, nullptr);
ASSERT_NE(finishSem, nullptr);
auto done = std::make_shared<bool>(false);
ASSERT_NE(done, nullptr);
std::thread bgThread([=]() {
readySem->Wait();
*done = true;
finishSem->Post();
});
EXPECT_TRUE(readySem->Post());
EXPECT_TRUE(finishSem->Wait());
EXPECT_TRUE(*done);
bgThread.join();
}
} // namespace

4
device/cmds/BUILD.gn Executable file → Normal file
View File

@ -24,9 +24,7 @@ ohos_source_set("command_line") {
include_dirs = [ "include" ]
}
ohos_executable("hiprofiler_cmd") {
sources = [
"src/main.cpp",
]
sources = [ "src/main.cpp" ]
include_dirs = [ "include" ]
deps = [
":command_line",

0
device/cmds/include/command_param.h Executable file → Normal file
View File

0
device/cmds/include/command_param_switch.h Executable file → Normal file
View File

0
device/cmds/include/command_param_text.h Executable file → Normal file
View File

2
device/cmds/src/command_param.cpp Executable file → Normal file
View File

@ -28,5 +28,5 @@ void CommandParam::AddFilter(const std::string& filterName)
bool CommandParam::IsInFilter(const std::string& filterName)
{
return std::any_of(paramFilter_.begin(), paramFilter_.end(),
[filterName](std::string s) { return s == filterName; });
[filterName](const std::string& s) { return s == filterName; });
}

0
device/cmds/src/command_param_switch.cpp Executable file → Normal file
View File

0
device/cmds/src/command_param_text.cpp Executable file → Normal file
View File

View File

@ -89,21 +89,30 @@ std::unique_ptr<CreateSessionRequest> MakeCreateRequest(const std::string& confi
const std::string& keepSecond, const std::string& outputFileName)
{
auto request = std::make_unique<CreateSessionRequest>();
auto sessionConfig = request->mutable_session_config();
if (!request || !sessionConfig) {
if (!request) {
return nullptr;
}
std::string content = ReadConfigContent(configFileName);
if (content.empty()) {
printf("config file empty!");
return nullptr;
}
printf("================================\n");
printf("CONFIG: read %zu bytes from %s:\n%s", content.size(), configFileName.c_str(), content.c_str());
if (!google::protobuf::TextFormat::ParseFromString(content, request.get())) {
printf("config file [%s] format error!\n", configFileName.c_str());
printf("config file [%s] parse FAILED!\n", configFileName.c_str());
return nullptr;
}
request->set_request_id(0);
auto sessionConfig = request->mutable_session_config();
if (!sessionConfig) {
return nullptr;
}
request->set_request_id(1);
printf("--------------------------------\n");
printf("keepSecond: %s,\noutputFileName: %s\n", keepSecond.c_str(), outputFileName.c_str());
if (!keepSecond.empty()) {
int ks = std::stoi(keepSecond);
if (ks > 0) {
@ -113,6 +122,15 @@ std::unique_ptr<CreateSessionRequest> MakeCreateRequest(const std::string& confi
if (!outputFileName.empty()) {
sessionConfig->set_result_file(outputFileName);
}
content.clear();
if (!google::protobuf::TextFormat::PrintToString(*request.get(), &content)) {
printf("config message format FAILED!\n");
return nullptr;
}
printf("--------------------------------\n");
printf("CONFIG: final config content:\n%s", content.c_str());
printf("================================\n");
return request;
}
@ -196,9 +214,6 @@ int main(int argc, char* argv[])
bool isHelp = false;
pCmdLine->AddParamSwitch("--help", "-h", isHelp, "make some help");
bool isBackground = false;
pCmdLine->AddParamSwitch("--background", "-d", isBackground, "run in background");
std::vector<std::string> argvVector;
for (int i = 0; i < argc; i++) {
argvVector.push_back(argv[i]);
@ -207,7 +222,7 @@ int main(int argc, char* argv[])
pCmdLine->PrintHelp();
exit(0);
}
if (isGetGrpcAddr) {
if (isGetGrpcAddr) { // handle get port
auto profilerStub = GetProfilerServiceStub();
if (profilerStub == nullptr) {
printf("FAIL\nGet profiler service stub failed!\n");
@ -229,13 +244,13 @@ int main(int argc, char* argv[])
return 0;
}
if (!configFileName.empty()) {
// Read the configFileNameconvert to protobuf objectstructure 'CreateSession',Send 'StartSession' command to
// profilerd
if (StartSession(configFileName, traceKeepSecond, outputFileName)) {
printf("OK\ntracing...\n");
}
exit(0);
if (configFileName.empty()) { // normal case
printf("FAIL\nconfig file argument must sepcified!");
return 1;
}
// Read the configFileName, call 'CreateSession', and 'StartSession'
if (StartSession(configFileName, traceKeepSecond, outputFileName)) {
printf("OK\ntracing...\n");
}
return 0;

0
device/format-code.sh Executable file → Normal file
View File

546
device/ohos_test.xml Normal file
View File

@ -0,0 +1,546 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<configuration ver="2.0">
<target name="profiler_service_ut">
<preparer>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="plugin_service_module_test">
<preparer>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="plugin_service_ut">
<preparer>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="shared_memory_ut">
<preparer>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="ipc_ut">
<preparer>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="memdataplugin_ut">
<preparer>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/1/oom_score_adj -> /data/local/tmp/utresources/proc/1/" src="res"/>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/1/smaps -> /data/local/tmp/utresources/proc/1/" src="res"/>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/1/status -> /data/local/tmp/utresources/proc/1/" src="res"/>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/2/oom_score_adj -> /data/local/tmp/utresources/proc/2/" src="res"/>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/2/smaps -> /data/local/tmp/utresources/proc/2/" src="res"/>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/2/status -> /data/local/tmp/utresources/proc/2/" src="res"/>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/11/oom_score_adj -> /data/local/tmp/utresources/proc/11/" src="res"/>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/11/smaps -> /data/local/tmp/utresources/proc/11/" src="res"/>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/11/status -> /data/local/tmp/utresources/proc/11/" src="res"/>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/cmdline -> /data/local/tmp/utresources/proc/" src="res"/>
<option name="push" value="plugins/memory_plugin/test/utresources/proc/meminfo -> /data/local/tmp/utresources/proc/" src="res"/>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="hiprofiler_plugins_ut">
<preparer>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/hiprofilerd -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="plugin_module_api_ut">
<preparer>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="cpudataplugin_ut">
<preparer>
<option name="push" value="plugins/cpu_plugin/test/resources/proc/stat -> /data/local/tmp/resources/proc/" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/proc/1872/stat -> /data/local/tmp/resources/proc/1872/" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/proc/1872/task/1872/stat -> /data/local/tmp/resources/proc/1872/task/1872/" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/proc/1872/task/1965/stat -> /data/local/tmp/resources/proc/1872/task/1965/" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/proc/1872/task/1966/stat -> /data/local/tmp/resources/proc/1872/task/1966/" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/proc/1872/task/1967/stat -> /data/local/tmp/resources/proc/1872/task/1967/" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/proc/1872/task/1968/stat -> /data/local/tmp/resources/proc/1872/task/1968/" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/proc/1872/task/1995/stat -> /data/local/tmp/resources/proc/1872/task/1995/" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/proc/1872/task/1996/stat -> /data/local/tmp/resources/proc/1872/task/1996/" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu0/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu0/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu0/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_cur_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu1/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_max_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu1/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_min_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu1/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu2/cpufreq/cpuinfo_cur_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu2/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu2/cpufreq/cpuinfo_max_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu2/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu2/cpufreq/cpuinfo_min_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu2/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu3/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_max_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu3/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_min_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu3/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu4/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_max_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu4/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_min_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu4/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu5/cpufreq/cpuinfo_cur_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu5/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu5/cpufreq/cpuinfo_max_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu5/cpufreq" src="res"/>
<option name="push" value="plugins/cpu_plugin/test/resources/sys/devices/system/cpu/cpu5/cpufreq/cpuinfo_min_freq -> /data/local/tmp/resources/sys/devices/system/cpu/cpu5/cpufreq" src="res"/>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcpudataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libdiskiodataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="diskiodataplugin_ut">
<preparer>
<option name="push" value="plugins/diskio_plugin/test/resources/proc/vmstat -> /data/local/tmp/resources/proc/" src="res"/>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcpudataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libdiskiodataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="networkplugin_ut">
<preparer>
<option name="push" value="plugins/network_plugin/test/utresources/begin/proc/9553/status -> /data/local/tmp/utresources/begin/proc/9553/" src="res"/>
<option name="push" value="plugins/network_plugin/test/utresources/begin/proc/net/xt_qtaguid/stats -> /data/local/tmp/utresources/begin/proc/net/xt_qtaguid/" src="res"/>
<option name="push" value="plugins/network_plugin/test/utresources/end/proc/9553/status -> /data/local/tmp/utresources/end/proc/9553/" src="res"/>
<option name="push" value="plugins/network_plugin/test/utresources/end/proc/net/xt_qtaguid/stats -> /data/local/tmp/utresources/end/proc/net/xt_qtaguid/" src="res"/>
<option name="push" value="developtools/developtools/libabsl_base.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_civil_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_cord.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_debugging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_demangle_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_dynamic_annotations.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_graphcycles_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_int128.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_log_severity.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_malloc_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_raw_logging_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_spinlock_wait.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_stacktrace.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_status.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_statusor.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_str_format_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_strings_internal.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_symbolize.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_synchronization.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_throw_delegate.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libabsl_time_zone.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libaddress_sorting.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libares.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libbytraceplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcpudataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libcrypto.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libdiskiodataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgpr.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpc.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libgrpcxx.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libhiperf_call_plugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotobuf_lite.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libprotoc_lib.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libre2.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/./libmemdataplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libshared_memory.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/libssl.z.so -> /system/lib/" src="out"/>
</preparer>
</target>
<target name="agent_ut">
<preparer>
<option name="push" value="developtools/developtools/libagentplugin.z.so -> /system/lib/" src="out"/>
<option name="push" value="developtools/developtools/hiprofilerd -> /system/lib/" src="out"/>
</preparer>
</target>
</configuration>

15
device/plugins/api/BUILD.gn Executable file → Normal file
View File

@ -35,12 +35,13 @@ ohos_source_set("plugins_sources") {
"../../base/include/",
"${OHOS_PROFILER_DIR}/interfaces/kits",
"//utils/native/base/include",
"//third_party/boringssl/src/include",
]
sources = [
"src/buffer_writer.cpp",
"src/command_poller.cpp",
"src/plugin_module.cpp",
"src/plugin_manager.cpp",
"src/plugin_module.cpp",
"src/plugin_watcher.cpp",
"src/writer_adapter.cpp",
]
@ -49,7 +50,9 @@ ohos_source_set("plugins_sources") {
"${OHOS_PROFILER_DIR}/protos/services:plugin_services_proto",
"${OHOS_PROFILER_DIR}/protos/services:service_types_proto",
"../../base:hiprofiler_base",
"//utils/native/base:utilsbase",
"//third_party/boringssl:crypto",
"//third_party/boringssl:crypto",
"//utils/native/base:utilsecurec",
]
public_configs = [ ":hiprofiler_plugins_config" ]
if (current_toolchain != host_toolchain) {
@ -62,12 +65,8 @@ ohos_source_set("plugins_sources") {
}
ohos_executable("hiprofiler_plugins") {
deps = [
":plugins_sources",
]
sources = [
"src/main.cpp",
]
deps = [ ":plugins_sources" ]
sources = [ "src/main.cpp" ]
if (current_toolchain != host_toolchain) {
defines = [ "HAVE_HILOG" ]
if (build_l2) {

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2021 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.
*/
#ifndef PLUGIN_INTERFACE_H
#define PLUGIN_INTERFACE_H
#include <map>
#include <memory>
#include <string>
#include <vector>
class ProfilerPluginConfig;
class PluginResult;
class CommandPoller;
class ManagerInterface {
public:
virtual ~ManagerInterface() {}
virtual bool LoadPlugin(const std::string& pluginPath) = 0;
virtual bool UnloadPlugin(const std::string& pluginPath) = 0;
virtual bool UnloadPlugin(const uint32_t pluginId) = 0;
// CommandPoller will call the following four interfaces after receiving the command
virtual bool CreatePluginSession(const std::vector<ProfilerPluginConfig>& config) = 0;
virtual bool DestroyPluginSession(const std::vector<uint32_t>& pluginIds) = 0;
virtual bool StartPluginSession(const std::vector<uint32_t>& pluginIds,
const std::vector<ProfilerPluginConfig>& config) = 0;
virtual bool StopPluginSession(const std::vector<uint32_t>& pluginIds) = 0;
virtual bool CreateWriter(std::string pluginName, uint32_t bufferSize, int smbFd, int eventFd) = 0;
virtual bool ResetWriter(uint32_t pluginId) = 0;
virtual void SetCommandPoller(const std::shared_ptr<CommandPoller>& p) = 0;
};
#endif // PLUGIN_INTERFACE_H

0
device/plugins/api/include/writer.h Executable file → Normal file
View File

View File

@ -15,50 +15,89 @@
#include "buffer_writer.h"
#include "command_poller.h"
#include "common_types.pb.h"
#include "logging.h"
#include "plugin_service_types.pb.h"
#include "share_memory_allocator.h"
#include <algorithm>
#include <cinttypes>
#include <thread>
#include <unistd.h>
BufferWriter::BufferWriter(std::string name,
uint32_t size,
int fd,
const CommandPollerPtr& cp,
int smbFd,
int eventFd,
uint32_t pluginId)
: pluginName_(name)
{
HILOG_DEBUG(LOG_CORE, "CreateMemoryBlockRemote %s %d %d", name.c_str(), size, fd);
shareMemoryBlock_ = ShareMemoryAllocator::GetInstance().CreateMemoryBlockRemote(name, size, fd);
HILOG_INFO(LOG_CORE, "BufferWriter %s %d [%d] [%d]", name.c_str(), size, smbFd, eventFd);
shareMemoryBlock_ = ShareMemoryAllocator::GetInstance().CreateMemoryBlockRemote(name, size, smbFd);
if (shareMemoryBlock_ == nullptr) {
HILOG_DEBUG(LOG_CORE, "shareMemoryBlock_ == nullptr=");
HILOG_DEBUG(LOG_CORE, "create shareMemoryBlock_ failed!");
}
commandPoller_ = cp;
eventNotifier_ = EventNotifier::CreateWithFd(eventFd);
pluginId_ = pluginId;
lastFlushTime_ = std::chrono::steady_clock::now();
}
BufferWriter::~BufferWriter()
{
HILOG_DEBUG(LOG_CORE, "BufferWriter destroy eventfd = %d!", eventNotifier_ ? eventNotifier_->GetFd() : -1);
eventNotifier_ = nullptr;
ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockRemote(pluginName_);
}
void BufferWriter::Report() const
{
HILOG_DEBUG(LOG_CORE, "BufferWriter stats B: %" PRIu64 ", P: %d, W:%" PRIu64 ", F: %d",
bytesCount_.load(), bytesPending_.load(), writeCount_.load(), flushCount_.load());
}
void BufferWriter::DoStats(long bytes)
{
++writeCount_;
bytesCount_ += bytes;
bytesPending_ += bytes;
}
long BufferWriter::Write(const void* data, size_t size)
{
if (shareMemoryBlock_ == nullptr) {
if (shareMemoryBlock_ == nullptr || data == nullptr || size == 0) {
return false;
}
HILOG_DEBUG(LOG_CORE, "BufferWriter Write %zu", size);
return shareMemoryBlock_->PutRaw(reinterpret_cast<const int8_t*>(data), static_cast<uint32_t>(size));
ProfilerPluginData pluginData;
pluginData.set_name(pluginName_);
pluginData.set_status(0);
pluginData.set_data(data, size);
struct timespec ts = { 0, 0 };
clock_gettime(CLOCK_REALTIME, &ts);
pluginData.set_clock_id(ProfilerPluginData::CLOCKID_REALTIME);
pluginData.set_tv_sec(ts.tv_sec);
pluginData.set_tv_nsec(ts.tv_nsec);
DoStats(pluginData.ByteSizeLong());
return shareMemoryBlock_->PutMessage(pluginData);
}
bool BufferWriter::WriteProtobuf(google::protobuf::Message& pmsg)
bool BufferWriter::WriteMessage(const google::protobuf::Message& pmsg)
{
if (shareMemoryBlock_ == nullptr) {
return false;
}
HILOG_DEBUG(LOG_CORE, "BufferWriter Write %zu", pmsg.ByteSizeLong());
return shareMemoryBlock_->PutProtobuf(pmsg);
DoStats(pmsg.ByteSizeLong());
return shareMemoryBlock_->PutMessage(pmsg);
}
bool BufferWriter::Flush()
{
++flushCount_;
eventNotifier_->Post(flushCount_.load());
lastFlushTime_ = std::chrono::steady_clock::now();
bytesPending_ = 0;
return true;
}

25
device/plugins/api/src/buffer_writer.h Executable file → Normal file
View File

@ -16,7 +16,9 @@
#ifndef BUFFER_WRITER_H
#define BUFFER_WRITER_H
#include <atomic>
#include <memory>
#include "event_notifier.h"
#include "plugin_module_api.h"
#include "share_memory_allocator.h"
#include "writer.h"
@ -27,18 +29,33 @@ using CommandPollerPtr = STD_PTR(shared, CommandPoller);
class BufferWriter : public Writer {
public:
BufferWriter(std::string name, uint32_t size, int fd, const CommandPollerPtr& cp, uint32_t pluginId);
BufferWriter(std::string name,
uint32_t size,
int smbFd,
int eventFd,
uint32_t pluginId);
~BufferWriter();
long Write(const void* data, size_t size) override;
bool Flush() override;
bool WriteProtobuf(google::protobuf::Message& pmsg);
bool WriteMessage(const google::protobuf::Message& pmsg);
private:
void DoStats(long bytes);
void Report() const;
private:
std::string pluginName_;
std::shared_ptr<ShareMemoryBlock> shareMemoryBlock_;
CommandPollerPtr commandPoller_;
uint32_t pluginId_;
EventNotifierPtr eventNotifier_ = nullptr;
std::chrono::steady_clock::time_point lastFlushTime_;
std::atomic<uint64_t> bytesCount_ = 0;
std::atomic<uint32_t> bytesPending_ = 0;
std::atomic<uint64_t> writeCount_ = 0;
std::atomic<uint32_t> flushCount_ = 0;
uint32_t pluginId_ = 0;
};
using BufferWriterPtr = STD_PTR(shared, BufferWriter);
#endif // BUFFER_WRITER_H

View File

@ -17,8 +17,14 @@
#include "plugin_manager.h"
#include "socket_context.h"
CommandPoller::CommandPoller(const PluginManagerPtr& p)
: requestIdAutoIncrease_(1), pluginManager_(p)
#include <fcntl.h>
#include <unistd.h>
namespace {
constexpr int SLEEP_TIME = 10;
}
CommandPoller::CommandPoller(const ManagerInterfacePtr& p) : requestIdAutoIncrease_(1), pluginManager_(p)
{
Connect(DEFAULT_UNIX_SOCKET_PATH);
}
@ -45,13 +51,17 @@ bool CommandPoller::OnCreateSessionCmd(const CreateSessionCmd& cmd, SocketContex
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd FAIL 1");
return false;
}
int fd = -1;
int smbFd = -1;
int eventFd = -1;
if (bufferSize != 0) {
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd bufferSize = %d", bufferSize);
fd = context.ReceiveFileDiscriptor();
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd fd = %d", fd);
smbFd = context.ReceiveFileDiscriptor();
eventFd = context.ReceiveFileDiscriptor();
int flags = fcntl(eventFd, F_GETFL);
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd smbFd = %d, eventFd = %d", smbFd, eventFd);
HILOG_DEBUG(LOG_CORE, "eventFd flags = %X", flags);
}
if (!pluginManager->CreateWriter(config.name(), bufferSize, fd)) {
if (!pluginManager->CreateWriter(config.name(), bufferSize, smbFd, eventFd)) {
HILOG_DEBUG(LOG_CORE, "OnCreateSessionCmd CreateWriter FAIL");
return false;
}
@ -128,7 +138,7 @@ bool CommandPoller::OnStopSessionCmd(const StopSessionCmd& cmd) const
bool CommandPoller::OnGetCommandResponse(SocketContext& context, ::GetCommandResponse& response)
{
HILOG_DEBUG(LOG_CORE, "OnGetCommandResponse");
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME));
NotifyResultRequest nrr;
nrr.set_request_id(1);
nrr.set_command_id(response.command_id());

8
device/plugins/api/src/command_poller.h Executable file → Normal file
View File

@ -18,7 +18,7 @@
#include <memory>
class PluginManager;
class ManagerInterface;
class CreateSessionCmd;
class DestroySessionCmd;
class StartSessionCmd;
@ -27,11 +27,11 @@ class StopSessionCmd;
#include "logging.h"
#include "plugin_service.ipc.h"
using PluginManagerPtr = STD_PTR(shared, PluginManager);
using ManagerInterfacePtr = STD_PTR(shared, ManagerInterface);
class CommandPoller final : public IPluginServiceClient {
public:
explicit CommandPoller(const PluginManagerPtr& p);
explicit CommandPoller(const ManagerInterfacePtr& p);
~CommandPoller();
bool OnCreateSessionCmd(const CreateSessionCmd& cmd, SocketContext& context) const;
@ -46,7 +46,7 @@ protected:
private:
uint32_t requestIdAutoIncrease_;
std::weak_ptr<PluginManager> pluginManager_;
std::weak_ptr<ManagerInterface> pluginManager_;
};
#endif // !COMMAND_POLLER_H

11
device/plugins/api/src/main.cpp Executable file → Normal file
View File

@ -47,8 +47,15 @@ int main(int argc, char* argv[])
pluginManager->SetCommandPoller(commandPoller);
PluginWatcher watcher(pluginManager);
watcher.ScanPlugins(pluginDir);
watcher.WatchPlugins(pluginDir);
if (!watcher.ScanPlugins(pluginDir)) {
HILOG_DEBUG(LOG_CORE, "Scan pluginDir:%s failed!", DEFAULT_PLUGIN_PATH);
return 0;
}
if (!watcher.WatchPlugins(pluginDir)) {
HILOG_DEBUG(LOG_CORE, "Monitor pluginDir:%s failed!", DEFAULT_PLUGIN_PATH);
return 0;
}
while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_ONE_SECOND));

View File

@ -15,12 +15,49 @@
#include "plugin_manager.h"
#include <cstdio>
#include <functional>
#include <iomanip>
#include "command_poller.h"
#include "logging.h"
#include "openssl/sha.h"
#include "plugin_service_types.pb.h"
namespace {
constexpr int FILE_READ_CHUNK_SIZE = 4096;
constexpr char HEX_CHARS[] = "0123456789abcdef";
#define HHB(v) (((v) & 0xF0) >> 4)
#define LHB(v) ((v) & 0x0F)
std::string ComputeFileSha256(const std::string& path)
{
uint8_t out[SHA256_DIGEST_LENGTH];
uint8_t buffer[FILE_READ_CHUNK_SIZE];
SHA256_CTX sha;
SHA256_Init(&sha);
size_t nbytes = 0;
std::unique_ptr<FILE, decltype(fclose)*> fptr(fopen(path.c_str(), "rb"), fclose);
while ((nbytes = fread(buffer, 1, sizeof(buffer), fptr.get())) > 0) {
SHA256_Update(&sha, buffer, nbytes);
}
SHA256_Final(out, &sha);
std::string result;
result.reserve(SHA256_DIGEST_LENGTH + SHA256_DIGEST_LENGTH);
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
result.push_back(HEX_CHARS[HHB(out[i])]);
result.push_back(HEX_CHARS[LHB(out[i])]);
}
HILOG_DEBUG(LOG_CORE, "SHA256(%s): %s", path.c_str(), result.c_str());
return result;
}
} // namespace
PluginManager::~PluginManager() {}
void PluginManager::SetCommandPoller(const CommandPollerPtr& p)
@ -30,7 +67,7 @@ void PluginManager::SetCommandPoller(const CommandPollerPtr& p)
bool PluginManager::AddPlugin(const std::string& pluginPath)
{
PluginModuleInfo info;
PluginModuleInfo info = {0};
if (pluginIds_.find(pluginPath) != pluginIds_.end()) {
HILOG_DEBUG(LOG_CORE, "already add");
@ -62,7 +99,7 @@ bool PluginManager::AddPlugin(const std::string& pluginPath)
RegisterPluginRequest request;
request.set_request_id(commandPoller_->GetRequestId());
request.set_path(pluginPath);
request.set_sha256("");
request.set_sha256(ComputeFileSha256(pluginPath));
request.set_name(pluginPath);
request.set_buffer_size_hint(0);
RegisterPluginResponse response;
@ -203,22 +240,22 @@ bool PluginManager::StartPluginSession(const std::vector<uint32_t>& pluginIds,
HILOG_DEBUG(LOG_CORE, "plugin not find");
return false;
}
auto configData = pluginModules_[id]->GetConfigData();
if (!pluginModules_[id]->StartSession(
reinterpret_cast<const uint8_t*>(configData.c_str()), configData.size())) {
auto plugin = pluginModules_[id];
auto cfgData = plugin->GetConfigData();
if (!plugin->StartSession(reinterpret_cast<const uint8_t*>(cfgData.c_str()), cfgData.size())) {
return false;
}
if (pluginModules_[id]->GetSampleMode() == PluginModule::POLLING) {
if (plugin->GetSampleMode() == PluginModule::POLLING) {
if (idx > config.size()) {
HILOG_WARN(LOG_CORE, "idx %zu out of size %zu", idx, config.size());
return false;
}
uint32_t sampleInterval = config[idx].sample_interval();
auto interval = ScheduleTaskManager::ms(config[idx].sample_interval());
std::string pluginName = config[idx].name();
HILOG_DEBUG(LOG_CORE, "sampleInterval = %d", sampleInterval);
HILOG_DEBUG(LOG_CORE, "name = %s", pluginName.c_str());
if (!scheduleTaskManager_.ScheduleTask(pluginName, std::bind(&PluginManager::PullResult, this, id),
ScheduleTaskManager::ms(sampleInterval))) {
HILOG_DEBUG(LOG_CORE, "interval = %ld", static_cast<long>(interval.count()));
HILOG_DEBUG(LOG_CORE, "pluginName = %s", pluginName.c_str());
auto callback = std::bind(&PluginManager::PullResult, this, id);
if (!scheduleTaskManager_.ScheduleTask(pluginName, callback, interval)) {
HILOG_DEBUG(LOG_CORE, "ScheduleTask failed");
return false;
}
@ -282,10 +319,8 @@ bool PluginManager::SubmitResult(const PluginResult& pluginResult)
bool PluginManager::PullResult(uint32_t pluginId)
{
HILOG_INFO(LOG_CORE, "%s: ready!", __func__);
uint32_t size = 0;
std::string name;
HILOG_DEBUG(LOG_CORE, "PullResult pluginId = %d", pluginId);
std::string name = "";
auto it = pluginModules_.find(pluginId);
if (it == pluginModules_.end()) {
HILOG_DEBUG(LOG_CORE, "plugin not find");
@ -293,19 +328,16 @@ bool PluginManager::PullResult(uint32_t pluginId)
}
pluginModules_[pluginId]->GetBufferSizeHint(size);
pluginModules_[pluginId]->GetPluginName(name);
std::unique_ptr<uint8_t[]> buffer {new (std::nothrow) uint8_t[size]};
std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[size]);
if (buffer == nullptr) {
HILOG_DEBUG(LOG_CORE, "buffer new failed!");
} else {
HILOG_DEBUG(LOG_CORE, "buffer new success!");
return false;
}
int length = it->second->ReportResult(buffer.get(), size);
if (length < 0) {
return false;
}
HILOG_DEBUG(LOG_CORE, "PullResult length = %d", length);
HILOG_DEBUG(LOG_CORE, "PullResult name = %s", name.c_str());
ProfilerPluginData pluginData;
pluginData.set_name(name);
@ -319,14 +351,15 @@ bool PluginManager::PullResult(uint32_t pluginId)
pluginData.set_tv_sec(ts.tv_sec);
pluginData.set_tv_nsec(ts.tv_nsec);
auto writer = pluginModules_[pluginId]->GetWriter();
auto writer = std::static_pointer_cast<BufferWriter>(pluginModules_[pluginId]->GetWriter());
CHECK_NOTNULL(writer, false, "PullResult GetWriter nullptr");
std::static_pointer_cast<BufferWriter>(writer)->WriteProtobuf(pluginData);
writer->WriteMessage(pluginData);
writer->Flush();
return true;
}
bool PluginManager::CreateWriter(std::string pluginName, uint32_t bufferSize, int fd)
bool PluginManager::CreateWriter(std::string pluginName, uint32_t bufferSize, int smbFd, int eventFd)
{
auto it = pluginIds_.find(pluginName);
if (it == pluginIds_.end()) {
@ -338,7 +371,7 @@ bool PluginManager::CreateWriter(std::string pluginName, uint32_t bufferSize, in
if (bufferSize > 0) {
HILOG_DEBUG(LOG_CORE, "%s Use ShareMemory %d", pluginName.c_str(), bufferSize);
pluginModules_[index]->RegisterWriter(
std::make_shared<BufferWriter>(pluginName, bufferSize, fd, commandPoller_, index));
std::make_shared<BufferWriter>(pluginName, bufferSize, smbFd, eventFd, index));
} else {
HILOG_ERROR(LOG_CORE, "no shared memory buffer allocated!");
return false;

View File

@ -21,6 +21,7 @@
#include <string>
#include <vector>
#include "manager_interface.h"
#include "plugin_module.h"
#include "schedule_task_manager.h"
@ -28,7 +29,7 @@ class ProfilerPluginConfig;
class PluginResult;
class CommandPoller;
class PluginManager {
class PluginManager : public ManagerInterface {
public:
virtual ~PluginManager();
bool AddPlugin(const std::string& pluginPath);
@ -50,7 +51,7 @@ public:
// for test
virtual bool SubmitResult(const PluginResult& pluginResult);
bool CreateWriter(std::string pluginName, uint32_t bufferSize, int fd);
bool CreateWriter(std::string pluginName, uint32_t bufferSize, int smbFd, int eventFd);
bool ResetWriter(uint32_t pluginId);
void SetCommandPoller(const CommandPollerPtr& p);

View File

@ -137,7 +137,7 @@ bool PluginModule::BindFunctions()
return false;
}
if (structPtr_ == nullptr) {
structPtr_ = (PluginModuleStruct*)dlsym(handle_, "g_pluginModule");
structPtr_ = static_cast<PluginModuleStruct*>(dlsym(handle_, "g_pluginModule"));
if (structPtr_ == nullptr) {
HILOG_DEBUG(LOG_CORE, "structPtr_ == nullptr");
return false;
@ -165,7 +165,6 @@ bool PluginModule::StartSession(const uint8_t* buffer, uint32_t size)
HILOG_DEBUG(LOG_CORE, "plugin not load");
return false;
}
HILOG_DEBUG(LOG_CORE, "size = %u, ", size);
if (structPtr_ != nullptr && structPtr_->callbacks != nullptr) {
if (structPtr_->callbacks->onPluginSessionStart) {
@ -192,8 +191,6 @@ bool PluginModule::StopSession()
int32_t PluginModule::ReportResult(uint8_t* buffer, uint32_t size)
{
HILOG_INFO(LOG_CORE, "%s: ready!", __func__);
HILOG_DEBUG(LOG_CORE, "ReportResult");
if (handle_ == nullptr) {
HILOG_DEBUG(LOG_CORE, "plugin not open");
return -1;
@ -203,15 +200,11 @@ int32_t PluginModule::ReportResult(uint8_t* buffer, uint32_t size)
first_ = false;
} else {
std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
std::chrono::duration<int, std::milli> interval =
std::chrono::duration_cast<std::chrono::duration<int, std::milli>>(t1 - lastTime_);
HILOG_DEBUG(LOG_CORE, "the id equals %u interval is %d milli seconds", size, interval.count());
lastTime_ = t1;
}
if (structPtr_ != nullptr && structPtr_->callbacks != nullptr) {
if (structPtr_->callbacks->onPluginReportResult != nullptr) {
HILOG_INFO(LOG_CORE, "%s: call plugin ready!", __func__);
return structPtr_->callbacks->onPluginReportResult(buffer, size);
}
}
@ -223,6 +216,11 @@ bool PluginModule::RegisterWriter(const BufferWriterPtr writer)
{
writerAdapter_ = std::make_shared<WriterAdapter>();
writerAdapter_->SetWriter(writer);
if (writer == nullptr) {
HILOG_INFO(LOG_CORE, "BufferWriter is null, update WriterAdapter only!");
return true;
}
if (structPtr_ != nullptr && structPtr_->callbacks != nullptr) {
if (structPtr_->callbacks->onRegisterWriterStruct != nullptr) {
return structPtr_->callbacks->onRegisterWriterStruct(writerAdapter_->GetStruct());

95
device/plugins/api/src/plugin_watcher.cpp Executable file → Normal file
View File

@ -19,6 +19,7 @@
#include <cstdio>
#include <cstring>
#include <dirent.h>
#include <pthread.h>
#include <sys/inotify.h>
#include <unistd.h>
@ -54,7 +55,7 @@ PluginWatcher::~PluginWatcher()
monitorThread_.join();
}
void PluginWatcher::ScanPlugins(const std::string& pluginDir)
bool PluginWatcher::ScanPlugins(const std::string& pluginDir)
{
DIR* dir = nullptr;
struct dirent* entry = nullptr;
@ -63,7 +64,7 @@ void PluginWatcher::ScanPlugins(const std::string& pluginDir)
HILOG_INFO(LOG_CORE, "scan plugin from directory %s", fullpath);
dir = opendir(fullpath);
if (dir == nullptr) {
return;
return false;
}
while (true) {
entry = readdir(dir);
@ -80,10 +81,10 @@ void PluginWatcher::ScanPlugins(const std::string& pluginDir)
}
}
closedir(dir);
return;
return true;
}
void PluginWatcher::WatchPlugins(const std::string& pluginDir)
bool PluginWatcher::WatchPlugins(const std::string& pluginDir)
{
char fullpath[PATH_MAX + 1] = {0};
realpath(pluginDir.c_str(), fullpath);
@ -91,66 +92,80 @@ void PluginWatcher::WatchPlugins(const std::string& pluginDir)
int wd = inotify_add_watch(inotifyFd_, fullpath, IN_ALL_EVENTS);
if (wd < 0) {
HILOG_INFO(LOG_CORE, "inotify_add_watch add directory %s failed", pluginDir.c_str());
return;
return false;
}
HILOG_INFO(LOG_CORE, "inotify_add_watch add directory %s success", fullpath);
std::lock_guard<std::mutex> guard(mtx_);
wdToDir_.insert(std::pair<int, std::string>(wd, std::string(fullpath)));
return true;
}
void PluginWatcher::Monitor()
bool PluginWatcher::MonitorIsSet()
{
const struct inotify_event* event = nullptr;
char buffer[MAX_BUF_SIZE] = {'\0'};
struct timeval time;
char* ptr = nullptr;
int ret = 0;
ssize_t readLength = read(inotifyFd_, buffer, MAX_BUF_SIZE);
if (readLength == -1) {
return false;
}
for (ptr = buffer; ptr < buffer + readLength; ptr += sizeof(struct inotify_event) + event->len) {
event = reinterpret_cast<const struct inotify_event*>(ptr);
std::unique_lock<std::mutex> guard(mtx_, std::adopt_lock);
const std::string& pluginDir = wdToDir_[event->wd];
guard.unlock();
if (event->mask & IN_ISDIR) {
continue;
}
std::string fileName = event->name;
size_t pos = fileName.rfind(".so");
if ((pos == std::string::npos) || (pos != fileName.length() - strlen(".so"))) {
continue;
}
switch (event->mask) {
case IN_CLOSE_WRITE:
case IN_MOVED_TO:
OnPluginAdded(pluginDir + '/' + fileName);
break;
case IN_DELETE:
case IN_MOVED_FROM:
OnPluginRemoved(pluginDir + '/' + fileName);
break;
default:
break;
}
}
if (memset_s(buffer, MAX_BUF_SIZE, 0, MAX_BUF_SIZE) != 0) {
HILOG_ERROR(LOG_CORE, "memset_s error!");
}
return true;
}
void PluginWatcher::Monitor()
{
struct timeval time;
pthread_setname_np(pthread_self(), "PluginWatcher");
while (runMonitor_) {
fd_set rFds;
FD_ZERO(&rFds);
FD_SET(inotifyFd_, &rFds);
time.tv_sec = 1;
time.tv_usec = 0;
ret = select(inotifyFd_ + 1, &rFds, nullptr, nullptr, &time);
int ret = select(inotifyFd_ + 1, &rFds, nullptr, nullptr, &time);
if (ret < 0) {
continue;
} else if (!ret) {
continue;
} else if (FD_ISSET(inotifyFd_, &rFds)) {
ssize_t readLength = read(inotifyFd_, buffer, MAX_BUF_SIZE);
if (readLength == -1) {
if (!MonitorIsSet()) {
continue;
}
for (ptr = buffer; ptr < buffer + readLength; ptr += sizeof(struct inotify_event) + event->len) {
event = reinterpret_cast<const struct inotify_event*>(ptr);
std::unique_lock<std::mutex> guard(mtx_, std::adopt_lock);
const std::string& pluginDir = wdToDir_[event->wd];
guard.unlock();
if (event->mask & IN_ISDIR) {
continue;
}
std::string fileName = event->name;
size_t pos = fileName.rfind(".so");
if (pos == std::string::npos || (pos != fileName.length() - strlen(".so"))) {
continue;
}
switch (event->mask) {
case IN_CLOSE_WRITE:
case IN_MOVED_TO:
OnPluginAdded(pluginDir + '/' + fileName);
break;
case IN_DELETE:
case IN_MOVED_FROM:
OnPluginRemoved(pluginDir + '/' + fileName);
break;
default:
break;
}
}
if (memset_s(buffer, MAX_BUF_SIZE, 0, MAX_BUF_SIZE) != EOK) {
HILOG_ERROR(LOG_CORE, "memset_s error!");
}
}
}
}

9
device/plugins/api/src/plugin_watcher.h Executable file → Normal file
View File

@ -31,10 +31,8 @@ class PluginWatcher {
public:
explicit PluginWatcher(const PluginManagerPtr& pluginManager);
~PluginWatcher();
void ScanPlugins(const std::string& pluginDir);
void WatchPlugins(const std::string& pluginDir);
bool ScanPlugins(const std::string& pluginDir);
bool WatchPlugins(const std::string& pluginDir);
private:
int inotifyFd_;
@ -43,11 +41,10 @@ private:
std::thread monitorThread_;
std::mutex mtx_;
bool runMonitor_;
virtual void OnPluginAdded(const std::string& pluginPath);
virtual void OnPluginRemoved(const std::string& pluginPath);
void MonitorEventName(uint32_t mask, const std::string& fileName, const std::string& pluginDir);
void Monitor();
bool MonitorIsSet();
};
#endif // !PLUGIN_WATCHER_H

3
device/plugins/api/src/writer_adapter.cpp Executable file → Normal file
View File

@ -40,7 +40,8 @@ const WriterStruct* WriterAdapter::GetStruct()
long WriterAdapter::WriteFunc(WriterStruct* writer, const void* data, size_t size)
{
WriterAdapter* writerAdaptor = reinterpret_cast<WriterAdapter*>(writer);
static_assert(offsetof(WriterAdapter, writerStruct_) == 0, "unexpected alignment of writerStruct_!");
WriterAdapter* writerAdaptor = reinterpret_cast<WriterAdapter*>(writer); // 转成 WriterAdapter*
if (writerAdaptor && writerAdaptor->writer_) {
return writerAdaptor->writer_->Write(data, size);
}

0
device/plugins/api/src/writer_adapter.h Executable file → Normal file
View File

30
device/plugins/api/test/BUILD.gn Executable file → Normal file
View File

@ -16,49 +16,43 @@ import("../../../base/config.gni")
module_output_path = "${OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH}/device"
config("module_private_config") {
visibility = [":*"]
visibility = [ ":*" ]
}
config("cflags_config") {
cflags = [
"-Wno-sign-compare",
"-pthread",
"-Dprivate=public", #allow test code access private members
"-Dprotected=public", #allow test code access private members
"-Dprivate=public", #allow test code access private members
"-Dprotected=public", #allow test code access private members
]
}
ohos_unittest("hiprofiler_plugins_ut") {
module_out_path = module_output_path
deps = [
"../:plugins_sources",
"${OHOS_PROFILER_DIR}/device/services/plugin_service:hiprofiler_plugin_service",
"${OHOS_PROFILER_DIR}/device/services/profiler_service:profiler_service",
"../:plugins_sources",
"//third_party/googletest:gmock",
"//third_party/googletest:gtest",
]
include_dirs = [
"//third_party/googletest/googletest/include/gtest",
]
include_dirs = [ "//third_party/googletest/googletest/include/gtest" ]
sources = [
"unittest/writer_adapter_test.cpp",
"unittest/buffer_write_test.cpp",
"unittest/command_poller_test.cpp",
"unittest/plugin_manager_test.cpp",
"unittest/plugin_module_test.cpp",
"unittest/plugin_watcher_test.cpp",
"unittest/services_ipc_test.cpp",
"unittest/services_profiler_service_test.cpp",
"unittest/services_shared_memory_test.cpp",
"unittest/services_plugin_service_test.cpp",
"unittest/writer_adapter_test.cpp",
]
configs = [ ":cflags_config" ]
external_deps = [
"hiviewdfx_hilog_native:libhilog",
]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
resource_config_file = "${OHOS_PROFILER_DIR}/device/ohos_test.xml"
}
group("unittest") {
testonly = true
deps = [
":hiprofiler_plugins_ut",
]
deps = [ ":hiprofiler_plugins_ut" ]
}

View File

@ -0,0 +1,205 @@
/*
* Copyright (c) 2021 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 <hwext/gtest-ext.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include "buffer_writer.h"
#include "plugin_service_types.pb.h"
using namespace testing::ext;
namespace {
constexpr uint32_t SMB1_SIZE = 10 * 4096;
constexpr uint32_t SMB2_SIZE = 10 * 4096;
const std::string SMB1_NAME = "testsmb1";
const std::string SMB2_NAME = "testsmb2";
const std::string PLUGIN_NAME = "testplugin";
void *g_smbAddr1 = nullptr;
void *g_smbAddr2 = nullptr;
int g_smbFd1 = 0;
int g_smbFd2 = 0;
int InitShareMemory1()
{
int fd = syscall(SYS_memfd_create, SMB1_NAME.c_str(), 0);
CHECK_TRUE(fd >= 0, false, "CreateBlock FAIL SYS_memfd_create");
int check = ftruncate(fd, SMB1_SIZE);
if (check < 0) {
close(fd);
HILOG_ERROR(LOG_CORE, "CreateBlock ftruncate ERR : %s", strerror(errno));
return -1;
}
g_smbAddr1 = mmap(nullptr, SMB1_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (g_smbAddr1 == MAP_FAILED) {
close(fd);
HILOG_ERROR(LOG_CORE, "CreateBlock g_smbAddr1 mmap ERR : %s", strerror(errno));
return -1;
}
ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr1);
// initialize header infos
header_->info.readOffset_ = 0;
header_->info.writeOffset_ = 0;
header_->info.memorySize_ = SMB1_SIZE - sizeof(ShareMemoryBlock::BlockHeader);
header_->info.bytesCount_ = 0;
header_->info.chunkCount_ = 0;
return fd;
}
int InitShareMemory2()
{
int fd = syscall(SYS_memfd_create, SMB2_NAME.c_str(), 0);
CHECK_TRUE(fd >= 0, false, "CreateBlock FAIL SYS_memfd_create");
int check = ftruncate(fd, SMB2_SIZE);
if (check < 0) {
close(fd);
HILOG_ERROR(LOG_CORE, "CreateBlock ftruncate ERR : %s", strerror(errno));
return -1;
}
g_smbAddr2 = mmap(nullptr, SMB2_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (g_smbAddr2 == MAP_FAILED) {
close(fd);
HILOG_ERROR(LOG_CORE, "CreateBlock g_smbAddr2 mmap ERR : %s", strerror(errno));
return -1;
}
ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr2);
// initialize header infos
header_->info.readOffset_ = 0;
header_->info.writeOffset_ = 0;
header_->info.memorySize_ = SMB2_SIZE - sizeof(ShareMemoryBlock::BlockHeader);
header_->info.bytesCount_ = 0;
header_->info.chunkCount_ = 0;
return fd;
}
class BufferWriteTest : public ::testing::Test {
protected:
static void SetUpTestCase()
{
g_smbFd1 = InitShareMemory1();
g_smbFd2 = InitShareMemory2();
printf("SetUpTestCase success\n");
}
static void TearDownTestCase() {}
};
bool CheckBuffer(uint8_t *buffer, size_t size)
{
ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr1);
uint8_t *cmpaddr = (uint8_t *)g_smbAddr1 + sizeof(ShareMemoryBlock::BlockHeader) + header_->info.readOffset_;
uint32_t cmpsize = *(uint32_t*)cmpaddr;
cmpaddr = cmpaddr + sizeof(uint32_t);
ProfilerPluginData pluginData;
pluginData.ParseFromArray(cmpaddr, cmpsize);
const char* data = pluginData.data().c_str();
header_->info.readOffset_ = header_->info.writeOffset_;
if (memcmp(buffer, data, size) == 0) {
return true;
}
return false;
}
bool CheckMessage(uint8_t *buffer, size_t size)
{
ShareMemoryBlock::BlockHeader* header_ = reinterpret_cast<ShareMemoryBlock::BlockHeader*>(g_smbAddr2);
uint8_t *cmpaddr = (uint8_t *)g_smbAddr2 + sizeof(ShareMemoryBlock::BlockHeader) + header_->info.readOffset_;
cmpaddr = cmpaddr + sizeof(uint32_t);
header_->info.readOffset_ = header_->info.writeOffset_;
if (memcmp(buffer, cmpaddr, size) == 0) {
return true;
}
return false;
}
/**
* @tc.name: plugin
* @tc.desc: Write data to shared memory through writer.
* @tc.type: FUNC
*/
HWTEST_F(BufferWriteTest, WriteTest, TestSize.Level1)
{
auto write = std::make_shared<BufferWriter>(PLUGIN_NAME, SMB1_SIZE, g_smbFd1, -1, 0);
uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA};
uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44};
uint8_t buffer3[] = {0xAA, 0xBB, 0xCC, 0xDD};
EXPECT_TRUE(write->Write(buffer1, sizeof(buffer1)));
EXPECT_TRUE(CheckBuffer(buffer1, sizeof(buffer1)));
EXPECT_TRUE(write->Write(buffer2, sizeof(buffer2)));
EXPECT_TRUE(CheckBuffer(buffer2, sizeof(buffer2)));
EXPECT_TRUE(write->Write(buffer3, sizeof(buffer3)));
EXPECT_TRUE(CheckBuffer(buffer3, sizeof(buffer3)));
EXPECT_FALSE(write->Write(nullptr, 0));
}
/**
* @tc.name: plugin
* @tc.desc: Write data to shared memory through writer.
* @tc.type: FUNC
*/
HWTEST_F(BufferWriteTest, WriteMessageTest, TestSize.Level1)
{
uint8_t data[1024];
auto write = std::make_shared<BufferWriter>(PLUGIN_NAME, SMB2_SIZE, g_smbFd2, -1, 0);
ProfilerPluginConfig configData;
configData.set_name("111");
configData.set_plugin_sha256("222");
configData.set_sample_interval(1000);
size_t size = configData.ByteSizeLong();
configData.SerializeToArray(data, size);
EXPECT_TRUE(write->WriteMessage(configData));
EXPECT_TRUE(CheckMessage(data, size));
ProfilerPluginState stateData;
stateData.set_name("st");
stateData.set_state(ProfilerPluginState::IN_SESSION);
size = stateData.ByteSizeLong();
stateData.SerializeToArray(data, size);
EXPECT_TRUE(write->WriteMessage(stateData));
EXPECT_TRUE(CheckMessage(data, size));
ProfilerPluginData pluginData;
pluginData.set_name("test");
pluginData.set_status(1);
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
pluginData.set_clock_id(ProfilerPluginData::CLOCKID_REALTIME);
pluginData.set_tv_sec(ts.tv_sec);
pluginData.set_tv_nsec(ts.tv_nsec);
size = pluginData.ByteSizeLong();
pluginData.SerializeToArray(data, size);
EXPECT_TRUE(write->WriteMessage(pluginData));
EXPECT_TRUE(CheckMessage(data, size));
}
} // namespace

View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2021 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 <gmock/gmock.h>
#include <hwext/gtest-ext.h>
#include <hwext/gtest-tag.h>
#include "command_poller.h"
#include "plugin_manager.h"
#include "plugin_service.ipc.h"
#include "socket_context.h"
using namespace testing::ext;
namespace {
class PluginManagerStub final : public ManagerInterface {
public:
virtual bool LoadPlugin(const std::string& pluginPath) override
{
if (pluginPath == "existplugin") {
return true;
} else if (pluginPath == "noexistplugin") {
return false;
}
return true;
}
virtual bool UnloadPlugin(const std::string& pluginPath)
{
if (pluginPath == "existplugin") {
return true;
} else if (pluginPath == "noexistplugin") {
return false;
}
return true;
}
virtual bool UnloadPlugin(const uint32_t pluginId)
{
if (pluginId == 0) {
return false;
}
return true;
}
virtual bool CreatePluginSession(const std::vector<ProfilerPluginConfig>& config)
{
if (config[0].name() == "existplugin") {
return true;
} else if (config[0].name() == "noexistplugin") {
return false;
}
return true;
}
virtual bool DestroyPluginSession(const std::vector<uint32_t>& pluginIds)
{
if (pluginIds[0] != 1) {
return false;
}
return true;
}
virtual bool StartPluginSession(const std::vector<uint32_t>& pluginIds,
const std::vector<ProfilerPluginConfig>& config)
{
if (pluginIds[0] == 0) {
return false;
}
if (config[0].name() == "existplugin") {
return true;
} else if (config[0].name() == "noexistplugin") {
return false;
}
return true;
}
virtual bool StopPluginSession(const std::vector<uint32_t>& pluginIds)
{
if (pluginIds[0] == 0) {
return false;
}
return true;
}
virtual bool CreateWriter(std::string pluginName, uint32_t bufferSize, int smbFd, int eventFd)
{
if (bufferSize == 0) {
return false;
}
return true;
}
virtual bool ResetWriter(uint32_t pluginId)
{
if (pluginId == 0) {
return false;
}
return true;
}
virtual void SetCommandPoller(const std::shared_ptr<CommandPoller>& p)
{
this->commandPoller_ = p;
}
private:
CommandPollerPtr commandPoller_;
};
class CommandPollerTest : public ::testing::Test {
protected:
static void SetUpTestCase() {}
static void TearDownTestCase() {}
};
HWTEST_F(CommandPollerTest, CreateCmdTest, TestSize.Level1)
{
auto pluginManage = std::make_shared<PluginManagerStub>();
auto commandPoller = std::make_shared<CommandPoller>(pluginManage);
pluginManage->SetCommandPoller(commandPoller);
CreateSessionCmd successCmd;
CreateSessionCmd failed1Cmd;
CreateSessionCmd failed2Cmd;
CreateSessionCmd failed3Cmd;
SocketContext ctx;
successCmd.add_buffer_sizes(1024);
successCmd.add_plugin_configs()->set_name("existplugin");
failed1Cmd.add_buffer_sizes(0);
failed1Cmd.add_plugin_configs()->set_name("existplugin");
failed2Cmd.add_buffer_sizes(0);
failed2Cmd.add_plugin_configs()->set_name("noexistplugin");
failed3Cmd.add_buffer_sizes(1);
failed3Cmd.add_plugin_configs()->set_name("noexistplugin");
EXPECT_TRUE(commandPoller->OnCreateSessionCmd(successCmd, ctx));
EXPECT_FALSE(commandPoller->OnCreateSessionCmd(failed1Cmd, ctx));
EXPECT_FALSE(commandPoller->OnCreateSessionCmd(failed2Cmd, ctx));
EXPECT_FALSE(commandPoller->OnCreateSessionCmd(failed3Cmd, ctx));
}
HWTEST_F(CommandPollerTest, StartCmdTest, TestSize.Level1)
{
auto pluginManage = std::make_shared<PluginManagerStub>();
auto commandPoller = std::make_shared<CommandPoller>(pluginManage);
pluginManage->SetCommandPoller(commandPoller);
StartSessionCmd successCmd;
successCmd.add_plugin_ids(1);
successCmd.add_plugin_configs()->set_name("existplugin");
StartSessionCmd failed1Cmd;
failed1Cmd.add_plugin_ids(0);
failed1Cmd.add_plugin_configs()->set_name("existplugin");
StartSessionCmd failed2Cmd;
failed2Cmd.add_plugin_ids(1);
failed2Cmd.add_plugin_configs()->set_name("noexistplugin");
EXPECT_TRUE(commandPoller->OnStartSessionCmd(successCmd));
EXPECT_FALSE(commandPoller->OnStartSessionCmd(failed1Cmd));
EXPECT_FALSE(commandPoller->OnStartSessionCmd(failed2Cmd));
}
HWTEST_F(CommandPollerTest, StopCmdTest, TestSize.Level1)
{
auto pluginManage = std::make_shared<PluginManagerStub>();
auto commandPoller = std::make_shared<CommandPoller>(pluginManage);
pluginManage->SetCommandPoller(commandPoller);
StopSessionCmd successCmd;
successCmd.add_plugin_ids(1);
StopSessionCmd failedCmd;
failedCmd.add_plugin_ids(0);
EXPECT_TRUE(commandPoller->OnStopSessionCmd(successCmd));
EXPECT_FALSE(commandPoller->OnStopSessionCmd(failedCmd));
}
HWTEST_F(CommandPollerTest, DestoryCmdTest, TestSize.Level1)
{
auto pluginManage = std::make_shared<PluginManagerStub>();
auto commandPoller = std::make_shared<CommandPoller>(pluginManage);
pluginManage->SetCommandPoller(commandPoller);
DestroySessionCmd successCmd;
DestroySessionCmd failed1Cmd;
DestroySessionCmd failed2Cmd;
DestroySessionCmd failed3Cmd;
successCmd.add_plugin_ids(1);
failed1Cmd.add_plugin_ids(0);
failed2Cmd.add_plugin_ids(2);
failed3Cmd.add_plugin_ids(3);
EXPECT_TRUE(commandPoller->OnDestroySessionCmd(successCmd));
EXPECT_FALSE(commandPoller->OnDestroySessionCmd(failed1Cmd));
EXPECT_FALSE(commandPoller->OnDestroySessionCmd(failed2Cmd));
EXPECT_FALSE(commandPoller->OnDestroySessionCmd(failed3Cmd));
}
}

View File

@ -32,8 +32,12 @@ using google::protobuf::Message;
using namespace testing::ext;
namespace {
constexpr int DEFAULT_BUFFER_SIZE = 4096;
constexpr int DEFAULT_SLEEP_TIME = 1000;
const static std::string SUCCESS_PLUGIN_NAME = "libmemdataplugin.z.so";
std::string g_testPluginDir("/data/local/tmp/");
std::string g_testPluginDir("/system/lib/");
int g_hiprofilerProcessNum = -1;
const std::string DEFAULT_HIPROFILERD_PATH("/system/lib/hiprofilerd");
class PluginManagerTest : public ::testing::Test {
protected:
@ -54,10 +58,29 @@ protected:
printf("======> pluginDir = %s\n", g_testPluginDir.c_str());
std::this_thread::sleep_for(TEMP_DELAY);
int processNum = fork();
std::cout << "processNum : " << processNum << std::endl;
if (processNum == 0) {
// start running hiprofilerd
std::string cmd = "chmod 777 " + DEFAULT_HIPROFILERD_PATH;
std::cout << "cmd : " << cmd << std::endl;
system(cmd.c_str());
execl(DEFAULT_HIPROFILERD_PATH.c_str(), nullptr, nullptr);
_exit(1);
} else {
g_hiprofilerProcessNum = processNum;
}
std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_SLEEP_TIME));
printf("SetUpTestCase success\n");
}
static void TearDownTestCase()
{
std::string stopCmd = "kill " + std::to_string(g_hiprofilerProcessNum);
std::cout << "stop command : " << stopCmd << std::endl;
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(stopCmd.c_str(), "r"), pclose);
}
};
@ -75,33 +98,30 @@ HWTEST_F(PluginManagerTest, SuccessPlugin, TestSize.Level1)
const uint8_t configData[] = {0x30, 0x01, 0x38, 0x01, 0x42, 0x01, 0x01};
ProfilerPluginConfig config;
const std::vector<uint32_t> pluginIdsVector = {1};
config.set_name(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME);
config.set_name(g_testPluginDir + SUCCESS_PLUGIN_NAME);
config.set_config_data((const void*)configData, 7);
config.set_sample_interval(1000);
config.set_sample_interval(DEFAULT_SLEEP_TIME);
EXPECT_FALSE(pluginManage->LoadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->UnloadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->AddPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->AddPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->RemovePlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->RemovePlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->AddPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->LoadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->LoadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->UnloadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->LoadPlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->UnloadPlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
EXPECT_TRUE(pluginManage->AddPlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->AddPlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
EXPECT_TRUE(pluginManage->RemovePlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->RemovePlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
EXPECT_TRUE(pluginManage->AddPlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
EXPECT_TRUE(pluginManage->LoadPlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->LoadPlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
EXPECT_TRUE(pluginManage->UnloadPlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
EXPECT_FALSE(pluginManage->LoadPlugin(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME));
EXPECT_TRUE(pluginManage->LoadPlugin(g_testPluginDir + SUCCESS_PLUGIN_NAME));
std::vector<ProfilerPluginConfig> configVec;
configVec.push_back(config);
EXPECT_FALSE(pluginManage->CreatePluginSession(configVec));
EXPECT_FALSE(pluginManage->StartPluginSession(pluginIdsVector, configVec));
EXPECT_TRUE(pluginManage->CreatePluginSession(configVec));
EXPECT_TRUE(pluginManage->StartPluginSession(pluginIdsVector, configVec));
std::this_thread::sleep_for(TEMP_DELAY);
EXPECT_FALSE(pluginManage->StopPluginSession(pluginIdsVector));
EXPECT_FALSE(pluginManage->DestroyPluginSession(pluginIdsVector));
EXPECT_TRUE(pluginManage->StopPluginSession(pluginIdsVector));
EXPECT_TRUE(pluginManage->DestroyPluginSession(pluginIdsVector));
}
/**
@ -112,7 +132,14 @@ HWTEST_F(PluginManagerTest, SuccessPlugin, TestSize.Level1)
HWTEST_F(PluginManagerTest, GetSampleMode, TestSize.Level1)
{
PluginModule pluginModule;
pluginModule.GetSampleMode();
if (pluginModule.structPtr_ && pluginModule.structPtr_->callbacks) {
if (pluginModule.structPtr_->callbacks->onPluginReportResult != nullptr) {
EXPECT_EQ(pluginModule.GetSampleMode(), PluginModule::SampleMode::POLLING);
} else if (pluginModule.structPtr_->callbacks->onRegisterWriterStruct != nullptr) {
EXPECT_EQ(pluginModule.GetSampleMode(), PluginModule::SampleMode::STREAMING);
}
}
EXPECT_EQ(pluginModule.GetSampleMode(), PluginModule::SampleMode::UNKNOWN);
}
/**
@ -124,25 +151,30 @@ HWTEST_F(PluginManagerTest, PluginManager, TestSize.Level1)
{
PluginManager pluginManager;
PluginModuleInfo info;
pluginManager.UnloadPlugin(0);
EXPECT_FALSE(pluginManager.UnloadPlugin(0));
PluginResult pluginResult;
pluginManager.SubmitResult(pluginResult);
pluginManager.PullResult(0);
pluginManager.CreateWriter("", 0, -1);
pluginManager.ResetWriter(-1);
EXPECT_FALSE(pluginManager.SubmitResult(pluginResult));
EXPECT_FALSE(pluginManager.PullResult(0));
EXPECT_FALSE(pluginManager.CreateWriter("", 0, -1, -1));
EXPECT_FALSE(pluginManager.ResetWriter(-1));
PluginModule pluginModule;
pluginModule.ComputeSha256();
pluginModule.Unload();
pluginModule.GetInfo(info);
EXPECT_EQ(pluginModule.ComputeSha256(), "");
EXPECT_FALSE(pluginModule.Unload());
EXPECT_FALSE(pluginModule.GetInfo(info));
std::string str("memory-plugin");
pluginModule.GetPluginName(str);
EXPECT_FALSE(pluginModule.GetPluginName(str));
uint32_t num = 0;
pluginModule.GetBufferSizeHint(num);
pluginModule.IsLoaded();
EXPECT_FALSE(pluginModule.GetBufferSizeHint(num));
EXPECT_FALSE(pluginModule.IsLoaded());
BufferWriter bufferWriter("", 0, -1, nullptr, 0);
bufferWriter.Write(nullptr, 0);
bufferWriter.Flush();
BufferWriter bufferWriter("test", DEFAULT_BUFFER_SIZE, -1, -1, 0);
EXPECT_EQ(bufferWriter.shareMemoryBlock_, nullptr);
EXPECT_FALSE(bufferWriter.Write(str.data(), str.size()));
bufferWriter.shareMemoryBlock_ =
ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal("test", DEFAULT_BUFFER_SIZE);
EXPECT_TRUE(bufferWriter.Write(str.data(), str.size()));
EXPECT_TRUE(bufferWriter.Flush());
}
} // namespace

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2021 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 <hwext/gtest-ext.h>
#include <hwext/gtest-tag.h>
#include <thread>
#include "plugin_module.h"
#include "common_types.pb.h"
using namespace testing::ext;
namespace {
const static std::string SUCCESS_PLUGIN_NAME = "libmemdataplugin.z.so";
constexpr size_t READ_BUFFER_SIZE = 4 * 1024 * 1024;
std::string g_testPluginDir("/system/lib/");
class PluginModuleTest : public ::testing::Test {
protected:
static constexpr auto TEMP_DELAY = std::chrono::milliseconds(20);
static void SetUpTestCase()
{
#if defined(__i386__) || defined(__x86_64__)
char pluginDir[PATH_MAX + 1] = {0};
if (readlink("/proc/self/exe", pluginDir, PATH_MAX) > 0) {
char* pos = strrchr(pluginDir, '/');
if (pos != nullptr) {
*(pos++) = '\0';
printf("-----> pluginModuleDir = %s\n", pluginDir);
g_testPluginDir = pluginDir;
}
}
#endif
printf("======> pluginModuleDir = %s\n", g_testPluginDir.c_str());
std::this_thread::sleep_for(TEMP_DELAY);
printf("SetUpTestCase success\n");
}
static void TearDownTestCase() {}
};
/**
* @tc.name: plugin
* @tc.desc: pluginmodule normal test.
* @tc.type: FUNC
*/
HWTEST_F(PluginModuleTest, PluginModuleNormal, TestSize.Level1)
{
std::string pluginPath = g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME;
PluginModuleInfo info;
auto plugin = std::make_shared<PluginModule>(pluginPath);
EXPECT_TRUE(plugin->Load());
EXPECT_TRUE(plugin->BindFunctions());
EXPECT_TRUE(plugin->GetInfo(info));
EXPECT_TRUE(plugin->IsLoaded());
uint32_t size = 0;
plugin->GetBufferSizeHint(size);
EXPECT_EQ(size, READ_BUFFER_SIZE);
std::string name;
plugin->GetPluginName(name);
EXPECT_STREQ(name.c_str(), "memory-plugin");
const uint8_t configData[] = {74, 1, 10};
ProfilerPluginConfig config;
config.set_name(g_testPluginDir + "/" + SUCCESS_PLUGIN_NAME);
config.set_config_data((const void*)configData, 3);
config.set_sample_interval(1000);
plugin->SetConfigData(config.config_data());
std::string cfgData = plugin->GetConfigData();
EXPECT_EQ(cfgData.c_str()[0], 74);
EXPECT_EQ(cfgData.c_str()[1], 1);
EXPECT_EQ(cfgData.c_str()[2], 10);
std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[size]);
EXPECT_NE(buffer, nullptr);
EXPECT_TRUE(plugin->StartSession(reinterpret_cast<const uint8_t*>(cfgData.c_str()), cfgData.size()));
EXPECT_NE(plugin->ReportResult(buffer.get(), size), 0);
EXPECT_TRUE(plugin->StopSession());
EXPECT_TRUE(plugin->StartSession(nullptr, 0));
EXPECT_EQ(plugin->ReportResult(buffer.get(), size), 0);
EXPECT_TRUE(plugin->StopSession());
EXPECT_TRUE(plugin->StartSession(reinterpret_cast<const uint8_t*>(cfgData.c_str()), cfgData.size()));
EXPECT_NE(plugin->ReportResult(nullptr, 0), 0);
EXPECT_NE(plugin->ReportResult(nullptr, 0), -1);
EXPECT_TRUE(plugin->StopSession());
EXPECT_TRUE(plugin->StartSession(nullptr, 0));
EXPECT_EQ(plugin->ReportResult(nullptr, 0), 0);
EXPECT_TRUE(plugin->StopSession());
EXPECT_TRUE(plugin->Unload());
EXPECT_FALSE(plugin->IsLoaded());
}
/**
* @tc.name: plugin
* @tc.desc: pluginmodule abnormal test.
* @tc.type: FUNC
*/
HWTEST_F(PluginModuleTest, PluginModuleAbnormal, TestSize.Level1)
{
std::string pluginPath = "invalid.z.so";
PluginModuleInfo info;
auto plugin = std::make_shared<PluginModule>(pluginPath);
EXPECT_FALSE(plugin->Load());
EXPECT_FALSE(plugin->BindFunctions());
EXPECT_FALSE(plugin->GetInfo(info));
EXPECT_FALSE(plugin->IsLoaded());
uint32_t size = 0;
plugin->GetBufferSizeHint(size);
EXPECT_EQ(size, 0);
std::string name;
plugin->GetPluginName(name);
EXPECT_STREQ(name.c_str(), "");
std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[size]);
EXPECT_NE(buffer, nullptr);
EXPECT_FALSE(plugin->StartSession(nullptr, 0));
EXPECT_EQ(plugin->ReportResult(buffer.get(), size), -1);
EXPECT_FALSE(plugin->StopSession());
EXPECT_FALSE(plugin->Unload());
}
} // namespace

272
device/plugins/api/test/unittest/plugin_watcher_test.cpp Executable file → Normal file
View File

@ -29,27 +29,15 @@
using namespace testing::ext;
namespace {
static std::vector<std::string> g_cmpFileList;
static std::vector<std::string> g_createFileList = {
"lib_6.so", "lib_5.so", "lib_8.so", "lib_4.so", "test1.txt"
};
std::vector<int> g_createFdList;
static std::vector<std::string> g_addFileList = {
"libadd_6.so", "libadd_5.so", "libadd_8.so", "libadd_4.so", "test2.txt"
};
static std::vector<std::string> g_expectFileList = {
"libadd_6.so", "libadd_5.so", "libadd_8.so", "libadd_4.so",
"lib_6.so", "lib_5.so", "lib_8.so", "lib_4.so"
};
static int g_defaultFileMode = 0777;
constexpr int DEAFULT_FILE_MODE = 0777;
#if defined(__i386__) || defined(__x86_64__)
const static std::string DEFAULT_TEST_PATH = "./";
#else
const static std::string DEFAULT_TEST_PATH = "/data/local/tmp/";
const static std::string DEFAULT_TEST_PATH_1 = "/data/local/tmp/watchertest/1/";
const static std::string DEFAULT_TEST_PATH_2 = "/data/local/tmp/watchertest/2/";
const static std::string DEFAULT_TEST_PATH_3 = "/data/local/tmp/watchertest/3/";
const static std::string NO_EXIST_TEST_PATH = "/data/local/tmp/noexist/";
#endif
class PluginWatchTest : public ::testing::Test {
@ -58,8 +46,98 @@ protected:
static void SetUpTestCase() {}
static void TearDownTestCase() {}
void SetUp() override {}
void TearDown() override {}
void SetUp() override
{
std::string cmd = "mkdir -p " + DEFAULT_TEST_PATH_1;
system(cmd.c_str());
cmd = "mkdir -p " + DEFAULT_TEST_PATH_2;
system(cmd.c_str());
cmd = "mkdir -p " + DEFAULT_TEST_PATH_3;
system(cmd.c_str());
sort(expectFileList.begin(), expectFileList.end());
}
void TearDown() override
{
cmpFileList.clear();
}
void OnPluginAddedStub(const std::string& path)
{
cmpFileList.push_back(path);
sort(cmpFileList.begin(), cmpFileList.end());
}
void OnPluginRemovedStub(const std::string& path)
{
for (auto iter = cmpFileList.cbegin(); iter != cmpFileList.cend(); iter++) {
if (*iter == path) {
cmpFileList.erase(iter);
break;
}
}
}
void CreateFile(std::string dirPath) const
{
for (auto it : createFileList) {
int fd = creat((dirPath + it).c_str(), DEAFULT_FILE_MODE);
close(fd);
}
}
void AddFile(std::string dirPath) const
{
for (auto it : addFileList) {
int fd = creat((dirPath + it).c_str(), DEAFULT_FILE_MODE);
if (fd < 0) {
return;
}
write(fd, "testcase", 1);
close(fd);
}
}
void DeleteFile(std::string dirPath) const
{
for (auto it : createFileList) {
remove((dirPath + it).c_str());
}
for (auto it : addFileList) {
remove((dirPath + it).c_str());
}
}
bool CheckFileList(std::string dirPath) const
{
if (cmpFileList.size() != expectFileList.size()) {
return false;
}
for (size_t i = 0; i < cmpFileList.size(); i++) {
if (cmpFileList.at(i) != (dirPath + expectFileList.at(i))) {
return false;
}
}
return true;
}
private:
std::vector<std::string> cmpFileList;
const std::vector<std::string> createFileList = {
"lib_6.so", "lib_5.so", "lib_8.so", "lib_4.so", "test1.txt"
};
const std::vector<std::string> addFileList = {
"libadd_6.so", "libadd_5.so", "libadd_8.so", "libadd_4.so", "test2.txt"
};
std::vector<std::string> expectFileList = {
"libadd_6.so", "libadd_5.so", "libadd_8.so", "libadd_4.so",
"lib_6.so", "lib_5.so", "lib_8.so", "lib_4.so"
};
};
class MockPluginWatcher : public PluginWatcher {
@ -70,82 +148,9 @@ public:
MOCK_METHOD1(OnPluginRemoved, void(const std::string&));
};
static void OnPluginAddedStub(const std::string& path)
{
g_cmpFileList.push_back(path);
sort(g_cmpFileList.begin(), g_cmpFileList.end());
return;
}
static void OnPluginRemovedStub(const std::string& path)
{
for (auto iter = g_cmpFileList.cbegin(); iter != g_cmpFileList.cend(); iter++) {
if (*iter == path) {
g_cmpFileList.erase(iter);
break;
}
}
return;
}
static void CreateFile()
{
for (auto it : g_createFileList) {
int fd = creat(it.c_str(), g_defaultFileMode);
g_createFdList.push_back(fd);
}
}
static void AddFile()
{
for (auto it : g_addFileList) {
int fd = creat(it.c_str(), g_defaultFileMode);
if (fd < 0) {
return;
}
write(fd, "testcase", 1);
close(fd);
}
return;
}
static void DeleteFile()
{
for (auto it : g_createFileList) {
for (auto fd : g_createFdList) {
close(fd);
}
remove(it.c_str());
}
for (auto it : g_addFileList) {
remove(it.c_str());
}
return;
}
static bool CheckFileList()
{
sort(g_expectFileList.begin(), g_expectFileList.end());
if (g_expectFileList.size() != g_cmpFileList.size()) {
return false;
}
for (size_t i = 0; i < g_expectFileList.size(); i++) {
char fullpath[PATH_MAX + 1] = {0};
realpath(g_expectFileList.at(i).c_str(), fullpath);
if (g_cmpFileList.at(i) != fullpath) {
return false;
}
}
return true;
}
/**
* @tc.name: plugin
* @tc.desc: Monitor the plugin loading in the test directory.
* @tc.desc: Monitor single plugin dir.
* @tc.type: FUNC
*/
HWTEST_F(PluginWatchTest, SingleWatchDirTest, TestSize.Level1)
@ -153,32 +158,81 @@ HWTEST_F(PluginWatchTest, SingleWatchDirTest, TestSize.Level1)
auto pluginManage = std::make_shared<PluginManager>();
MockPluginWatcher watcher(pluginManage);
EXPECT_CALL(watcher, OnPluginAdded(testing::_)).WillRepeatedly(testing::Invoke(OnPluginAddedStub));
EXPECT_CALL(watcher, OnPluginRemoved(testing::_)).WillRepeatedly(testing::Invoke(OnPluginRemovedStub));
EXPECT_CALL(watcher, OnPluginAdded(testing::_)).WillRepeatedly(
testing::Invoke(this, &PluginWatchTest::OnPluginAddedStub));
EXPECT_CALL(watcher, OnPluginRemoved(testing::_)).WillRepeatedly(
testing::Invoke(this, &PluginWatchTest::OnPluginRemovedStub));
CreateFile(DEFAULT_TEST_PATH_1);
g_createFdList.clear();
CreateFile();
watcher.ScanPlugins(DEFAULT_TEST_PATH);
watcher.WatchPlugins(DEFAULT_TEST_PATH);
EXPECT_TRUE(watcher.ScanPlugins(DEFAULT_TEST_PATH_1));
EXPECT_TRUE(watcher.WatchPlugins(DEFAULT_TEST_PATH_1));
usleep(TEMP_DELAY);
AddFile();
AddFile(DEFAULT_TEST_PATH_1);
usleep(TEMP_DELAY);
EXPECT_EQ(CheckFileList(), false);
DeleteFile();
EXPECT_EQ(CheckFileList(DEFAULT_TEST_PATH_1), true);
DeleteFile(DEFAULT_TEST_PATH_1);
usleep(TEMP_DELAY);
EXPECT_EQ(g_cmpFileList.empty(), true);
EXPECT_EQ(cmpFileList.size(), 0);
}
/**
* @tc.name: plugin
* @tc.desc: Plug-in process exception test.
* @tc.desc: Monitor multi plugin dir.
* @tc.type: FUNC
*/
HWTEST_F(PluginWatchTest, OnPluginAdded, TestSize.Level1)
HWTEST_F(PluginWatchTest, MultiWatchDirTest, TestSize.Level1)
{
const auto pluginManage = std::make_shared<PluginManager>();
PluginWatcher pluginWatcher(pluginManage);
pluginWatcher.OnPluginAdded("");
pluginWatcher.OnPluginRemoved("");
auto pluginManage = std::make_shared<PluginManager>();
MockPluginWatcher watcher(pluginManage);
EXPECT_CALL(watcher, OnPluginAdded(testing::_)).WillRepeatedly(
testing::Invoke(this, &PluginWatchTest::OnPluginAddedStub));
EXPECT_CALL(watcher, OnPluginRemoved(testing::_)).WillRepeatedly(
testing::Invoke(this, &PluginWatchTest::OnPluginRemovedStub));
CreateFile(DEFAULT_TEST_PATH_1);
EXPECT_TRUE(watcher.ScanPlugins(DEFAULT_TEST_PATH_1));
EXPECT_TRUE(watcher.WatchPlugins(DEFAULT_TEST_PATH_1));
usleep(TEMP_DELAY);
AddFile(DEFAULT_TEST_PATH_1);
usleep(TEMP_DELAY);
EXPECT_EQ(CheckFileList(DEFAULT_TEST_PATH_1), true);
DeleteFile(DEFAULT_TEST_PATH_1);
usleep(TEMP_DELAY);
EXPECT_EQ(cmpFileList.size(), 0);
CreateFile(DEFAULT_TEST_PATH_2);
EXPECT_TRUE(watcher.ScanPlugins(DEFAULT_TEST_PATH_2));
EXPECT_TRUE(watcher.WatchPlugins(DEFAULT_TEST_PATH_2));
usleep(TEMP_DELAY);
AddFile(DEFAULT_TEST_PATH_2);
usleep(TEMP_DELAY);
EXPECT_EQ(CheckFileList(DEFAULT_TEST_PATH_2), true);
DeleteFile(DEFAULT_TEST_PATH_2);
usleep(TEMP_DELAY);
EXPECT_EQ(cmpFileList.size(), 0);
CreateFile(DEFAULT_TEST_PATH_3);
EXPECT_TRUE(watcher.ScanPlugins(DEFAULT_TEST_PATH_3));
EXPECT_TRUE(watcher.WatchPlugins(DEFAULT_TEST_PATH_3));
usleep(TEMP_DELAY);
AddFile(DEFAULT_TEST_PATH_3);
usleep(TEMP_DELAY);
EXPECT_EQ(CheckFileList(DEFAULT_TEST_PATH_3), true);
DeleteFile(DEFAULT_TEST_PATH_3);
usleep(TEMP_DELAY);
EXPECT_EQ(cmpFileList.size(), 0);
}
/**
* @tc.name: plugin
* @tc.desc: Exception test.
* @tc.type: FUNC
*/
HWTEST_F(PluginWatchTest, ExceptionTest, TestSize.Level1)
{
auto pluginManage = std::make_shared<PluginManager>();
MockPluginWatcher watcher(pluginManage);
EXPECT_FALSE(watcher.ScanPlugins(NO_EXIST_TEST_PATH));
EXPECT_FALSE(watcher.WatchPlugins(NO_EXIST_TEST_PATH));
}
} // namespace

View File

@ -1,118 +0,0 @@
/*
* Copyright (c) 2021 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 <hwext/gtest-ext.h>
#include <hwext/gtest-tag.h>
#include <thread>
#include "client_map.h"
#include "plugin_service.ipc.h"
#include "service_entry.h"
#include "socket_context.h"
#include "unix_socket_client.h"
#include "unix_socket_server.h"
using namespace testing::ext;
namespace {
class ServicesIpcTest : public ::testing::Test {
protected:
static constexpr auto TEMP_DELAY = std::chrono::milliseconds(10);
static void SetUpTestCase() {}
static void TearDownTestCase() {}
};
/**
* @tc.name: ipc
* @tc.desc: Socket send/recv interface.
* @tc.type: FUNC
*/
HWTEST_F(ServicesIpcTest, ProtocolProc, TestSize.Level1)
{
ServiceBase serviceBase;
SocketContext socketContext;
ASSERT_FALSE(serviceBase.ProtocolProc(socketContext, 0, nullptr, 0));
ASSERT_TRUE(!socketContext.SendRaw(-1, nullptr, 0, 0));
ASSERT_TRUE(!socketContext.SendFileDescriptor(-1));
ASSERT_EQ(socketContext.ReceiveFileDiscriptor(), -1);
ASSERT_EQ(socketContext.RawProtocolProc(-1, nullptr, -1), -1);
}
/**
* @tc.name: ipc
* @tc.desc: Client link.
* @tc.type: FUNC
*/
HWTEST_F(ServicesIpcTest, ClientSocket, TestSize.Level1)
{
ServiceEntry serviceEntry;
ClientMap::GetInstance().PutClientSocket(0, serviceEntry);
ASSERT_EQ(ClientMap::GetInstance().AutoRelease(), 1);
ClientConnection* clientConnection = new ClientConnection(0, serviceEntry);
ASSERT_EQ(clientConnection->RawProtocolProc(-1, nullptr, 0), -1);
}
/**
* @tc.name: plugin
* @tc.desc: Abnormal client link.
* @tc.type: FUNC
*/
HWTEST_F(ServicesIpcTest, unixSocketClient, TestSize.Level1)
{
UnixSocketClient unixSocketClient;
ServiceBase serviceBase;
ASSERT_TRUE(!unixSocketClient.Connect("asdf", serviceBase));
}
/**
* @tc.name: plugin
* @tc.desc: Start unixSocket Server.
* @tc.type: FUNC
*/
HWTEST_F(ServicesIpcTest, UnixSocketServer, TestSize.Level1)
{
UnixSocketServer unixSocketServer;
unixSocketServer.UnixSocketAccept(nullptr);
ServiceEntry serviceEntry;
ASSERT_TRUE(unixSocketServer.StartServer("", serviceEntry));
}
/**
* @tc.name: plugin
* @tc.desc: Server process monitoring.
* @tc.type: FUNC
*/
HWTEST_F(ServicesIpcTest, ServiceEntry, TestSize.Level1)
{
ServiceEntry serviceEntry;
IPluginServiceServer pluginService;
serviceEntry.StartServer("test_unix_socket_service_entry");
serviceEntry.RegisterService(pluginService);
serviceEntry.FindServiceByName(pluginService.serviceName_);
std::this_thread::sleep_for(TEMP_DELAY);
GetTimeMS();
GetTimeUS();
GetTimeNS();
IPluginServiceClient pluginClient;
ASSERT_FALSE(pluginClient.Connect(""));
std::this_thread::sleep_for(TEMP_DELAY);
}
} // namespace

View File

@ -1,80 +0,0 @@
/*
* Copyright (c) 2021 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 <hwext/gtest-ext.h>
#include <hwext/gtest-tag.h>
#include "plugin_service.h"
#include "plugin_session.h"
#include "profiler_data_repeater.h"
using namespace testing::ext;
using PluginServicePtr = STD_PTR(shared, PluginService);
class ServicesPluginServiceTest : public ::testing::Test {
protected:
static void SetUpTestCase() {}
static void TearDownTestCase() {}
};
/**
* @tc.name: plugin
* @tc.desc: Session flow test, get session id by plugin name.
* @tc.type: FUNC
*/
HWTEST_F(ServicesPluginServiceTest, PluginService1, TestSize.Level1)
{
PluginServicePtr pluginService = std::make_shared<PluginService>();
ProfilerPluginConfig ppc;
ppc.set_name("abc.so");
ppc.set_plugin_sha256("ASDFAADSF");
ppc.set_sample_interval(20);
pluginService->CreatePluginSession(ppc, std::make_shared<ProfilerDataRepeater>(4096));
pluginService->StartPluginSession(ppc);
pluginService->StopPluginSession("abc.so");
pluginService->DestroyPluginSession("abc.so");
pluginService->GetPluginIdByName("abc.so");
}
/**
* @tc.name: plugin
* @tc.desc: Session flow test, get plugin status.
* @tc.type: FUNC
*/
HWTEST_F(ServicesPluginServiceTest, PluginService2, TestSize.Level1)
{
PluginServicePtr pluginService = std::make_shared<PluginService>();
ProfilerPluginConfig ppc;
ppc.set_name("abc.so");
ppc.set_plugin_sha256("ASDFAADSF");
ppc.set_sample_interval(20);
ProfilerSessionConfig::BufferConfig bc;
bc.set_pages(1);
bc.set_policy(ProfilerSessionConfig_BufferConfig_Policy_RECYCLE);
pluginService->CreatePluginSession(ppc, bc, std::make_shared<ProfilerDataRepeater>(4096));
pluginService->StartPluginSession(ppc);
pluginService->StopPluginSession("abc.so");
pluginService->GetPluginStatus();
PluginInfo pi;
pi.id = 0;
pi.name = "abc.so";
pi.path = "abc.so";
pi.sha256 = "asdfasdf";
pluginService->RemovePluginInfo(pi);
}

View File

@ -1,435 +0,0 @@
/*
* Copyright (c) 2021 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 <hwext/gtest-ext.h>
#include <hwext/gtest-tag.h>
#include "logging.h"
#include "plugin_service.h"
#include "plugin_session.h"
#include "profiler_capability_manager.h"
#include "profiler_data_repeater.h"
#include "profiler_service.h"
#include "result_demuxer.h"
#include "trace_file_reader.h"
#include "trace_file_writer.h"
using namespace testing::ext;
namespace {
#if defined(__i386__) || defined(__x86_64__)
const std::string DEFAULT_TEST_PATH("./");
#else
const std::string DEFAULT_TEST_PATH("/data/local/tmp/");
#endif
using PluginServicePtr = STD_PTR(shared, PluginService);
using ProfilerDataRepeaterPtr = STD_PTR(shared, ProfilerDataRepeater);
using ProfilerServicePtr = STD_PTR(shared, ProfilerService);
using ProfilerPluginDataPtr = STD_PTR(shared, ProfilerPluginData);
constexpr int DATA_MAX_SIZE = 10;
class ServicesProfilerServiceTest : public ::testing::Test {
protected:
ProfilerPluginConfig config;
ProfilerSessionConfig::BufferConfig bufferConfig;
PluginInfo pluginInfo;
PluginServicePtr service;
ProfilerDataRepeaterPtr repeater;
ProfilerServicePtr service_;
std::unique_ptr<grpc::ServerContext> context_;
std::atomic<int> requestCounter{0};
static void SetUpTestCase() {}
static void TearDownTestCase() {}
void SetUp() override
{
config.set_name("test_session");
bufferConfig.set_pages(0);
pluginInfo.name = config.name();
service = std::make_shared<PluginService>();
repeater = std::make_shared<ProfilerDataRepeater>(DATA_MAX_SIZE);
if (service) {
service->AddPluginInfo(pluginInfo);
}
service_ = std::make_shared<ProfilerService>(service);
context_ = std::make_unique<grpc::ServerContext>();
}
void TearDown() override
{
if (service) {
service->RemovePluginInfo(pluginInfo);
}
ProfilerCapabilityManager::GetInstance().pluginCapabilities_.clear();
}
};
/**
* @tc.name: plugin
* @tc.desc: Plugin session flow test.
* @tc.type: FUNC
*/
HWTEST_F(ServicesProfilerServiceTest, PluginSession, TestSize.Level1)
{
auto session = std::make_shared<PluginSession>(config, nullptr, nullptr);
EXPECT_NE(session, nullptr);
EXPECT_FALSE(session->IsAvailable());
EXPECT_FALSE(session->Create());
config.set_name("test_session2");
session = std::make_shared<PluginSession>(config, service, repeater);
repeater->Size();
session.reset();
config.set_name("test_session3");
session = std::make_shared<PluginSession>(config, service, repeater);
ASSERT_NE(session->GetState(), PluginSession::CREATED);
EXPECT_FALSE(session->Start());
ASSERT_NE(session->GetState(), PluginSession::STARTED);
EXPECT_FALSE(session->Stop());
ASSERT_NE(session->GetState(), PluginSession::CREATED);
EXPECT_FALSE(session->Destroy());
EXPECT_EQ(session->GetState(), PluginSession::INITIAL);
// recreate is OK
EXPECT_FALSE(session->Create());
EXPECT_FALSE(session->Destroy());
repeater->Reset();
}
/**
* @tc.name: plugin
* @tc.desc: Streaming session test.
* @tc.type: FUNC
*/
HWTEST_F(ServicesProfilerServiceTest, TraceFileWriter, TestSize.Level1)
{
std::string path = "trace.bin";
auto writer = std::make_shared<TraceFileWriter>(path);
EXPECT_NE(writer, nullptr);
std::string testData = "Hello, Wrold!";
EXPECT_EQ(writer->Write(testData.data(), testData.size()), sizeof(uint32_t) + testData.size());
EXPECT_EQ(writer->Flush(), true);
ProfilerPluginData pluginData;
pluginData.set_name("ABC");
pluginData.set_status(0);
pluginData.set_data("DEF");
EXPECT_GT(writer->Write(pluginData), 0);
}
/**
* @tc.name: plugin
* @tc.desc: Streaming session test.
* @tc.type: FUNC
*/
HWTEST_F(ServicesProfilerServiceTest, TraceFileReader, TestSize.Level1)
{
std::string path = "trace-write-msg.bin";
auto writer = std::make_shared<TraceFileWriter>(path);
ASSERT_NE(writer, nullptr);
constexpr int n = 100;
for (int i = 1; i <= n; i++) {
ProfilerPluginData pluginData{};
pluginData.set_name("test_name");
pluginData.set_status(i);
pluginData.set_data("Hello, Wrold!");
long bytes = writer->Write(pluginData);
EXPECT_EQ(bytes, sizeof(uint32_t) + pluginData.ByteSizeLong());
HILOG_INFO(LOG_CORE, "[%d/%d] write %ld bytes to %s.", i, n, bytes, path.c_str());
}
writer.reset(); // make sure write done!
auto reader = std::make_shared<TraceFileReader>();
ASSERT_NE(reader, nullptr);
ASSERT_TRUE(reader->Open(path));
for (int i = 1; i <= n; i++) {
ProfilerPluginData data{};
long bytes = reader->Read(data);
HILOG_INFO(LOG_CORE, "data = {%s, %d, %s}", data.name().c_str(), data.status(), data.data().c_str());
HILOG_INFO(LOG_CORE, "read %ld bytes from %s", bytes, path.c_str());
}
ASSERT_TRUE(reader->Open(path));
long bytes = 0;
do {
ProfilerPluginData data{};
bytes = reader->Read(data);
HILOG_INFO(LOG_CORE, "data = {%s, %d, %s}", data.name().c_str(), data.status(), data.data().c_str());
HILOG_INFO(LOG_CORE, "read %ld bytes from %s", bytes, path.c_str());
} while (bytes > 0);
ASSERT_EQ(reader->Read(nullptr, 0), 0);
}
/**
* @tc.name: service
* @tc.desc: Streaming session report result test.
* @tc.type: FUNC
*/
HWTEST_F(ServicesProfilerServiceTest, ResultDemuxer1, TestSize.Level1)
{
std::string path = "demux.bin";
ProfilerDataRepeaterPtr repeater = std::make_shared<ProfilerDataRepeater>(DATA_MAX_SIZE);
auto demuxer = std::make_shared<ResultDemuxer>(repeater);
EXPECT_NE(demuxer, nullptr);
demuxer->SetTraceWriter(nullptr);
auto writer = std::make_shared<TraceFileWriter>(path);
EXPECT_NE(writer, nullptr);
demuxer->SetTraceWriter(writer);
const int putCount = 20;
const int putDelayUs = 10 * 1000;
demuxer->StartTakeResults();
std::thread dataProducer([=] {
for (int i = 0; i < putCount; i++) {
auto pluginData = std::make_shared<ProfilerPluginData>();
ASSERT_NE(pluginData, nullptr);
pluginData->set_name("test-" + std::to_string(i));
pluginData->set_status(i);
repeater->PutPluginData(pluginData);
HILOG_DEBUG(LOG_CORE, "put test data %d...", i);
usleep(putDelayUs);
}
repeater->PutPluginData(nullptr);
});
HILOG_DEBUG(LOG_CORE, "wating producer thread done...");
dataProducer.join();
}
/**
* @tc.name: service
* @tc.desc: Streaming session report result test.
* @tc.type: FUNC
*/
HWTEST_F(ServicesProfilerServiceTest, ResultDemuxer2, TestSize.Level1)
{
std::string path = "demux.bin";
ProfilerDataRepeaterPtr repeater = std::make_shared<ProfilerDataRepeater>(DATA_MAX_SIZE);
auto demuxer = std::make_shared<ResultDemuxer>(repeater);
ASSERT_NE(demuxer, nullptr);
auto writer = std::make_shared<TraceFileWriter>(path);
EXPECT_NE(writer, nullptr);
demuxer->SetTraceWriter(writer);
const int putCount = 30;
const int putDelayUs = 10 * 1000;
demuxer->StartTakeResults();
std::thread dataProducer([=] {
for (int i = 0; i < putCount; i++) {
auto pluginData = std::make_shared<ProfilerPluginData>();
ASSERT_NE(pluginData, nullptr);
pluginData->set_name("AB-" + std::to_string(i));
pluginData->set_status(i);
HILOG_DEBUG(LOG_CORE, "put test data %d...", i);
if (!repeater->PutPluginData(pluginData)) {
HILOG_WARN(LOG_CORE, "put test data %d FAILED!", i);
break;
}
usleep(putDelayUs);
}
});
usleep((putCount / 2) * putDelayUs);
demuxer->StopTakeResults();
repeater->Close();
HILOG_DEBUG(LOG_CORE, "wating producer thread done...");
dataProducer.join();
}
/**
* @tc.name: server
* @tc.desc: Profiler capacity management.
* @tc.type: FUNC
*/
HWTEST_F(ServicesProfilerServiceTest, ProfilerCapabilityManager, TestSize.Level1)
{
std::vector<ProfilerPluginCapability> caps = ProfilerCapabilityManager::GetInstance().GetCapabilities();
for (int i = 0; i < caps.size(); i++) {
auto cap = caps[i];
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().RemoveCapability(cap.name()));
}
caps.clear();
EXPECT_EQ(ProfilerCapabilityManager::GetInstance().GetCapability("xxx"), nullptr);
EXPECT_EQ(ProfilerCapabilityManager::GetInstance().GetCapabilities().size(), 0);
caps = ProfilerCapabilityManager::GetInstance().GetCapabilities();
EXPECT_EQ(caps.size(), 0);
const int n = 10;
for (int i = 0; i < n; i++) {
ProfilerPluginCapability cap;
cap.set_path("/system/lib/libcap_" + std::to_string(i) + ".so");
cap.set_name("cap_" + std::to_string(i));
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().AddCapability(cap));
EXPECT_EQ(ProfilerCapabilityManager::GetInstance().GetCapabilities().size(), i + 1);
}
for (int i = 0; i < n; i++) {
ProfilerPluginCapability cap;
cap.set_name("cap_" + std::to_string(i));
auto capPtr = ProfilerCapabilityManager::GetInstance().GetCapability(cap.name());
ASSERT_NE(capPtr, nullptr);
EXPECT_EQ(capPtr->name(), cap.name());
}
ProfilerPluginCapability cap1;
cap1.set_path("/system/lib/libcap1.so");
cap1.set_name("cap1");
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().AddCapability(cap1));
cap1.set_path("/system/lib/libcap2.so");
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().UpdateCapability(cap1.name(), cap1));
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().RemoveCapability(cap1.name()));
caps = ProfilerCapabilityManager::GetInstance().GetCapabilities();
EXPECT_EQ(caps.size(), n);
for (int i = 0; i < caps.size(); i++) {
auto cap = caps[i];
EXPECT_TRUE(ProfilerCapabilityManager::GetInstance().RemoveCapability(cap.name()));
EXPECT_EQ(ProfilerCapabilityManager::GetInstance().GetCapabilities().size(), n - (i + 1));
}
}
/**
* @tc.name: server
* @tc.desc: Profiler data repeater.
* @tc.type: FUNC
*/
HWTEST_F(ServicesProfilerServiceTest, ProfilerDataRepeater, TestSize.Level1)
{
const int itemCounts = 10000;
const int bufferSize = itemCounts;
auto inDataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
ASSERT_NE(inDataRepeater, nullptr);
auto outDataRepeater = std::make_shared<ProfilerDataRepeater>(bufferSize);
ASSERT_NE(outDataRepeater, nullptr);
auto f = [](int x) { return 2 * x + 1; };
std::thread worker([&]() {
for (int i = 0; i < itemCounts; i++) {
auto xData = inDataRepeater->TakePluginData();
// compute in worker thread
int x = xData ? std::stoi(xData->data()) : 0;
int y = f(x);
auto yData = std::make_shared<ProfilerPluginData>();
yData->set_data(std::to_string(y));
outDataRepeater->PutPluginData(yData);
}
});
std::vector<int> yVec;
for (int i = 0; i < itemCounts; i++) {
int x0 = i;
auto xData = std::make_shared<ProfilerPluginData>();
xData->set_data(std::to_string(x0));
inDataRepeater->PutPluginData(xData);
int y0 = f(x0);
yVec.push_back(y0);
}
worker.join();
std::vector<ProfilerPluginDataPtr> pluginDataVec;
auto count = outDataRepeater->TakePluginData(pluginDataVec);
EXPECT_EQ(count, yVec.size());
for (size_t i = 0; i < pluginDataVec.size(); i++) {
auto yData = pluginDataVec[i];
int y = yData ? std::stoi(yData->data()) : 0;
EXPECT_EQ(y, yVec[i]);
}
}
/**
* @tc.name: server
* @tc.desc: Session flow test.
* @tc.type: FUNC
*/
HWTEST_F(ServicesProfilerServiceTest, ProfilerService1, TestSize.Level1)
{
ASSERT_NE(service_, nullptr);
ASSERT_NE(context_, nullptr);
GetCapabilitiesRequest request;
GetCapabilitiesResponse response;
ProfilerPluginCapability cap;
cap.set_name("cap1");
ProfilerCapabilityManager::GetInstance().AddCapability(cap);
request.set_request_id(++requestCounter);
auto status = service_->GetCapabilities(context_.get(), &request, &response);
EXPECT_EQ(status.error_code(), grpc::StatusCode::OK);
EXPECT_GT(response.capabilities_size(), 0);
HILOG_DEBUG(LOG_CORE, "GetCapabilities, capabilities_size = %d", response.capabilities_size());
}
/**
* @tc.name: server
* @tc.desc: Session flow test.
* @tc.type: FUNC
*/
HWTEST_F(ServicesProfilerServiceTest, ProfilerService2, TestSize.Level1)
{
ASSERT_NE(service_, nullptr);
ASSERT_NE(context_, nullptr);
CreateSessionRequest request;
CreateSessionResponse response;
auto status = service_->CreateSession(context_.get(), &request, &response);
EXPECT_NE(status.error_code(), grpc::StatusCode::OK);
StartSessionRequest startrequest;
StartSessionResponse startresponse;
startrequest.set_session_id(0);
startrequest.set_request_id(++requestCounter);
status = service_->StartSession(context_.get(), &startrequest, &startresponse);
EXPECT_NE(status.error_code(), grpc::StatusCode::OK);
StopSessionRequest stoprequest;
StopSessionResponse stopresponse;
stoprequest.set_session_id(0);
stoprequest.set_request_id(++requestCounter);
status = service_->StopSession(context_.get(), &stoprequest, &stopresponse);
EXPECT_NE(status.error_code(), grpc::StatusCode::OK);
DestroySessionRequest destroyrequest;
DestroySessionResponse destroyresponse;
destroyrequest.set_session_id(0);
destroyrequest.set_request_id(++requestCounter);
status = service_->DestroySession(context_.get(), &destroyrequest, &destroyresponse);
EXPECT_NE(status.error_code(), grpc::StatusCode::OK);
}
} // namespace

View File

@ -1,86 +0,0 @@
/*
* Copyright (c) 2021 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 <hwext/gtest-ext.h>
#include <hwext/gtest-tag.h>
#include <thread>
#include "plugin_service_types.pb.h"
#include "share_memory_allocator.h"
#include "share_memory_block.h"
using namespace testing::ext;
namespace {
class ServicesSharedMemoryTest : public ::testing::Test {
protected:
static void SetUpTestCase() {}
static void TearDownTestCase() {}
};
/**
* @tc.name: server
* @tc.desc: Shared memory flow test.
* @tc.type: FUNC
*/
HWTEST_F(ServicesSharedMemoryTest, SharedMemoryBlock, TestSize.Level1)
{
ShareMemoryBlock shareMemoryBlock;
ASSERT_TRUE(shareMemoryBlock.CreateBlock("testname", 1024));
shareMemoryBlock.GetName();
shareMemoryBlock.GetSize();
shareMemoryBlock.GetfileDescriptor();
shareMemoryBlock.SetDropType(ShareMemoryBlock::DropType::DROP_NONE);
int8_t data[100];
for (int i = 0; i < 20; i++) {
*((uint32_t*)data) = i;
shareMemoryBlock.PutRaw(data, 100);
}
int8_t* p = shareMemoryBlock.GetFreeMemory(100);
ASSERT_TRUE(p == nullptr);
do {
p = const_cast<int8_t*>(shareMemoryBlock.GetDataPoint());
printf("%p,p=%d\n", p, *((int*)p));
} while (shareMemoryBlock.Next() && shareMemoryBlock.GetDataSize() > 0);
NotifyResultResponse response;
response.set_status(123);
ASSERT_TRUE(shareMemoryBlock.PutProtobuf(response));
ASSERT_TRUE(shareMemoryBlock.GetDataSize() > 0);
response.ParseFromArray(shareMemoryBlock.GetDataPoint(), shareMemoryBlock.GetDataSize());
ASSERT_TRUE(response.status() == 123);
ASSERT_TRUE(shareMemoryBlock.ReleaseBlock());
}
/**
* @tc.name: server
* @tc.desc: Shared memory abnormal flow test.
* @tc.type: FUNC
*/
HWTEST_F(ServicesSharedMemoryTest, SharedMemoryAllocator, TestSize.Level1)
{
ASSERT_TRUE(ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal("testname", 1) ==
nullptr); // 创建内存块大小<1024返回空
ASSERT_TRUE(ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal("testname", 1024) != nullptr); // 成功创建
ASSERT_TRUE(ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal("testname", 1024) ==
nullptr); // 创建同名内存块返回空
ASSERT_TRUE(ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockLocal("testname"));
ASSERT_FALSE(ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockLocal("or")); // 释放不存在的内存块返回-1
}
} // namespace

View File

@ -34,8 +34,8 @@ protected:
HWTEST_F(WriterAdapterTest, Writer, TestSize.Level1)
{
WriterAdapter writerAdapter;
writerAdapter.GetWriter();
writerAdapter.GetStruct();
EXPECT_EQ(writerAdapter.GetWriter(), nullptr);
EXPECT_EQ(writerAdapter.GetStruct(), &writerAdapter.writerStruct_);
}
/**
@ -46,7 +46,7 @@ HWTEST_F(WriterAdapterTest, Writer, TestSize.Level1)
HWTEST_F(WriterAdapterTest, Func, TestSize.Level1)
{
WriterAdapter writerAdapter;
writerAdapter.WriteFunc(nullptr, nullptr, 0);
writerAdapter.FlushFunc(nullptr);
EXPECT_EQ(writerAdapter.WriteFunc(nullptr, nullptr, 0), 0);
EXPECT_FALSE(writerAdapter.FlushFunc(nullptr));
}
} // namespace

18
device/plugins/bytrace_plugin/BUILD.gn Executable file → Normal file
View File

@ -10,7 +10,6 @@
# 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/ohos.gni")
import("../../base/config.gni")
@ -27,14 +26,13 @@ config("bytraceplugin_config") {
ohos_shared_library("bytraceplugin") {
output_name = "bytraceplugin"
sources = [
"src/bytrace_module.cpp",
]
sources = [ "src/bytrace_module.cpp" ]
public_configs = [ ":bytraceplugin_config" ]
public_deps = [
"${OHOS_PROFILER_DIR}/protos/types/plugins/bytrace_plugin:bytrace_plugin_protos_cpp",
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc_lib",
"${OHOS_PROFILER_DIR}/protos/types/plugins/bytrace_plugin:bytrace_plugin_protos_cpp",
"//utils/native/base:utilsecurec",
]
if (current_toolchain != host_toolchain) {
defines = [ "HAVE_HILOG" ]
@ -48,14 +46,10 @@ ohos_shared_library("bytraceplugin") {
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
}
ohos_executable("test_bytraceplugin") {
ohos_executable("test_bytrace_plugin") {
output_name = "test_bytraceplugin"
sources = [
"src/run_test.cpp",
]
deps = [
":bytraceplugin",
]
sources = [ "src/run_test.cpp" ]
deps = [ ":bytraceplugin" ]
install_enable = true
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
}

5
device/plugins/bytrace_plugin/include/bytrace_module.h Executable file → Normal file
View File

@ -16,13 +16,12 @@
#ifndef BYTRACE_MODULE_H
#define BYTRACE_MODULE_H
#include <stdint.h>
#include "plugin_module_api.h"
int BytracePluginSessionStart(const uint8_t* configData, const uint32_t configSize);
int BytraceRegisterWriterStruct(WriterStruct* writer);
int BytraceRegisterWriterStruct(const WriterStruct* writer);
int BytracePluginSessionStop();
int BytracePluginSessionStop(void);
#endif // BYTRACE_MODULE_H

View File

@ -12,9 +12,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bytrace_module.h"
#include <array>
#include <poll.h>
#include <sys/stat.h>
#include <sys/types.h>
@ -27,101 +27,136 @@
#include "securec.h"
namespace {
const std::string CMD_PATH = "/system/bin/bytrace";
int g_processNum = -1;
constexpr uint32_t MAX_BUFFER_SIZE = 4 * 1024 * 1024;
constexpr uint32_t READ_BUFFER_SIZE = 4096;
const std::string DEFAULT_FILE = "/local/data/tmp/bytrace.txt";
bool RunWithConfig(const BytracePluginConfig& config)
std::mutex g_taskMutex;
struct BytraceInfo {
bool isRoot;
uint32_t buffSize;
uint32_t time;
std::string clockType;
std::string outFile;
std::vector<std::string> categoryVec;
};
std::unique_ptr<BytraceInfo> g_bytraceInfo = nullptr;
void ParseConfig(const BytracePluginConfig& config)
{
std::vector<std::string> args;
args.push_back("bytrace");
if (config.buffe_size() != 0) {
args.push_back("-b");
args.push_back(std::to_string(config.buffe_size()));
}
if (config.time() != 0) {
args.push_back("-t");
args.push_back(std::to_string(config.time()));
g_bytraceInfo->buffSize = config.buffe_size();
}
g_bytraceInfo->time = config.time();
g_bytraceInfo->isRoot = config.is_root();
if (!config.clock().empty()) {
args.push_back("--trace_clock");
args.push_back(config.clock());
g_bytraceInfo->clockType = config.clock();
}
if (!config.outfile_name().empty()) {
args.push_back("-o");
args.push_back(config.outfile_name());
g_bytraceInfo->outFile = config.outfile_name();
}
if (!config.categories().empty()) {
for (std::string category : config.categories()) {
args.push_back(category);
g_bytraceInfo->categoryVec.push_back(category);
}
}
}
std::vector<char*> params;
std::string cmdPrintStr = "";
for (std::string& it : args) {
cmdPrintStr += (it + " ");
params.push_back(const_cast<char*>(it.c_str()));
bool RunCommand(const std::string& cmd)
{
HILOG_INFO(LOG_CORE, "BytraceCall::start running commond: %s", cmd.c_str());
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.data(), "r"), pclose);
CHECK_TRUE(pipe, false, "BytraceCall::RunCommand: create popen FAILED!");
if (g_bytraceInfo->time == 0) {
return true;
}
params.push_back(nullptr);
HILOG_INFO(LOG_CORE, "call bytrace::Run: %s", cmdPrintStr.c_str());
execv(CMD_PATH.data(), &params[0]);
std::array<char, READ_BUFFER_SIZE> buffer;
std::string result;
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
HILOG_INFO(LOG_CORE, "BytraceCall::RunCommand result: %s", result.data());
return true;
}
bool BeginTrace()
{
// two case: real-time and offline type.
std::string beginCmd;
if (g_bytraceInfo->isRoot) {
beginCmd = "su root ";
}
beginCmd += "bytrace ";
if (g_bytraceInfo->buffSize != 0) {
beginCmd += " -b " + std::to_string(g_bytraceInfo->buffSize);
}
if (!g_bytraceInfo->clockType.empty()) {
beginCmd += " --trace_clock " + g_bytraceInfo->clockType;
}
// real-time: time is set 0.
if (g_bytraceInfo->time == 0) {
// if time is not set 1s(must >= 1), bytrace tool will use 5s by dafault.
beginCmd += " -t 1 ";
beginCmd += " --trace_begin ";
} else {
beginCmd += " -t " + std::to_string(g_bytraceInfo->time);
beginCmd += " -o ";
beginCmd += g_bytraceInfo->outFile;
beginCmd += " ";
}
for (const std::string& category : g_bytraceInfo->categoryVec) {
beginCmd += category;
beginCmd += " ";
}
return RunCommand(beginCmd);
}
bool StopTrace()
{
std::string finishCmd;
if (g_bytraceInfo->isRoot) {
finishCmd = "su root ";
}
finishCmd += "bytrace --trace_finish --trace_dump";
if (g_bytraceInfo->outFile.empty()) {
g_bytraceInfo->outFile = DEFAULT_FILE;
}
finishCmd += " -o ";
finishCmd += g_bytraceInfo->outFile;
return RunCommand(finishCmd);
}
} // namespace
int BytracePluginSessionStart(const uint8_t* configData, const uint32_t configSize)
{
std::lock_guard<std::mutex> guard(g_taskMutex);
BytracePluginConfig config;
HILOG_INFO(LOG_CORE, "BytracePluginSessionStart %u", configSize);
CHECK_TRUE(config.ParseFromArray(configData, configSize), 0, "parse config FAILED!");
g_processNum = fork();
CHECK_TRUE(g_processNum >= 0, -1, "create process FAILED!");
if (g_processNum == 0) {
// child process
CHECK_TRUE(RunWithConfig(config), 0, "run bytrace FAILED!");
_exit(0);
}
return 0;
}
int BytraceRegisterWriterStruct(const WriterStruct* writer)
{
int res = config.ParseFromArray(configData, configSize);
CHECK_TRUE(res, 0, "BytracePluginSessionStart, parse config FAILED! configSize: %u", configSize);
g_bytraceInfo = std::make_unique<BytraceInfo>();
ParseConfig(config);
res = BeginTrace();
CHECK_TRUE(res, 0, "BytracePluginSessionStart, bytrace begin FAILED!");
return 0;
}
int BytracePluginSessionStop()
{
if (g_processNum > 0) {
// parent process
int status = 0;
// judge if child process have exited.
if (waitpid(g_processNum, &status, WNOHANG) == 0) {
// send SIGKILL to child process.
if (kill(g_processNum, SIGINT)) {
HILOG_WARN(LOG_CORE, "BytracePluginSessionStop kill child process failed.");
} else {
HILOG_INFO(LOG_CORE, "BytracePluginSessionStop kill child process success.");
}
}
// report child process exit status.
if (WIFEXITED(status)) {
HILOG_INFO(LOG_CORE, "child %d exit with status %d!", g_processNum,
WEXITSTATUS(static_cast<unsigned>(status)));
} else if (WIFSIGNALED(status)) {
HILOG_INFO(LOG_CORE, "child %d exit with signal %d!", g_processNum,
WTERMSIG(static_cast<unsigned>(status)));
} else if (WIFSTOPPED(status)) {
HILOG_INFO(LOG_CORE, "child %d stopped by signal %d", g_processNum,
WSTOPSIG(static_cast<unsigned>(status)));
} else {
HILOG_INFO(LOG_CORE, "child %d otherwise", g_processNum);
}
std::lock_guard<std::mutex> guard(g_taskMutex);
// real-time type nead finish trace.
if (g_bytraceInfo->time == 0) {
int res = StopTrace();
CHECK_TRUE(res, 0, "BytracePluginSessionStop, bytrace finish FAILED!");
}
g_bytraceInfo = nullptr;
return 0;
}
int BytraceRegisterWriterStruct(const WriterStruct* writer)
{
HILOG_INFO(LOG_CORE, "writer %p", writer);
return 0;
}
@ -132,4 +167,4 @@ static PluginModuleCallbacks g_callbacks = {
BytraceRegisterWriterStruct,
};
PluginModuleStruct g_pluginModule = {&g_callbacks, "bytrace_plugin", MAX_BUFFER_SIZE};
PluginModuleStruct g_pluginModule = {&g_callbacks, "bytrace_plugin", MAX_BUFFER_SIZE};

View File

@ -25,15 +25,15 @@ constexpr uint32_t BUFFE_SIZE = 1024;
int main()
{
WriterStruct writer;
BytraceRegisterWriterStruct(&writer);
BytracePluginConfig config;
config.set_outfile_name("/data/local/tmp/bytrace.txt");
config.set_clock("boot");
config.set_time(TRACE_TIME);
config.set_buffe_size(BUFFE_SIZE);
config.set_outfile_name("/data/local/tmp/bytrace.txt");
config.add_categories("sched");
config.add_categories("freq");
config.add_categories("idle");
config.add_categories("workq");
std::vector<char> buffer(config.ByteSizeLong());
CHECK_TRUE(config.SerializeToArray(buffer.data(), buffer.size()), 0, "Serialize config FAILED!");

View File

@ -0,0 +1,75 @@
# Copyright (C) 2021 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/ohos.gni")
import("../../base/config.gni")
ohos_shared_library("cpudataplugin") {
output_name = "cpudataplugin"
sources = [
"../memory_plugin/src/buffer_splitter.cpp",
"src/cpu_data_plugin.cpp",
"src/cpu_module.cpp",
]
include_dirs = [
"include",
"../memory_plugin/include",
"${OHOS_PROFILER_DIR}/interfaces/kits",
"${OHOS_PROFILER_DIR}/device/base/include",
"//utils/native/base/include",
]
deps = [
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc_lib",
"${OHOS_PROFILER_DIR}/protos/types/plugins/cpu_data:cpu_data_cpp",
"//utils/native/base:utilsecurec",
]
if (current_toolchain != host_toolchain) {
defines = [ "HAVE_HILOG" ]
if (build_l2) {
external_deps = [ "shared_library:libhilog" ]
} else {
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
}
}
public_configs = [ "${OHOS_PROFILER_DIR}/device/base:hiprofiler_test_config" ]
install_enable = true
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
}
ohos_executable("cpudataplugintest") {
output_name = "cpudataplugintest"
sources = [ "src/test_main.cpp" ]
include_dirs = [
"include",
"../api/include",
"${OHOS_PROFILER_DIR}/interfaces/kits",
"${OHOS_PROFILER_DIR}/device/base/include",
]
deps = [
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc_lib",
"${OHOS_PROFILER_DIR}/protos/types/plugins/cpu_data:cpu_data_cpp",
]
if (current_toolchain != host_toolchain) {
defines = [ "HAVE_HILOG" ]
if (build_l2) {
external_deps = [ "shared_library:libhilog" ]
} else {
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
}
}
public_configs = [ "${OHOS_PROFILER_DIR}/device/base:hiprofiler_test_config" ]
install_enable = true
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
}

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2021 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.
*/
#ifndef CPU_DATA_PLUGIN_H
#define CPU_DATA_PLUGIN_H
#include <dirent.h>
#include <fcntl.h>
#include <string>
#include <unistd.h>
#include "cpu_plugin_config.pb.h"
#include "cpu_plugin_result.pb.h"
#include "logging.h"
enum ErrorType {
RET_NULL_ADDR,
RET_IVALID_PID,
RET_TGID_VALUE_NULL,
RET_FAIL = -1,
RET_SUCC = 0,
};
enum ProcessCpuTimeType {
PROCESS_UTIME = 0,
PROCESS_STIME,
PROCESS_CUTIME,
PROCESS_CSTIME,
PROCESS_UNSPECIFIED,
};
enum SystemCpuTimeType {
SYSTEM_USER = 1,
SYSTEM_NICE,
SYSTEM_SYSTEM,
SYSTEM_IDLE,
SYSTEM_IOWAIT,
SYSTEM_IRQ,
SYSTEM_SOFTIRQ,
SYSTEM_STEAL,
SYSTEM_UNSPECIFIED,
};
class CpuDataPlugin {
public:
CpuDataPlugin();
~CpuDataPlugin();
int Start(const uint8_t* configData, uint32_t configSize);
int Report(uint8_t* configData, uint32_t configSize);
int Stop();
private:
int32_t ReadFile(std::string& fileName);
void SetTimestamp(SampleTimeStamp& timestamp);
int64_t GetUserHz();
int64_t GetCpuUsageTime(std::vector<std::string>& cpuUsageVec);
void WriteProcessCpuUsage(CpuUsageInfo& cpuUsageInfo, const char* pFile, uint32_t fileLen);
void GetSystemCpuTime(std::vector<std::string>& cpuUsageVec, int64_t& usageTime, int64_t& time);
void WriteSystemCpuUsage(CpuUsageInfo& cpuUsageInfo, const char* pFile, uint32_t fileLen);
void WriteCpuUsageInfo(CpuData& data);
bool addTidBySort(int32_t tid);
DIR* OpenDestDir(std::string& dirPath);
int32_t GetValidTid(DIR* dirp);
ThreadState GetThreadState(const char threadState);
void WriteThread(ThreadInfo& threadInfo, const char* pFile, uint32_t fileLen, int32_t tid);
void WriteSingleThreadInfo(CpuData& data, int32_t tid);
void WriteThreadInfo(CpuData& data);
int32_t GetCpuFrequency(std::string fileName);
int GetCpuCoreSize();
int32_t GetMaxCpuFrequencyIndex();
void SetCpuFrequency(CpuCoreUsageInfo& cpuCore, int32_t coreNum);
// for UT
void SetPath(std::string path)
{
path_ = path;
}
void SetFreqPath(std::string path);
private:
/* data */
CpuConfig protoConfig_;
void* buffer_;
std::string path_;
int32_t err_;
int pid_;
std::vector<int32_t> tidVec_;
int64_t prevProcessCpuTime_;
int64_t prevSystemCpuTime_;
int64_t prevSystemBootTime_;
std::map<int32_t, int64_t> prevThreadCpuTimeMap_;
std::map<int32_t, int64_t> prevCoreSystemCpuTimeMap_;
std::map<int32_t, int64_t> prevCoreSystemBootTimeMap_;
std::vector<int32_t> maxFrequencyVec_;
std::vector<int32_t> minFrequencyVec_;
int32_t maxFreqIndex_;
std::string freqPath_;
};
#endif

View File

@ -0,0 +1,567 @@
/*
* Copyright (c) 2021 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 "cpu_data_plugin.h"
#include <ctime>
#include <vector>
#include "buffer_splitter.h"
namespace {
constexpr size_t READ_BUFFER_SIZE = 1024 * 16;
constexpr int SYSTEM_STAT_COUNT = 9;
constexpr int STAT_COUNT = 17;
constexpr int STAT_START = 13;
constexpr int THREAD_NAME_POS = 1;
constexpr int THREAD_STATE_POS = 2;
constexpr int CPU_USER_HZ_L = 100;
constexpr int CPU_USER_HZ_H = 1000;
constexpr int CPU_HZ_H = 10;
const std::string FREQUENCY_PATH = "/sys/devices/system/cpu";
const std::string FREQUENCY_MIN_PATH = "/cpufreq/cpuinfo_min_freq";
const std::string FREQUENCY_MAX_PATH = "/cpufreq/cpuinfo_max_freq";
const std::string FREQUENCY_CUR_PATH = "/cpufreq/cpuinfo_cur_freq";
constexpr int CPU_FREQUENCY_KHZ = 1000;
} // namespace
CpuDataPlugin::CpuDataPlugin()
{
buffer_ = nullptr;
path_ = "/proc/";
err_ = -1;
pid_ = -1;
prevProcessCpuTime_ = 0;
prevSystemCpuTime_ = 0;
prevSystemBootTime_ = 0;
maxFreqIndex_ = -1;
freqPath_ = FREQUENCY_PATH;
}
CpuDataPlugin::~CpuDataPlugin()
{
HILOG_INFO(LOG_CORE, "plugin:~CpuDataPlugin!");
if (buffer_ != nullptr) {
free(buffer_);
buffer_ = nullptr;
}
tidVec_.clear();
prevThreadCpuTimeMap_.clear();
prevCoreSystemCpuTimeMap_.clear();
prevCoreSystemBootTimeMap_.clear();
maxFrequencyVec_.clear();
minFrequencyVec_.clear();
}
int CpuDataPlugin::Start(const uint8_t* configData, uint32_t configSize)
{
buffer_ = malloc(READ_BUFFER_SIZE);
if (buffer_ == nullptr) {
HILOG_ERROR(LOG_CORE, "plugin:malloc buffer_ fail");
return RET_FAIL;
}
if (protoConfig_.ParseFromArray(configData, configSize) <= 0) {
HILOG_ERROR(LOG_CORE, "plugin:ParseFromArray failed");
return RET_FAIL;
}
if (protoConfig_.pid() > 0) {
pid_ = protoConfig_.pid();
} else {
HILOG_ERROR(LOG_CORE, "plugin:Invalid pid");
return RET_FAIL;
}
HILOG_INFO(LOG_CORE, "plugin:start success!");
return RET_SUCC;
}
int CpuDataPlugin::Report(uint8_t* data, uint32_t dataSize)
{
CpuData dataProto;
uint32_t length;
WriteCpuUsageInfo(dataProto);
WriteThreadInfo(dataProto);
length = dataProto.ByteSizeLong();
if (length > dataSize) {
return -length;
}
if (dataProto.SerializeToArray(data, length) > 0) {
return length;
}
return 0;
}
int CpuDataPlugin::Stop()
{
if (buffer_ != nullptr) {
free(buffer_);
buffer_ = nullptr;
}
tidVec_.clear();
prevThreadCpuTimeMap_.clear();
prevCoreSystemCpuTimeMap_.clear();
prevCoreSystemBootTimeMap_.clear();
HILOG_INFO(LOG_CORE, "plugin:stop success!");
return 0;
}
int32_t CpuDataPlugin::ReadFile(std::string& fileName)
{
int fd = -1;
ssize_t bytesRead = 0;
fd = open(fileName.c_str(), O_RDONLY | O_CLOEXEC);
if (fd == -1) {
HILOG_ERROR(LOG_CORE, "Failed to open(%s), errno=%d", fileName.c_str(), errno);
err_ = errno;
return RET_FAIL;
}
if (buffer_ == nullptr) {
HILOG_ERROR(LOG_CORE, "%s:Empty address, buffer_ is NULL", __func__);
err_ = RET_NULL_ADDR;
close(fd);
return RET_FAIL;
}
bytesRead = read(fd, buffer_, READ_BUFFER_SIZE - 1);
if (bytesRead <= 0) {
close(fd);
HILOG_ERROR(LOG_CORE, "Failed to read(%s), errno=%d", fileName.c_str(), errno);
err_ = errno;
return RET_FAIL;
}
close(fd);
return bytesRead;
}
void CpuDataPlugin::SetTimestamp(SampleTimeStamp& timestamp)
{
timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
timestamp.set_tv_sec(time.tv_sec);
timestamp.set_tv_nsec(time.tv_nsec);
}
int64_t CpuDataPlugin::GetUserHz()
{
int64_t hz = -1;
int64_t user_hz = sysconf(_SC_CLK_TCK);
switch (user_hz) {
case CPU_USER_HZ_L:
hz = CPU_HZ_H;
break;
case CPU_USER_HZ_H:
hz = 1;
break;
default:
break;
}
return hz;
}
int64_t CpuDataPlugin::GetCpuUsageTime(std::vector<std::string>& cpuUsageVec)
{
int64_t utime, stime, cutime, cstime, usageTime;
utime = atoi(cpuUsageVec[PROCESS_UTIME].c_str());
stime = atoi(cpuUsageVec[PROCESS_STIME].c_str());
cutime = atoi(cpuUsageVec[PROCESS_CUTIME].c_str());
cstime = atoi(cpuUsageVec[PROCESS_CSTIME].c_str());
usageTime = (utime + stime + cutime + cstime) * GetUserHz();
return usageTime;
}
void CpuDataPlugin::WriteProcessCpuUsage(CpuUsageInfo& cpuUsageInfo, const char* pFile, uint32_t fileLen)
{
BufferSplitter totalbuffer(const_cast<char*>(pFile), fileLen + 1);
std::vector<std::string> cpuUsageVec;
for (int i = 0; i < STAT_COUNT; i++) {
totalbuffer.NextWord(' ');
if (!totalbuffer.CurWord()) {
return;
}
if (i < STAT_START) {
continue;
} else {
std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
cpuUsageVec.push_back(curWord);
}
}
// 获取到的数据不包含utime、stime、cutime、cstime四个数值时返回
if (cpuUsageVec.size() != PROCESS_UNSPECIFIED) {
HILOG_ERROR(LOG_CORE, "Failed to get process cpu usage, size=%d", cpuUsageVec.size());
return;
}
int64_t usageTime = GetCpuUsageTime(cpuUsageVec);
cpuUsageInfo.set_prev_process_cpu_time_ms(prevProcessCpuTime_);
cpuUsageInfo.set_process_cpu_time_ms(usageTime);
prevProcessCpuTime_ = usageTime;
}
int32_t CpuDataPlugin::GetCpuFrequency(std::string fileName)
{
int32_t frequency = 0;
int32_t ret = ReadFile(fileName);
if (ret == RET_FAIL) {
HILOG_ERROR(LOG_CORE, "read %s file failed", fileName.c_str());
} else {
frequency = atoi((char*)buffer_);
}
return frequency;
}
int CpuDataPlugin::GetCpuCoreSize()
{
int coreSize = 0;
DIR* procDir = nullptr;
procDir = OpenDestDir(freqPath_);
if (procDir == nullptr) {
HILOG_ERROR(LOG_CORE, "procDir is nullptr");
return -1;
}
while (struct dirent* dirEnt = readdir(procDir)) {
if (dirEnt->d_type != DT_DIR) {
continue;
}
if (strncmp(dirEnt->d_name, "cpu", strlen("cpu")) == 0) {
coreSize++;
}
}
return coreSize;
}
int32_t CpuDataPlugin::GetMaxCpuFrequencyIndex()
{
int coreSize = GetCpuCoreSize();
int index = -1;
int32_t maxFreq = -1;
maxFrequencyVec_.clear();
minFrequencyVec_.clear();
for (int i = 0; i < coreSize; i++) {
std::string fileName = freqPath_ + "/cpu" + std::to_string(i) + FREQUENCY_MAX_PATH;
int32_t maxFrequency = GetCpuFrequency(fileName);
maxFrequencyVec_.push_back(maxFrequency);
fileName = freqPath_ + "/cpu" + std::to_string(i) + FREQUENCY_MIN_PATH;
int32_t minFrequency = GetCpuFrequency(fileName);
minFrequencyVec_.push_back(minFrequency);
if (maxFreq < maxFrequency) {
maxFreq = maxFrequency;
index = i;
}
}
// 单核或所有核最大频率相同,默认小核
if (coreSize == 1 || (coreSize > 1 && index == 0 && maxFreq == maxFrequencyVec_[1])) {
index = -1;
}
return index;
}
void CpuDataPlugin::SetCpuFrequency(CpuCoreUsageInfo& cpuCore, int32_t coreNum)
{
// 第一次获取最大频率核位置并保存各核最大最小频率到vector
if (maxFrequencyVec_.empty() || minFrequencyVec_.empty()) {
maxFreqIndex_ = GetMaxCpuFrequencyIndex();
}
std::string fileName = freqPath_ + "/cpu" + std::to_string(coreNum) + FREQUENCY_CUR_PATH;
int32_t curFrequency = GetCpuFrequency(fileName) / CPU_FREQUENCY_KHZ;
int32_t maxFrequency = maxFrequencyVec_[coreNum] / CPU_FREQUENCY_KHZ;
int32_t minFrequency = minFrequencyVec_[coreNum] / CPU_FREQUENCY_KHZ;
if (coreNum == maxFreqIndex_) {
cpuCore.set_is_little_core(false);
} else {
cpuCore.set_is_little_core(true);
}
CpuCoreFrequency* frequency = cpuCore.mutable_frequency();
frequency->set_min_frequency_khz(minFrequency);
frequency->set_max_frequency_khz(maxFrequency);
frequency->set_cur_frequency_khz(curFrequency);
}
void CpuDataPlugin::GetSystemCpuTime(std::vector<std::string>& cpuUsageVec, int64_t& usageTime, int64_t& time)
{
// 获取到的数据不包含user, nice, system, idle, iowait, irq, softirq, steal八个数值时返回
if (cpuUsageVec.size() != SYSTEM_UNSPECIFIED) {
HILOG_ERROR(LOG_CORE, "Failed to get system cpu usage, size=%d", cpuUsageVec.size());
return;
}
int64_t user, nice, system, idle, iowait, irq, softirq, steal;
user = atoi(cpuUsageVec[SYSTEM_USER].c_str());
nice = atoi(cpuUsageVec[SYSTEM_NICE].c_str());
system = atoi(cpuUsageVec[SYSTEM_SYSTEM].c_str());
idle = atoi(cpuUsageVec[SYSTEM_IDLE].c_str());
iowait = atoi(cpuUsageVec[SYSTEM_IOWAIT].c_str());
irq = atoi(cpuUsageVec[SYSTEM_IRQ].c_str());
softirq = atoi(cpuUsageVec[SYSTEM_SOFTIRQ].c_str());
steal = atoi(cpuUsageVec[SYSTEM_STEAL].c_str());
usageTime = (user + nice + system + irq + softirq + steal) * GetUserHz();
time = (usageTime + idle + iowait) * GetUserHz();
}
void CpuDataPlugin::WriteSystemCpuUsage(CpuUsageInfo& cpuUsageInfo, const char* pFile, uint32_t fileLen)
{
BufferSplitter totalbuffer(const_cast<char*>(pFile), fileLen + 1);
std::vector<std::string> cpuUsageVec;
int64_t usageTime, time;
size_t cpuLength = strlen("cpu");
do {
totalbuffer.NextWord(' ');
if (strncmp(totalbuffer.CurWord(), "cpu", cpuLength) != 0) {
return;
}
for (int i = 0; i < SYSTEM_STAT_COUNT; i++) {
if (!totalbuffer.CurWord()) {
return;
}
std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
cpuUsageVec.push_back(curWord);
totalbuffer.NextWord(' ');
}
GetSystemCpuTime(cpuUsageVec, usageTime, time);
if (strcmp(cpuUsageVec[0].c_str(), "cpu") == 0) {
cpuUsageInfo.set_prev_system_cpu_time_ms(prevSystemCpuTime_);
cpuUsageInfo.set_prev_system_boot_time_ms(prevSystemBootTime_);
cpuUsageInfo.set_system_cpu_time_ms(usageTime);
cpuUsageInfo.set_system_boot_time_ms(time);
prevSystemCpuTime_ = usageTime;
prevSystemBootTime_ = time;
} else {
std::string core = std::string(cpuUsageVec[0].c_str() + cpuLength, cpuUsageVec[0].size() - cpuLength);
int32_t coreNum = atoi(core.c_str());
// 第一次获取数据时需要将前一个数据置为0
if (prevCoreSystemCpuTimeMap_.size() == static_cast<size_t>(coreNum)) {
prevCoreSystemCpuTimeMap_[coreNum] = 0;
prevCoreSystemBootTimeMap_[coreNum] = 0;
}
CpuCoreUsageInfo* cpuCore = cpuUsageInfo.add_cores();
cpuCore->set_cpu_core(coreNum);
cpuCore->set_prev_system_cpu_time_ms(prevCoreSystemCpuTimeMap_[coreNum]);
cpuCore->set_prev_system_boot_time_ms(prevCoreSystemBootTimeMap_[coreNum]);
cpuCore->set_system_cpu_time_ms(usageTime);
cpuCore->set_system_boot_time_ms(time);
SetCpuFrequency(*cpuCore, coreNum);
prevCoreSystemCpuTimeMap_[coreNum] = usageTime;
prevCoreSystemBootTimeMap_[coreNum] = time;
}
cpuUsageVec.clear();
usageTime = 0;
time = 0;
} while (totalbuffer.NextLine());
}
void CpuDataPlugin::WriteCpuUsageInfo(CpuData& data)
{
// write process info
std::string fileName = path_ + std::to_string(pid_) + "/stat";
int32_t ret = ReadFile(fileName);
if (ret == RET_FAIL) {
HILOG_ERROR(LOG_CORE, "read /proc/pid/stat file failed");
return;
}
if ((buffer_ == nullptr) || (ret == 0)) {
HILOG_ERROR(LOG_CORE, "%s:invalid params, read buffer_ is NULL", __func__);
return;
}
auto* cpuUsageInfo = data.mutable_cpu_usage_info();
WriteProcessCpuUsage(*cpuUsageInfo, (char*)buffer_, ret);
// write system info
fileName = path_ + "stat";
ret = ReadFile(fileName);
if (ret == RET_FAIL) {
HILOG_ERROR(LOG_CORE, "read /proc/stat file failed");
return;
}
if ((buffer_ == nullptr) || (ret == 0)) {
HILOG_ERROR(LOG_CORE, "%s:invalid params, read buffer_ is NULL", __func__);
return;
}
WriteSystemCpuUsage(*cpuUsageInfo, (char*)buffer_, ret);
auto* timestamp = cpuUsageInfo->mutable_timestamp();
SetTimestamp(*timestamp);
}
bool CpuDataPlugin::addTidBySort(int32_t tid)
{
auto tidsEnd = tidVec_.end();
auto it = std::lower_bound(tidVec_.begin(), tidsEnd, tid);
if (it != tidsEnd && *it == tid) {
return false;
}
it = tidVec_.insert(it, std::move(tid));
return true;
}
DIR* CpuDataPlugin::OpenDestDir(std::string& dirPath)
{
DIR* destDir = nullptr;
destDir = opendir(dirPath.c_str());
if (destDir == nullptr) {
HILOG_ERROR(LOG_CORE, "Failed to opendir(%s), errno=%d", dirPath.c_str(), errno);
}
return destDir;
}
int32_t CpuDataPlugin::GetValidTid(DIR* dirp)
{
if (!dirp) {
return 0;
}
while (struct dirent* dirEnt = readdir(dirp)) {
if (dirEnt->d_type != DT_DIR) {
continue;
}
int32_t tid = atoi(dirEnt->d_name);
if (tid) {
return tid;
}
}
return 0;
}
ThreadState CpuDataPlugin::GetThreadState(const char threadState)
{
ThreadState state = THREAD_UNSPECIFIED;
switch (threadState) {
case 'R':
state = THREAD_RUNNING;
break;
case 'S':
state = THREAD_SLEEPING;
break;
case 'T':
state = THREAD_STOPPED;
break;
case 'D':
state = THREAD_WAITING;
break;
default:
break;
}
return state;
}
void CpuDataPlugin::WriteThread(ThreadInfo& threadInfo, const char* pFile, uint32_t fileLen, int32_t tid)
{
BufferSplitter totalbuffer(const_cast<char*>(pFile), fileLen + 1);
std::vector<std::string> cpuUsageVec;
for (int i = 0; i < STAT_COUNT; i++) {
totalbuffer.NextWord(' ');
if (!totalbuffer.CurWord()) {
return;
}
if (i == THREAD_NAME_POS) {
std::string curWord = std::string(totalbuffer.CurWord() + 1, totalbuffer.CurWordSize() - sizeof(")"));
threadInfo.set_thread_name(curWord);
} else if (i == THREAD_STATE_POS) {
std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
ThreadState state = GetThreadState(curWord[0]);
threadInfo.set_thread_state(state);
} else if (i >= STAT_START) {
std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize());
cpuUsageVec.push_back(curWord);
}
}
// 获取到的数据不包含utime、stime、cutime、cstime四个数值时返回
if (cpuUsageVec.size() != PROCESS_UNSPECIFIED) {
HILOG_ERROR(LOG_CORE, "Failed to get thread cpu usage, size=%d", cpuUsageVec.size());
return;
}
// 第一次获取该线程数据时需要将前一个数据置为0
if (prevThreadCpuTimeMap_.find(tid) == prevThreadCpuTimeMap_.end()) {
prevThreadCpuTimeMap_[tid] = 0;
}
int64_t usageTime = GetCpuUsageTime(cpuUsageVec);
threadInfo.set_prev_thread_cpu_time_ms(prevThreadCpuTimeMap_[tid]);
threadInfo.set_thread_cpu_time_ms(usageTime);
prevThreadCpuTimeMap_[tid] = usageTime;
threadInfo.set_tid(tid);
auto* timestamp = threadInfo.mutable_timestamp();
SetTimestamp(*timestamp);
}
void CpuDataPlugin::WriteSingleThreadInfo(CpuData& data, int32_t tid)
{
std::string fileName = path_ + std::to_string(pid_) + "/task/" + std::to_string(tid) + "/stat";
int32_t ret = ReadFile(fileName);
if (ret == RET_FAIL) {
HILOG_ERROR(LOG_CORE, "%s:read tid file failed", fileName.c_str());
return;
}
if ((buffer_ == nullptr) || (ret == 0)) {
HILOG_ERROR(LOG_CORE, "%s:invalid params, read buffer_ is NULL", __func__);
return;
}
auto* threadInfo = data.add_thread_info();
WriteThread(*threadInfo, (char*)buffer_, ret, tid);
}
void CpuDataPlugin::WriteThreadInfo(CpuData& data)
{
DIR* procDir = nullptr;
std::string path = path_ + std::to_string(pid_) + "/task";
procDir = OpenDestDir(path);
if (procDir == nullptr) {
return;
}
while (int32_t tid = GetValidTid(procDir)) {
if (find(tidVec_.begin(), tidVec_.end(), tid) == tidVec_.end()) {
addTidBySort(tid);
}
}
for (unsigned int i = 0; i < tidVec_.size(); i++) {
WriteSingleThreadInfo(data, tidVec_[i]);
}
closedir(procDir);
}
// for UT
void CpuDataPlugin::SetFreqPath(std::string path)
{
freqPath_ = path + FREQUENCY_PATH;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2021 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 <mutex>
#include "cpu_data_plugin.h"
#include "plugin_module_api.h"
namespace {
constexpr uint32_t MAX_BUFFER_SIZE = 4 * 1024 * 1024;
std::unique_ptr<CpuDataPlugin> g_plugin = nullptr;
std::mutex g_taskMutex;
} // namespace
static int CpuDataPluginSessionStart(const uint8_t* configData, uint32_t configSize)
{
std::lock_guard<std::mutex> guard(g_taskMutex);
g_plugin = std::make_unique<CpuDataPlugin>();
return g_plugin->Start(configData, configSize);
}
static int CpuPluginReportResult(uint8_t* bufferData, uint32_t bufferSize)
{
std::lock_guard<std::mutex> guard(g_taskMutex);
return g_plugin->Report(bufferData, bufferSize);
}
static int CpuPluginSessionStop()
{
std::lock_guard<std::mutex> guard(g_taskMutex);
HILOG_INFO(LOG_CORE, "%s:stop Session success!", __func__);
g_plugin->Stop();
g_plugin = nullptr;
return 0;
}
static PluginModuleCallbacks g_callbacks = {
CpuDataPluginSessionStart,
CpuPluginReportResult,
CpuPluginSessionStop,
};
PluginModuleStruct g_pluginModule = {&g_callbacks, "cpu-plugin", MAX_BUFFER_SIZE};

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2021 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 <dlfcn.h>
#include <unistd.h>
#include "cpu_plugin_config.pb.h"
#include "cpu_plugin_result.pb.h"
#include "plugin_module_api.h"
namespace {
constexpr int TEST_PID = 10;
int g_testCount = 10;
} // namespace
static void Report(PluginModuleStruct*& cpuPlugin, std::vector<uint8_t>& dataBuffer)
{
while (g_testCount--) {
int len = cpuPlugin->callbacks->onPluginReportResult(dataBuffer.data(), cpuPlugin->resultBufferSizeHint);
std::cout << "test:filler buffer length = " << len << std::endl;
if (len > 0) {
CpuData cpuData;
cpuData.ParseFromArray(dataBuffer.data(), len);
std::cout << "test:ParseFromArray length = " << len << std::endl;
CpuUsageInfo cpuUsageInfo = cpuData.cpu_usage_info();
std::cout << "prev_process_cpu_time_ms:" << cpuUsageInfo.prev_process_cpu_time_ms() << std::endl;
std::cout << "prev_system_cpu_time_ms:" << cpuUsageInfo.prev_system_cpu_time_ms() << std::endl;
std::cout << "prev_system_boot_time_ms:" << cpuUsageInfo.prev_system_boot_time_ms() << std::endl;
std::cout << "process_cpu_time_ms:" << cpuUsageInfo.process_cpu_time_ms() << std::endl;
std::cout << "system_cpu_time_ms:" << cpuUsageInfo.system_cpu_time_ms() << std::endl;
std::cout << "system_boot_time_ms:" << cpuUsageInfo.system_boot_time_ms() << std::endl;
for (int i = 0; i < cpuUsageInfo.cores_size(); i++) {
CpuCoreUsageInfo cpuCoreUsageInfo = cpuUsageInfo.cores()[i];
std::cout << "cpu_core:" << cpuCoreUsageInfo.cpu_core() << std::endl;
std::cout << "prev_system_cpu_time_ms:" << cpuCoreUsageInfo.prev_system_cpu_time_ms() << std::endl;
std::cout << "prev_system_boot_time_ms:" << cpuCoreUsageInfo.prev_system_boot_time_ms() << std::endl;
std::cout << "system_cpu_time_ms:" << cpuCoreUsageInfo.system_cpu_time_ms() << std::endl;
std::cout << "system_boot_time_ms:" << cpuCoreUsageInfo.system_boot_time_ms() << std::endl;
std::cout << "min_frequency_khz:" << cpuCoreUsageInfo.frequency().min_frequency_khz() << std::endl;
std::cout << "max_frequency_khz:" << cpuCoreUsageInfo.frequency().max_frequency_khz() << std::endl;
std::cout << "cur_frequency_khz:" << cpuCoreUsageInfo.frequency().cur_frequency_khz() << std::endl;
std::cout << "is_little_core:" << cpuCoreUsageInfo.is_little_core() << std::endl;
}
std::cout << "timestamp.tv_sec : " << cpuUsageInfo.timestamp().tv_sec() << std::endl;
std::cout << "timestamp.tv_nsec : " << cpuUsageInfo.timestamp().tv_nsec() << std::endl;
for (int i = 0; i < cpuData.thread_info_size(); i++) {
ThreadInfo threadInfo = cpuData.thread_info()[i];
std::cout << "tid : " << threadInfo.tid() << std::endl;
std::cout << "thread_name : " << threadInfo.thread_name() << std::endl;
std::cout << "thread_state : " << threadInfo.thread_state() << std::endl;
std::cout << "prev_thread_cpu_time_ms : " << threadInfo.prev_thread_cpu_time_ms() << std::endl;
std::cout << "thread_cpu_time_ms : " << threadInfo.thread_cpu_time_ms() << std::endl;
std::cout << "timestamp.tv_sec : " << threadInfo.timestamp().tv_sec() << std::endl;
std::cout << "timestamp.tv_nsec : " << threadInfo.timestamp().tv_nsec() << std::endl;
}
}
std::cout << "test:sleep...................." << std::endl;
sleep(1);
}
}
int main()
{
CpuConfig protoConfig;
void* handle = dlopen("./libcpudataplugin.z.so", RTLD_LAZY);
if (handle == nullptr) {
std::cout << "test:dlopen err: " << dlerror() << std::endl;
return 0;
}
std::cout << "test:handle = " << handle << std::endl;
PluginModuleStruct* cpuPlugin = (PluginModuleStruct*)dlsym(handle, "g_pluginModule");
std::cout << "test:name = " << cpuPlugin->name << std::endl;
std::cout << "test:buffer size = " << cpuPlugin->resultBufferSizeHint << std::endl;
// Serialize config
protoConfig.set_pid(TEST_PID);
int configLength = protoConfig.ByteSizeLong();
std::vector<uint8_t> configBuffer(configLength);
int ret = protoConfig.SerializeToArray(configBuffer.data(), configLength);
std::cout << "test:configLength = " << configLength << std::endl;
std::cout << "test:serialize success start plugin ret = " << ret << std::endl;
// run plugin
std::vector<uint8_t> dataBuffer(cpuPlugin->resultBufferSizeHint);
cpuPlugin->callbacks->onPluginSessionStart(configBuffer.data(), configLength);
Report(cpuPlugin, dataBuffer);
cpuPlugin->callbacks->onPluginSessionStop();
return 0;
}

View File

@ -0,0 +1,55 @@
# Copyright (c) 2021 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")
import("../../../base/config.gni")
module_output_path = "${OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH}/device"
config("module_private_config") {
visibility = [ ":*" ]
if (current_toolchain != host_toolchain) {
defines = [ "HAVE_HILOG" ]
}
}
ohos_unittest("cpudataplugin_ut") {
module_out_path = module_output_path
sources = [ "unittest/cpu_data_plugin_unittest.cpp" ]
deps = [
"${OHOS_PROFILER_DIR}/device/plugins/cpu_plugin:cpudataplugin",
"${OHOS_PROFILER_DIR}/protos/types/plugins/cpu_data:cpu_data_cpp",
"//third_party/googletest:gtest_main",
"//utils/native/base:utilsecurec",
]
include_dirs = [
"../include",
"../../../memory_plugin/include",
"${OHOS_PROFILER_DIR}/interfaces/kits",
"${OHOS_PROFILER_DIR}/device/base/include",
"//third_party/googletest/googletest/include/gtest",
"//utils/native/base/include",
]
cflags = [
"-Wno-inconsistent-missing-override",
"-Dprivate=public", #allow test code access private members
]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
configs = [ ":module_private_config" ]
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
resource_config_file = "${OHOS_PROFILER_DIR}/device/ohos_test.xml"
}
group("unittest") {
testonly = true
deps = [ ":cpudataplugin_ut" ]
}

View File

@ -0,0 +1 @@
1872 (ibus-x11) S 1 1865 1780 1025 1780 4194304 3233 0 457 0 60 10 20 30 20 0 7 0 4394 726278144 0 18446744073709551615 1 1 0 0 0 0 0 16781312 16386 0 0 0 17 5 0 0 5 0 0 0 0 0 0 0 0 0 0

View File

@ -0,0 +1 @@
1872 (ibus-x11) R 1 1865 1780 1025 1780 4194304 3217 0 457 0 17 5 10 10 20 0 7 0 4394 726278144 0 18446744073709551615 1 1 0 0 0 0 0 16781312 16386 0 0 0 17 5 0 0 5 0 0 0 0 0 0 0 0 0 0

View File

@ -0,0 +1 @@
1965 (ibus-x1:disk$0) S 1 1865 1780 1025 1780 1077936192 1 0 0 0 8 1 5 8 20 0 7 0 4444 726278144 0 18446744073709551615 1 1 0 0 0 0 1073479423 16781312 16386 0 0 0 -1 5 0 5 0 0 0 0 0 0 0 0 0 0 0

View File

@ -0,0 +1 @@
1966 (ibus-x1:disk$1) X 1 1865 1780 1025 1780 1077936192 1 0 0 0 0 0 0 0 20 0 7 0 4444 726278144 0 18446744073709551615 1 1 0 0 0 0 1073479423 16781312 16386 0 0 0 -1 5 0 5 0 0 0 0 0 0 0 0 0 0 0

View File

@ -0,0 +1 @@
1967 (ibus-x1:disk$2) S 1 1865 1780 1025 1780 1077936192 1 0 0 0 10 1 5 8 20 0 7 0 4444 726278144 0 18446744073709551615 1 1 0 0 0 0 1073479423 16781312 16386 0 0 0 -1 5 0 5 0 0 0 0 0 0 0 0 0 0 0

View File

@ -0,0 +1 @@
1968 (ibus-x1:disk$3) T 1 1865 1780 1025 1780 1077936192 1 0 0 0 7 0 0 0 20 0 7 0 4444 726278144 0 18446744073709551615 1 1 0 0 0 0 1073479423 16781312 16386 0 0 0 -1 5 0 5 0 0 0 0 0 0 0 0 0 0 0

View File

@ -0,0 +1 @@
1995 (gmain) S 1 1865 1780 1025 1780 4194368 1 0 0 0 15 3 0 4 20 0 7 0 4446 726278144 0 18446744073709551615 1 1 0 0 0 0 2147221247 16781312 16386 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0

View File

@ -0,0 +1 @@
1996 (gdbus) D 1 1865 1780 1025 1780 4194368 11 0 0 0 5 0 0 0 20 0 7 0 4446 726278144 0 18446744073709551615 1 1 0 0 0 0 0 16781312 16386 0 0 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0

View File

@ -0,0 +1,14 @@
cpu 24875428 3952448 11859815 1193297105 8980661 0 2607250 0 0 0
cpu0 4165400 662862 1966195 196987024 3571925 0 817371 0 0 0
cpu1 3861506 676578 1702753 199535158 1752008 0 401639 0 0 0
cpu2 3549890 676286 1544630 200640747 1133743 0 205972 0 0 0
cpu3 3336646 676939 1458898 201176432 854578 0 124812 0 0 0
cpu4 4566158 601107 2305309 197166395 929594 0 1007959 0 0 0
cpu5 5395826 658673 2882028 197791346 738811 0 49496 0 0 0
intr 1770859348 7 4 0 0 0 0 0 0 1 11 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 171 59725591 981403168 19 439482 559268 457611 427943 581724 453376 45 20991 669 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 2926398868
btime 1620093904
processes 18239603
procs_running 1
procs_blocked 0
softirq 2254950393 2090427 450858980 2885663 985716628 59484869 0 134917257 208251538 45883 410699148

View File

@ -0,0 +1,399 @@
/*
* Copyright (c) 2021 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 <cinttypes>
#include <hwext/gtest-ext.h>
#include <hwext/gtest-tag.h>
#include <dlfcn.h>
#include "cpu_data_plugin.h"
#include "plugin_module_api.h"
using namespace testing::ext;
namespace {
#if defined(__i386__) || defined(__x86_64__)
const std::string DEFAULT_TEST_PATH = "./resources";
#else
const std::string DEFAULT_TEST_PATH = "/data/local/tmp/resources";
#endif
constexpr uint32_t BUF_SIZE = 4 * 1024 * 1024;
const std::string SO_PATH = "/system/lib/libcpudataplugin.z.so";
constexpr int TEST_PID = 1;
std::string g_path;
std::string g_testPath;
std::vector<int> g_tidList = {1872, 1965, 1966, 1967, 1968, 1995, 1996};
constexpr int CORE_NUM = 6;
constexpr int THREAD_NUM = 7;
struct TestSystemStat {
int32_t core;
int64_t user;
int64_t nice;
int64_t system;
int64_t idle;
int64_t iowait;
int64_t irq;
int64_t softirq;
int64_t steal;
};
struct TestStat {
int64_t utime;
int64_t stime;
int64_t cutime;
int64_t cstime;
};
struct TestTidStat {
int32_t tid;
std::string name;
ThreadState state;
TestStat stat;
};
struct TestFreq {
int32_t curFreq;
int32_t maxFreq;
int32_t minFreq;
};
TestSystemStat g_systemStat[CORE_NUM + 1] = {
{-1, 24875428, 3952448, 11859815, 1193297105, 8980661, 0, 2607250, 0},
{0, 4165400, 662862, 1966195, 196987024, 3571925, 0, 817371, 0},
{1, 3861506, 676578, 1702753, 199535158, 1752008, 0, 401639, 0},
{2, 3549890, 676286, 1544630, 200640747, 1133743, 0, 205972, 0},
{3, 3336646, 676939, 1458898, 201176432, 854578, 0, 124812, 0},
{4, 4566158, 601107, 2305309, 197166395, 929594, 0, 1007959, 0},
{5, 5395826, 658673, 2882028, 197791346, 738811, 0, 49496, 0},
};
TestStat g_pidStat = {60, 10, 20, 30};
TestTidStat g_tidStat[THREAD_NUM] = {
{1872, "ibus-x11", THREAD_RUNNING, {17, 5, 10, 10}},
{1965, "ibus-x1:disk$0", THREAD_SLEEPING, {8, 1, 5, 8}},
{1966, "ibus-x1:disk$1", THREAD_UNSPECIFIED, {0, 0, 0, 0}},
{1967, "ibus-x1:disk$2", THREAD_SLEEPING, {10, 1, 5, 8}},
{1968, "ibus-x1:disk$3", THREAD_STOPPED, {7, 0, 0, 0}},
{1995, "gmain", THREAD_SLEEPING, {15, 3, 0, 4}},
{1996, "gdbus", THREAD_WAITING, {5, 0, 0, 0}},
};
TestFreq g_Freq[CORE_NUM + 1] = {
{1018, 3844, 509}, {1023, 2844, 509}, {1011, 3844, 509}, {1518, 3844, 1018}, {1245, 1844, 1018}, {1767, 3044, 1018},
};
class CpuDataPluginTest : public ::testing::Test {
public:
static void SetUpTestCase() {}
static void TearDownTestCase()
{
if (access(g_testPath.c_str(), F_OK) == 0) {
std::string str = "rm -rf " + g_testPath;
printf("TearDown--> %s\r\n", str.c_str());
system(str.c_str());
}
}
};
string Getexepath()
{
char buf[PATH_MAX] = "";
std::string path = "/proc/self/exe";
size_t rslt = readlink(path.c_str(), buf, sizeof(buf));
if (rslt < 0 || (rslt >= sizeof(buf))) {
return "";
}
buf[rslt] = '\0';
for (int i = rslt; i >= 0; i--) {
if (buf[i] == '/') {
buf[i + 1] = '\0';
break;
}
}
return buf;
}
std::string GetFullPath(std::string path)
{
if (path.size() > 0 && path[0] != '/') {
return Getexepath() + path;
}
return path;
}
#if defined(__i386__) || defined(__x86_64__)
bool CreatTestResource(std::string path, std::string exepath)
{
std::string str = "cp -r " + path + " " + exepath;
printf("CreatTestResource:%s\n", str.c_str());
pid_t status = system(str.c_str());
if (-1 == status) {
printf("system error!");
} else {
printf("exit status value = [0x%x]\n", status);
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) == 0) {
return true;
} else {
printf("run shell script fail, script exit code: %d\n", WEXITSTATUS(status));
return false;
}
} else {
printf("exit status = [%d]\n", WEXITSTATUS(status));
return true;
}
}
return false;
}
#endif
bool CheckTid(std::vector<int>& tidListTmp)
{
sort(g_tidList.begin(), g_tidList.end());
for (size_t i = 0; i < g_tidList.size(); i++) {
if (tidListTmp.at(i) != g_tidList.at(i)) {
return false;
}
}
return true;
}
bool PluginCpuinfoStub(CpuDataPlugin& cpuPlugin, CpuData& cpuData, int pid, bool unusualBuff)
{
CpuConfig protoConfig;
protoConfig.set_pid(pid);
// serialize
std::vector<uint8_t> configData(protoConfig.ByteSizeLong());
int ret = protoConfig.SerializeToArray(configData.data(), configData.size());
// start
ret = cpuPlugin.Start(configData.data(), configData.size());
if (ret < 0) {
return false;
}
printf("ut: serialize success start plugin ret = %d\n", ret);
// report
std::vector<uint8_t> bufferData(BUF_SIZE);
if (unusualBuff) { // buffer异常调整缓冲区长度为1测试异常情况
bufferData.resize(1, 0);
printf("ut: bufferData resize\n");
}
ret = cpuPlugin.Report(bufferData.data(), bufferData.size());
if (ret > 0) {
cpuData.ParseFromArray(bufferData.data(), ret);
return true;
}
return false;
}
void GetSystemCpuTime(TestSystemStat& stat, int64_t Hz, int64_t& usageTime, int64_t& time)
{
usageTime = (stat.user + stat.nice + stat.system + stat.irq + stat.softirq + stat.steal) * Hz;
time = (usageTime + stat.idle + stat.iowait) * Hz;
}
/**
* @tc.name: cpu plugin
* @tc.desc: Test whether the path exists.
* @tc.type: FUNC
*/
HWTEST_F(CpuDataPluginTest, TestPath, TestSize.Level1)
{
g_path = GetFullPath(DEFAULT_TEST_PATH);
g_testPath = g_path;
printf("g_path:%s\n", g_path.c_str());
EXPECT_NE("", g_path);
#if defined(__i386__) || defined(__x86_64__)
if (DEFAULT_TEST_PATH != g_path) {
if ((access(g_path.c_str(), F_OK) != 0) && (access(DEFAULT_TEST_PATH.c_str(), F_OK) == 0)) {
EXPECT_TRUE(CreatTestResource(DEFAULT_TEST_PATH, g_path));
}
}
#endif
}
/**
* @tc.name: cpu plugin
* @tc.desc: Tid list test in a specific directory.
* @tc.type: FUNC
*/
HWTEST_F(CpuDataPluginTest, TestTidlist, TestSize.Level1)
{
CpuDataPlugin cpuPlugin;
std::string path = g_path + "/proc/1872/task/";
printf("path:%s\n", path.c_str());
DIR* dir = cpuPlugin.OpenDestDir(path);
EXPECT_NE(nullptr, dir);
std::vector<int> tidListTmp;
while (int32_t pid = cpuPlugin.GetValidTid(dir)) {
tidListTmp.push_back(pid);
sort(tidListTmp.begin(), tidListTmp.end());
}
EXPECT_TRUE(CheckTid(tidListTmp));
}
/**
* @tc.name: cpu plugin
* @tc.desc: a part of cpu information test for specific pid.
* @tc.type: FUNC
*/
HWTEST_F(CpuDataPluginTest, TestPluginInfo, TestSize.Level1)
{
CpuDataPlugin cpuPlugin;
CpuData cpuData;
cpuPlugin.SetFreqPath(g_path);
g_path += "/proc/";
cpuPlugin.SetPath(g_path);
EXPECT_TRUE(PluginCpuinfoStub(cpuPlugin, cpuData, 1872, false));
int64_t systemCpuTime = 0;
int64_t systemBootTime = 0;
int64_t Hz = cpuPlugin.GetUserHz();
printf("Hz : %" PRId64 "\n", Hz);
int64_t processCpuTime = (g_pidStat.utime + g_pidStat.stime + g_pidStat.cutime + g_pidStat.cstime) * Hz;
GetSystemCpuTime(g_systemStat[0], Hz, systemCpuTime, systemBootTime);
CpuUsageInfo cpuUsageInfo = cpuData.cpu_usage_info();
EXPECT_EQ(cpuUsageInfo.prev_process_cpu_time_ms(), 0);
EXPECT_EQ(cpuUsageInfo.prev_system_cpu_time_ms(), 0);
EXPECT_EQ(cpuUsageInfo.prev_system_boot_time_ms(), 0);
EXPECT_EQ(cpuUsageInfo.process_cpu_time_ms(), processCpuTime);
EXPECT_EQ(cpuUsageInfo.system_cpu_time_ms(), systemCpuTime);
printf("systemCpuTime = %" PRId64 "\n", systemCpuTime);
EXPECT_EQ(cpuUsageInfo.system_boot_time_ms(), systemBootTime);
printf("systemBootTime = %" PRId64 "\n", systemBootTime);
ASSERT_EQ(cpuUsageInfo.cores_size(), 6);
for (int i = 1; i <= CORE_NUM; i++) {
CpuCoreUsageInfo cpuCoreUsageInfo = cpuUsageInfo.cores()[i - 1];
GetSystemCpuTime(g_systemStat[i], Hz, systemCpuTime, systemBootTime);
EXPECT_EQ(cpuCoreUsageInfo.cpu_core(), g_systemStat[i].core);
EXPECT_EQ(cpuCoreUsageInfo.prev_system_cpu_time_ms(), 0);
EXPECT_EQ(cpuCoreUsageInfo.prev_system_boot_time_ms(), 0);
EXPECT_EQ(cpuCoreUsageInfo.system_cpu_time_ms(), systemCpuTime);
EXPECT_EQ(cpuCoreUsageInfo.system_boot_time_ms(), systemBootTime);
EXPECT_EQ(cpuCoreUsageInfo.frequency().min_frequency_khz(), g_Freq[i - 1].minFreq);
EXPECT_EQ(cpuCoreUsageInfo.frequency().max_frequency_khz(), g_Freq[i - 1].maxFreq);
EXPECT_EQ(cpuCoreUsageInfo.frequency().cur_frequency_khz(), g_Freq[i - 1].curFreq);
if (i == 1) { // cpu0为大核
EXPECT_EQ(cpuCoreUsageInfo.is_little_core(), false);
} else {
EXPECT_EQ(cpuCoreUsageInfo.is_little_core(), true);
}
}
}
/**
* @tc.name: cpu plugin
* @tc.desc: cpu information test for specific pid.
* @tc.type: FUNC
*/
HWTEST_F(CpuDataPluginTest, TestPlugin, TestSize.Level1)
{
CpuDataPlugin cpuPlugin;
CpuData cpuData;
g_path = g_testPath;
cpuPlugin.SetFreqPath(g_path);
g_path += "/proc/";
cpuPlugin.SetPath(g_path);
EXPECT_TRUE(PluginCpuinfoStub(cpuPlugin, cpuData, 1872, false));
int64_t Hz = cpuPlugin.GetUserHz();
int64_t threadCpuTime;
ASSERT_EQ(cpuData.thread_info_size(), 7);
for (int i = 0; i < THREAD_NUM; i++) {
threadCpuTime = (g_tidStat[i].stat.utime + g_tidStat[i].stat.stime +
g_tidStat[i].stat.cutime + g_tidStat[i].stat.cstime) * Hz;
ThreadInfo threadInfo = cpuData.thread_info()[i];
EXPECT_EQ(threadInfo.tid(), g_tidStat[i].tid);
EXPECT_STREQ(threadInfo.thread_name().c_str(), g_tidStat[i].name.c_str());
EXPECT_EQ(threadInfo.thread_state(), g_tidStat[i].state);
EXPECT_EQ(threadInfo.thread_cpu_time_ms(), threadCpuTime);
EXPECT_EQ(threadInfo.prev_thread_cpu_time_ms(), 0);
}
EXPECT_EQ(cpuPlugin.Stop(), 0);
// 缓冲区异常
EXPECT_FALSE(PluginCpuinfoStub(cpuPlugin, cpuData, 1872, true));
EXPECT_EQ(cpuPlugin.Stop(), 0);
}
/**
* @tc.name: cpu plugin
* @tc.desc: cpu information test for unusual path.
* @tc.type: FUNC
*/
HWTEST_F(CpuDataPluginTest, TestPluginBoundary, TestSize.Level1)
{
CpuDataPlugin cpuPlugin;
CpuData cpuData;
g_path += "/proc/";
cpuPlugin.SetPath(g_path);
EXPECT_FALSE(PluginCpuinfoStub(cpuPlugin, cpuData, -1, false));
EXPECT_FALSE(PluginCpuinfoStub(cpuPlugin, cpuData, 12345, false));
CpuDataPlugin cpuPlugin2;
cpuPlugin2.SetPath("123");
EXPECT_FALSE(PluginCpuinfoStub(cpuPlugin2, cpuData, 1872, false));
EXPECT_FALSE(PluginCpuinfoStub(cpuPlugin2, cpuData, -1, false));
EXPECT_FALSE(PluginCpuinfoStub(cpuPlugin2, cpuData, 12345, false));
}
/**
* @tc.name: cpu plugin
* @tc.desc: cpu plugin registration test.
* @tc.type: FUNC
*/
HWTEST_F(CpuDataPluginTest, TestPluginRegister, TestSize.Level1)
{
void* handle = dlopen(SO_PATH.c_str(), RTLD_LAZY);
ASSERT_NE(handle, nullptr);
PluginModuleStruct* cpuPlugin = (PluginModuleStruct*)dlsym(handle, "g_pluginModule");
ASSERT_NE(cpuPlugin, nullptr);
EXPECT_STREQ(cpuPlugin->name, "cpu-plugin");
EXPECT_EQ(cpuPlugin->resultBufferSizeHint, BUF_SIZE);
// Serialize config
CpuConfig protoConfig;
protoConfig.set_pid(TEST_PID);
int configLength = protoConfig.ByteSizeLong();
ASSERT_GT(configLength, 0);
std::vector<uint8_t> configBuffer(configLength);
EXPECT_TRUE(protoConfig.SerializeToArray(configBuffer.data(), configLength));
// run plugin
std::vector<uint8_t> dataBuffer(cpuPlugin->resultBufferSizeHint);
EXPECT_EQ(cpuPlugin->callbacks->onPluginSessionStart(configBuffer.data(), configLength), RET_SUCC);
ASSERT_GT(cpuPlugin->callbacks->onPluginReportResult(dataBuffer.data(), cpuPlugin->resultBufferSizeHint), 0);
EXPECT_EQ(cpuPlugin->callbacks->onPluginSessionStop(), 0);
// 反序列化失败导致的start失败
EXPECT_EQ(cpuPlugin->callbacks->onPluginSessionStart(configBuffer.data(), configLength+1), RET_FAIL);
}
} // namespace

2
device/plugins/memory_plugin/BUILD.gn Executable file → Normal file
View File

@ -33,7 +33,7 @@ ohos_shared_library("memdataplugin") {
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite",
"${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc_lib",
"${OHOS_PROFILER_DIR}/protos/types/plugins/memory_data:memory_data_cpp",
"//utils/native/base:utilsbase",
"//utils/native/base:utilsecurec",
]
if (current_toolchain != host_toolchain) {
defines = [ "HAVE_HILOG" ]

Some files were not shown because too many files have changed in this diff Show More