Add unit tests for component info API 67/279367/2
authorHwankyu Jhun <h.jhun@samsung.com>
Mon, 8 Aug 2022 05:01:07 +0000 (14:01 +0900)
committerHwanKyu Jhun <h.jhun@samsung.com>
Mon, 8 Aug 2022 05:01:35 +0000 (05:01 +0000)
To refactor comp info API, unit tests are added.

Change-Id: Ied5bd442557d171972fd0b211f7416aa52dd144d
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
test/unit_tests/mock/vconf_mock.cc [new file with mode: 0644]
test/unit_tests/mock/vconf_mock.h [new file with mode: 0644]
test/unit_tests/test_comp_info.cc [new file with mode: 0644]

diff --git a/test/unit_tests/mock/vconf_mock.cc b/test/unit_tests/mock/vconf_mock.cc
new file mode 100644 (file)
index 0000000..4672d45
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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 "mock/vconf_mock.h"
+
+#include "mock/mock_hook.h"
+#include "mock/test_fixture.h"
+
+extern "C" char* vconf_get_str(const char* in_key) {
+  return MOCK_HOOK_P1(VconfMock, vconf_get_str, in_key);
+}
diff --git a/test/unit_tests/mock/vconf_mock.h b/test/unit_tests/mock/vconf_mock.h
new file mode 100644 (file)
index 0000000..90c4eb6
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#ifndef UNIT_TESTS_MOCK_VCONF_MOCK_H_
+#define UNIT_TESTS_MOCK_VCONF_MOCK_H_
+
+#include <gmock/gmock.h>
+#include <vconf.h>
+
+#include "mock/module_mock.h"
+
+class VconfMock : public virtual ModuleMock {
+ public:
+  VconfMock() {
+    using ::testing::_;
+    using ::testing::Return;
+    using ::testing::Invoke;
+
+    ON_CALL(*this, vconf_get_str(_))
+        .WillByDefault(Return(nullptr));
+  }
+
+  MOCK_METHOD1(vconf_get_str, char* (const char*));
+};
+
+#endif  // UNIT_TESTS_MOCK_VCONF_MOCK_H_
diff --git a/test/unit_tests/test_comp_info.cc b/test/unit_tests/test_comp_info.cc
new file mode 100644 (file)
index 0000000..2aec828
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * 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.h>
+#include <aul_cmd.h>
+#include <aul_comp_info.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 "mock/vconf_mock.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 kLaunchMode[] = "caller";
+constexpr const char kMainComponent[] = "true";
+constexpr const char kIconDisplay[] = "true";
+constexpr const char kTaskManage[] = "true";
+constexpr const char kLocale[] = "en-us";
+constexpr const char kIcon[] = "/home/owner/apps_rw/org.tizen.component-based-app/shared/res/frame-component.png";
+constexpr const char kLabel[] = "Frame-Component";
+
+class Mocks : virtual public ::testing::NiceMock<SocketMock>,
+              virtual public ::testing::NiceMock<VconfMock> {};
+
+}  // namespace
+
+class CompInfoTest : public TestFixture {
+ public:
+  CompInfoTest() : TestFixture(std::make_unique<::Mocks>()) {}
+
+  virtual void SetUp() {
+    int times = 2;
+    if (aul_is_initialized())
+      times--;
+
+    EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+      .Times(times)
+      .WillOnce(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(MakeCompInfoBundle()));
+    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_info_create(kComponentId, &handle_);
+      EXPECT_EQ(ret, AUL_R_OK);
+  }
+
+  virtual void TearDown() {
+    if (handle_ != nullptr) {
+      aul_comp_info_destroy(handle_);
+      handle_ = nullptr;
+    }
+
+    if (aul_is_initialized())
+      aul_launch_fini();
+  }
+
+  tizen_base::Bundle MakeLocalizedInfoBundle() {
+    return {
+      { AUL_K_LOCALE, kLocale },
+      { AUL_K_ICON, kIcon },
+      { AUL_K_LABEL, kLabel }
+    };
+  }
+
+  tizen_base::Bundle MakeCompInfoBundle() {
+    tizen_base::Bundle b {
+      { AUL_K_APPID, kAppId },
+      { AUL_K_COMPONENT_ID, kComponentId },
+      { AUL_K_COMPONENT_TYPE, kComponentType },
+      { AUL_K_LAUNCH_MODE, kLaunchMode },
+      { AUL_K_MAIN_COMP, kMainComponent },
+      { AUL_K_ICON_DISPLAY, kIconDisplay },
+      { AUL_K_TASK_MANAGE, kTaskManage }
+    };
+
+    auto raw = MakeLocalizedInfoBundle().ToRaw();
+    std::vector<std::string> localized_info_size {
+      std::to_string(raw.second)
+    };
+    std::vector<std::string> localized_info {
+      reinterpret_cast<char*>(raw.first.get())
+    };
+
+    b.Add(AUL_K_LOCALIZED_INFO, localized_info);
+    b.Add(AUL_K_LOCALIZED_INFO_SIZE, localized_info_size);
+    return b;
+  }
+
+  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 = APP_GET_INFO_OK;
+    pkt->len = raw.second;
+    memcpy(pkt->data, raw.first.get(), raw.second);
+
+    return std::shared_ptr<app_pkt_t>(pkt, free);
+  }
+
+  bool touched_ = false;
+  aul_comp_info_h handle_ = nullptr;
+};
+
+TEST_F(CompInfoTest, aul_comp_info_create_P) {
+  int cmd = -1;
+  int opt = -1;
+  bundle* kb = nullptr;
+  auto pkt = MakePacket(std::move(MakeCompInfoBundle()));
+  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* pkt = reinterpret_cast<const app_pkt_t*>(buf);
+        cmd = pkt->cmd;
+        opt = pkt->opt;
+        kb = bundle_decode(pkt->data, pkt->len);
+        return n;
+      }));
+  EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+      .Times(2)
+      .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;
+      }));
+
+  aul_comp_info_h handle = nullptr;
+  int ret = aul_comp_info_create(kComponentId, &handle);
+  EXPECT_NE(kb, nullptr);
+  tizen_base::Bundle b(kb, false, true);
+
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_NE(handle, nullptr);
+  auto handle_auto = std::unique_ptr<std::remove_pointer<aul_comp_info_h>::type,
+       decltype(aul_comp_info_destroy)*>(handle, aul_comp_info_destroy);
+
+  EXPECT_EQ(cmd, COMP_INFO_GET);
+  EXPECT_EQ(opt, (AUL_SOCK_BUNDLE | AUL_SOCK_ASYNC));
+  EXPECT_EQ(b.GetString(AUL_K_COMPONENT_ID), kComponentId);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_create_N) {
+  int ret = aul_comp_info_create(kComponentId, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  aul_comp_info_h handle = nullptr;
+  ret = aul_comp_info_create(nullptr, &handle);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_destroy_P) {
+  int ret = aul_comp_info_destroy(handle_);
+  EXPECT_EQ(ret, AUL_R_OK);
+  handle_ = nullptr;
+}
+
+TEST_F(CompInfoTest, aul_comp_info_destroy_N) {
+  int ret = aul_comp_info_destroy(nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_clone_P) {
+  aul_comp_info_h cloned_info = nullptr;
+  int ret = aul_comp_info_clone(handle_, &cloned_info);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_NE(cloned_info, nullptr);
+  auto cloned_info_auto =
+      std::unique_ptr<std::remove_pointer<aul_comp_info_h>::type,
+        decltype(aul_comp_info_destroy)*>(cloned_info, aul_comp_info_destroy);
+
+  const char* comp_id = nullptr;
+  ret = aul_comp_info_get_comp_id(cloned_info, &comp_id);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(std::string(comp_id), kComponentId);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_clone_N) {
+  int ret = aul_comp_info_clone(handle_, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  aul_comp_info_h cloned_info = nullptr;
+  ret = aul_comp_info_clone(nullptr, &cloned_info);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_app_id_P) {
+  const char* app_id = nullptr;
+  int ret = aul_comp_info_get_app_id(handle_, &app_id);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(std::string(app_id), kAppId);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_app_id_N) {
+  int ret = aul_comp_info_get_app_id(handle_, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  const char* app_id = nullptr;
+  ret = aul_comp_info_get_app_id(nullptr, &app_id);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_comp_id_P) {
+  const char* comp_id = nullptr;
+  int ret = aul_comp_info_get_comp_id(handle_, &comp_id);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(std::string(comp_id), kComponentId);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_comp_id_N) {
+  int ret = aul_comp_info_get_comp_id(handle_, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  const char* comp_id = nullptr;
+  ret = aul_comp_info_get_comp_id(nullptr, &comp_id);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_type_P) {
+  const char* type = nullptr;
+  int ret = aul_comp_info_get_type(handle_, &type);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(std::string(type), kComponentType);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_type_N) {
+  int ret = aul_comp_info_get_type(handle_, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  const char* type = nullptr;
+  ret = aul_comp_info_get_type(nullptr, &type);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_launch_mode_P) {
+  const char* launch_mode = nullptr;
+  int ret = aul_comp_info_get_launch_mode(handle_, &launch_mode);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(std::string(launch_mode), kLaunchMode);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_launch_mode_N) {
+  int ret = aul_comp_info_get_launch_mode(handle_, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  const char* launch_mode = nullptr;
+  ret = aul_comp_info_get_launch_mode(nullptr, &launch_mode);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_is_main_comp_P) {
+  bool main_comp = false;
+  int ret = aul_comp_info_is_main_comp(handle_, &main_comp);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(main_comp, true);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_is_main_comp_N) {
+  int ret = aul_comp_info_is_main_comp(handle_, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  bool main_comp = false;
+  ret = aul_comp_info_is_main_comp(nullptr, &main_comp);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_is_icon_display_P) {
+  bool icon_display = false;
+  int ret = aul_comp_info_is_icon_display(handle_, &icon_display);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(icon_display, true);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_is_icon_display_N) {
+  int ret = aul_comp_info_is_icon_display(handle_, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  bool icon_display = false;
+  ret = aul_comp_info_is_icon_display(nullptr, &icon_display);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_is_taskmanage_P) {
+  bool taskmanage = false;
+  int ret = aul_comp_info_is_taskmanage(handle_, &taskmanage);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(taskmanage, true);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_is_taskmanage_N) {
+  int ret = aul_comp_info_is_taskmanage(handle_, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  bool taskmanage = false;
+  ret = aul_comp_info_is_taskmanage(nullptr, &taskmanage);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_icon_P) {
+  std::string key;
+
+  EXPECT_CALL(GetMock<VconfMock>(), vconf_get_str(_))
+      .Times(1)
+      .WillOnce(Invoke([&](const char* in_key) -> char* {
+        key = std::string(in_key);
+        return strdup("en_US.UTF-8");
+      }));
+
+  const char* icon = nullptr;
+  int ret = aul_comp_info_get_icon(handle_, &icon);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(std::string(icon), kIcon);
+  EXPECT_EQ(key, VCONFKEY_LANGSET);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_icon_N) {
+  int ret = aul_comp_info_get_icon(handle_, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  const char* icon = nullptr;
+  ret = aul_comp_info_get_icon(nullptr, &icon);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_label_P) {
+  std::string key;
+
+  EXPECT_CALL(GetMock<VconfMock>(), vconf_get_str(_))
+      .Times(1)
+      .WillOnce(Invoke([&](const char* in_key) -> char* {
+        key = std::string(in_key);
+        return strdup("en_US.UTF-8");
+      }));
+
+  const char* label = nullptr;
+  int ret = aul_comp_info_get_label(handle_, &label);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(std::string(label), kLabel);
+  EXPECT_EQ(key, VCONFKEY_LANGSET);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_label_N) {
+  int ret = aul_comp_info_get_label(handle_, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  const char* label = nullptr;
+  ret = aul_comp_info_get_label(nullptr, &label);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_localed_label_P) {
+  const char* label = nullptr;
+  int ret = aul_comp_info_get_localed_label(handle_, kLocale, &label);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(std::string(label), kLabel);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_get_localed_label_N) {
+  int ret = aul_comp_info_get_localed_label(handle_, kLocale, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  const char* label = nullptr;
+  ret = aul_comp_info_get_localed_label(handle_, nullptr, &label);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  ret = aul_comp_info_get_localed_label(nullptr, kLocale, &label);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_foreach_comp_info_from_app_P) {
+  int cmd = -1;
+  int opt = -1;
+  auto pkt = MakePacket(std::move(MakeCompInfoBundle()));
+  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* pkt = reinterpret_cast<const app_pkt_t*>(buf);
+        cmd = pkt->cmd;
+        opt = pkt->opt;
+        return n;
+      }));
+  EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+      .Times(3)
+      .WillOnce(Invoke([&](int fd, void* buf, size_t n, int flags) -> ssize_t {
+        int count = 1;
+        memcpy(buf, &count, sizeof(int));
+        return n;
+      }))
+      .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_info_foreach_comp_info_from_app(kAppId,
+      [](aul_comp_info_h handle, void* user_data) {
+        const char* comp_id = nullptr;
+        aul_comp_info_get_comp_id(handle, &comp_id);
+        if (comp_id && !strcmp(comp_id, kComponentId)) {
+          auto* test = static_cast<CompInfoTest*>(user_data);
+          test->touched_ = true;
+          return false;
+        }
+
+        return true;
+      }, this);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(cmd, COMP_INFO_FOREACH);
+  EXPECT_EQ(opt, (AUL_SOCK_BUNDLE | AUL_SOCK_ASYNC));
+  EXPECT_EQ(touched_, true);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_foreach_comp_info_from_app_N) {
+  int ret = aul_comp_info_foreach_comp_info_from_app(kAppId, nullptr, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+
+  ret = aul_comp_info_foreach_comp_info_from_app(nullptr,
+      [](aul_comp_info_h handle, void* user_data) {
+        return true;
+      }, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_foreach_comp_info_P) {
+  int cmd = -1;
+  int opt = -1;
+  auto pkt = MakePacket(std::move(MakeCompInfoBundle()));
+  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* pkt = reinterpret_cast<const app_pkt_t*>(buf);
+        cmd = pkt->cmd;
+        opt = pkt->opt;
+        return n;
+      }));
+  EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+      .Times(3)
+      .WillOnce(Invoke([&](int fd, void* buf, size_t n, int flags) -> ssize_t {
+        int count = 1;
+        memcpy(buf, &count, sizeof(int));
+        return n;
+      }))
+      .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_info_foreach_comp_info(
+      [](aul_comp_info_h handle, void* user_data) {
+        const char* app_id = nullptr;
+        aul_comp_info_get_app_id(handle, &app_id);
+        const char* comp_id = nullptr;
+        aul_comp_info_get_comp_id(handle, &comp_id);
+        if (comp_id && !strcmp(comp_id, kComponentId) &&
+            app_id && !strcmp(app_id, kAppId)) {
+          auto* test = static_cast<CompInfoTest*>(user_data);
+          test->touched_ = true;
+          return false;
+        }
+
+        return true;
+      }, this);
+  EXPECT_EQ(ret, AUL_R_OK);
+  EXPECT_EQ(cmd, COMP_INFO_FOREACH);
+  EXPECT_EQ(opt, (AUL_SOCK_BUNDLE | AUL_SOCK_ASYNC));
+  EXPECT_EQ(touched_, true);
+}
+
+TEST_F(CompInfoTest, aul_comp_info_foreach_comp_info_N) {
+  int ret = aul_comp_info_foreach_comp_info(nullptr, nullptr);
+  EXPECT_EQ(ret, AUL_R_EINVAL);
+}