--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics 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 <aul_comp_context.h>
+#include <aul_cmd.h>
+#include <aul_sock.h>
+#include <gtest/gtest.h>
+#include <stdlib.h>
+
+#include <bundle_cpp.h>
+
+#include <iostream>
+#include <memory>
+
+#include "mock/mock_hook.h"
+#include "mock/socket_mock.h"
+#include "mock/test_fixture.h"
+#include "src/launch.h"
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+using ::testing::Invoke;
+using ::testing::SaveArg;
+
+namespace {
+
+constexpr const char kAppId[] = "org.tizen.component-based-app";
+constexpr const char kComponentId[] = "org.tizen.frame-component";
+constexpr const char kComponentType[] = "frame";
+constexpr const char kInstanceId[] = "frame@frame-component";
+pid_t kPid = getpid();
+constexpr int kStatus = 3;
+constexpr bool kIsSubComp = false;
+
+class Mocks : virtual public ::testing::NiceMock<SocketMock> {};
+
+} // namespace
+
+class CompContextTest : public TestFixture {
+ public:
+ CompContextTest() : TestFixture(std::make_unique<::Mocks>()) {}
+
+ virtual void SetUp() {
+ int times = 2;
+ if (aul_is_initialized())
+ times--;
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(times)
+ .WillRepeatedly(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ return n;
+ }));
+
+ if (!aul_is_initialized())
+ aul_launch_init(nullptr, nullptr);
+
+ auto pkt = MakePacket(std::move(MakeCompContextBundle()));
+ EXPECT_NE(pkt, nullptr);
+
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(2)
+ .WillOnce(Invoke([&](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ pkt->cmd = APP_GET_INFO_OK;
+ memcpy(buf, pkt.get(), n);
+ return n;
+ }))
+ .WillOnce(Invoke([&](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ memcpy(buf, pkt->data, n);
+ return n;
+ }));
+
+ int ret = aul_comp_context_create("org.tizen.frame-component", &handle_);
+ EXPECT_EQ(ret, AUL_R_OK);
+ }
+
+ virtual void TearDown() {
+ if (handle_ != nullptr) {
+ aul_comp_context_destroy(handle_);
+ handle_ = nullptr;
+ }
+
+ if (aul_is_initialized())
+ aul_launch_fini();
+ }
+
+ tizen_base::Bundle MakeCompContextBundle() {
+ return {
+ { AUL_K_APPID, kAppId },
+ { AUL_K_PID, std::to_string(kPid) },
+ { AUL_K_INSTANCE_ID, kInstanceId },
+ { AUL_K_COMPONENT_ID, kComponentId },
+ { AUL_K_STATUS, std::to_string(kStatus) },
+ { AUL_K_IS_SUB_COMP, std::to_string(kIsSubComp) },
+ { AUL_K_COMPONENT_TYPE, kComponentType }
+ };
+ }
+
+ std::shared_ptr<app_pkt_t> MakePacket(tizen_base::Bundle b) {
+ auto raw = b.ToRaw();
+ app_pkt_t* pkt =
+ static_cast<app_pkt_t*>(calloc(1, sizeof(app_pkt_t) + raw.second));
+ if (pkt == nullptr)
+ return nullptr;
+
+ pkt->opt = AUL_SOCK_BUNDLE;
+ pkt->cmd = AUL_R_OK;
+ pkt->len = raw.second;
+ memcpy(pkt->data, raw.first.get(), raw.second);
+
+ return std::shared_ptr<app_pkt_t>(pkt, free);
+ }
+
+ std::shared_ptr<app_pkt_t> MakePacket(std::string str) {
+ app_pkt_t* pkt = static_cast<app_pkt_t*>(
+ calloc(1, sizeof(app_pkt_t) + str.length() + 1));
+ if (pkt == nullptr)
+ return nullptr;
+
+ pkt->opt = AUL_SOCK_NONE;
+ pkt->cmd = APP_GET_INFO_OK;
+ pkt->len = str.length() + 1;
+ memcpy(pkt->data, str.c_str(), str.length());
+
+ return std::shared_ptr<app_pkt_t>(pkt, free);
+ }
+
+ bool touched_ = false;
+ aul_comp_context_h handle_ = nullptr;
+};
+
+TEST_F(CompContextTest, aul_comp_context_foreach_comp_context_P) {
+ int cmd = -1;
+ auto pkt = MakePacket(std::move(MakeCompContextBundle()));
+ EXPECT_NE(pkt, nullptr);
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(3)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = 1;
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }))
+ .WillOnce(Invoke([&](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ memcpy(buf, pkt.get(), n);
+ return n;
+ }))
+ .WillOnce(Invoke([&](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ memcpy(buf, pkt->data, n);
+ return n;
+ }));
+
+ touched_ = false;
+ int ret = aul_comp_context_foreach_comp_context(
+ [](aul_comp_context_h handle, void* user_data) {
+ const char* appid = nullptr;
+ if (aul_comp_context_get_app_id(handle, &appid) != AUL_R_OK)
+ return false;
+
+ const char* comp_id = nullptr;
+ if (aul_comp_context_get_comp_id(handle, &comp_id) != AUL_R_OK)
+ return false;
+
+ if (appid && !strcmp(appid, kAppId) &&
+ comp_id && !strcmp(comp_id, kComponentId)) {
+ auto* test = static_cast<CompContextTest*>(user_data);
+ test->touched_ = true;
+ return false;
+ }
+
+ return true;
+ }, this);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(touched_, true);
+ EXPECT_EQ(cmd, COMP_CONTEXT_FOREACH);
+}
+
+TEST_F(CompContextTest, aul_comp_context_foreach_comp_context_N) {
+ int ret = aul_comp_context_foreach_comp_context(nullptr, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_create_P) {
+ int cmd = -1;
+ auto pkt = MakePacket(std::move(MakeCompContextBundle()));
+ EXPECT_NE(pkt, nullptr);
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(2)
+ .WillOnce(Invoke([&](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ pkt->cmd = APP_GET_INFO_OK;
+ memcpy(buf, pkt.get(), n);
+ return n;
+ }))
+ .WillOnce(Invoke([&](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ memcpy(buf, pkt->data, n);
+ return n;
+ }));
+
+ aul_comp_context_h handle = nullptr;
+ int ret = aul_comp_context_create(kComponentId, &handle);
+ auto handle_auto =
+ std::unique_ptr<std::remove_pointer<aul_comp_context_h>::type,
+ decltype(aul_comp_context_destroy)*>(
+ handle, aul_comp_context_destroy);
+
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_NE(handle, nullptr);
+ EXPECT_EQ(cmd, COMP_CONTEXT_GET);
+}
+
+TEST_F(CompContextTest, aul_comp_context_create_N) {
+ aul_comp_context_h handle = nullptr;
+ int ret = aul_comp_context_create(nullptr, &handle);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+
+ ret = aul_comp_context_create(kComponentId, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_destroy_P) {
+ int ret = aul_comp_context_destroy(handle_);
+ EXPECT_EQ(ret, AUL_R_OK);
+ handle_ = nullptr;
+}
+
+TEST_F(CompContextTest, aul_comp_context_destroy_N) {
+ int ret = aul_comp_context_destroy(nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_comp_id_P) {
+ const char* comp_id = nullptr;
+ int ret = aul_comp_context_get_comp_id(handle_, &comp_id);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(std::string(comp_id), kComponentId);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_comp_id_N) {
+ int ret = aul_comp_context_get_comp_id(handle_, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+
+ const char* comp_id = nullptr;
+ ret = aul_comp_context_get_comp_id(nullptr, &comp_id);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_instance_id_P) {
+ const char* instance_id = nullptr;
+ int ret = aul_comp_context_get_instance_id(handle_, &instance_id);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(std::string(instance_id), kInstanceId);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_instance_id_N) {
+ int ret = aul_comp_context_get_instance_id(handle_, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+
+ const char* instance_id = nullptr;
+ ret = aul_comp_context_get_instance_id(nullptr, &instance_id);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_app_id_P) {
+ const char* app_id = nullptr;
+ int ret = aul_comp_context_get_app_id(handle_, &app_id);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(std::string(app_id), kAppId);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_app_id_N) {
+ int ret = aul_comp_context_get_app_id(handle_, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+
+ const char* app_id = nullptr;
+ ret = aul_comp_context_get_app_id(nullptr, &app_id);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_type_P) {
+ const char* type = nullptr;
+ int ret = aul_comp_context_get_type(handle_, &type);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(std::string(type), kComponentType);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_type_N) {
+ int ret = aul_comp_context_get_type(handle_, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+
+ const char* type = nullptr;
+ ret = aul_comp_context_get_type(nullptr, &type);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_pid_P) {
+ pid_t pid = -1;
+ int ret = aul_comp_context_get_pid(handle_, &pid);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(pid, kPid);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_pid_N) {
+ int ret = aul_comp_context_get_pid(handle_, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+
+ pid_t pid = -1;
+ ret = aul_comp_context_get_pid(nullptr, &pid);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_status_P) {
+ int status = -1;
+ int ret = aul_comp_context_get_status(handle_, &status);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(status, kStatus);
+}
+
+TEST_F(CompContextTest, aul_comp_context_get_status_N) {
+ int ret = aul_comp_context_get_status(handle_, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+
+ int status = -1;
+ ret = aul_comp_context_get_status(nullptr, &status);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_is_sub_comp_P) {
+ bool is_sub_comp;
+ int ret = aul_comp_context_is_sub_comp(handle_, &is_sub_comp);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(is_sub_comp, kIsSubComp);
+}
+
+TEST_F(CompContextTest, aul_comp_context_is_sub_comp_N) {
+ int ret = aul_comp_context_is_sub_comp(handle_, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+
+ bool is_sub_comp;
+ ret = aul_comp_context_is_sub_comp(nullptr, &is_sub_comp);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_clone_P) {
+ aul_comp_context_h clone = nullptr;
+ int ret = aul_comp_context_clone(handle_, &clone);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_NE(clone, nullptr);
+
+ auto clone_auto =
+ std::unique_ptr<std::remove_pointer<aul_comp_context_h>::type,
+ decltype(aul_comp_context_destroy)*>(
+ clone, aul_comp_context_destroy);
+
+ const char* comp_id = nullptr;
+ ret = aul_comp_context_get_comp_id(clone, &comp_id);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(std::string(comp_id), kComponentId);
+}
+
+TEST_F(CompContextTest, aul_comp_context_clone_N) {
+ int ret = aul_comp_context_clone(handle_, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+
+ aul_comp_context_h clone = nullptr;
+ ret = aul_comp_context_clone(nullptr, &clone);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_is_running_P) {
+ int cmd = -1;
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = getpid();
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }));
+
+ bool running = false;
+ int ret = aul_comp_context_is_running(handle_, &running);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(running , true);
+ EXPECT_EQ(cmd, COMP_CONTEXT_IS_RUNNING);
+}
+
+TEST_F(CompContextTest, aul_comp_context_is_running_N) {
+ int ret = aul_comp_context_is_running(handle_, nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+
+ bool running = false;
+ ret = aul_comp_context_is_running(nullptr, &running);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_resume_P) {
+ int cmd = -1;
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = AUL_R_OK;
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }));
+
+ int ret = aul_comp_context_resume(handle_);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(cmd, COMP_CONTEXT_RESUME);
+}
+
+TEST_F(CompContextTest, aul_comp_context_resume_N) {
+ int ret = aul_comp_context_resume(nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_pause_P) {
+ int cmd = -1;
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = AUL_R_OK;
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }));
+
+ int ret = aul_comp_context_pause(handle_);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(cmd, COMP_CONTEXT_PAUSE);
+}
+
+TEST_F(CompContextTest, aul_comp_context_pause_N) {
+ int ret = aul_comp_context_pause(nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_terminate_bg_comp_P) {
+ int cmd = -1;
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = AUL_R_OK;
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }));
+
+ int ret = aul_comp_context_terminate_bg_comp(handle_);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(cmd, COMP_CONTEXT_TERMINATE_BG_COMP);
+}
+
+TEST_F(CompContextTest, aul_comp_context_terminate_bg_comp_N) {
+ int ret = aul_comp_context_terminate_bg_comp(nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompContextTest, aul_comp_context_terminate_P) {
+ int cmd = -1;
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = AUL_R_OK;
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }));
+
+ int ret = aul_comp_context_terminate(handle_);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(cmd, COMP_CONTEXT_TERMINATE);
+}
+
+TEST_F(CompContextTest, aul_comp_context_terminateN) {
+ int ret = aul_comp_context_terminate(nullptr);
+ EXPECT_EQ(ret, AUL_R_EINVAL);
+}