/* * Copyright (C) 2022 The Android Open Source Project * * 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. */ #define LOG_TAG "ThreadNetworkHalTargetTest" #include #include #include #include #include #include #include #include #include #include #include using aidl::android::hardware::threadnetwork::BnThreadChipCallback; using aidl::android::hardware::threadnetwork::IThreadChip; using android::ProcessState; using ndk::ScopedAStatus; using ndk::SpAIBinder; namespace { constexpr static int kCallbackTimeoutMs = 5000; } // namespace class ThreadChipCallback : public BnThreadChipCallback { public: ThreadChipCallback(const std::function&)>& on_spinel_message_cb) : on_spinel_message_cb_(on_spinel_message_cb) {} ScopedAStatus onReceiveSpinelFrame(const std::vector& in_aFrame) { on_spinel_message_cb_(in_aFrame); return ScopedAStatus::ok(); } private: std::function&)> on_spinel_message_cb_; }; class ThreadNetworkAidl : public testing::TestWithParam { public: virtual void SetUp() override { std::string serviceName = GetParam(); ALOGI("serviceName: %s", serviceName.c_str()); thread_chip = IThreadChip::fromBinder( SpAIBinder(AServiceManager_waitForService(serviceName.c_str()))); ASSERT_NE(thread_chip, nullptr); } virtual void TearDown() override { thread_chip->close(); } std::shared_ptr thread_chip; }; TEST_P(ThreadNetworkAidl, Open) { std::shared_ptr callback = ndk::SharedRefBase::make([](auto /* data */) {}); EXPECT_TRUE(thread_chip->open(callback).isOk()); } TEST_P(ThreadNetworkAidl, Close) { std::shared_ptr callback = ndk::SharedRefBase::make([](auto /* data */) {}); EXPECT_TRUE(thread_chip->open(callback).isOk()); EXPECT_TRUE(thread_chip->close().isOk()); } TEST_P(ThreadNetworkAidl, Reset) { std::shared_ptr callback = ndk::SharedRefBase::make([](auto /* data */) {}); EXPECT_TRUE(thread_chip->open(callback).isOk()); EXPECT_TRUE(thread_chip->hardwareReset().isOk()); } TEST_P(ThreadNetworkAidl, SendSpinelFrame) { const uint8_t kCmdOffset = 2; const uint8_t kMajorVersionOffset = 3; const uint8_t kMinorVersionOffset = 4; const std::vector kGetSpinelProtocolVersion({0x81, 0x02, 0x01}); const std::vector kGetSpinelProtocolVersionResponse({0x81, 0x06, 0x01, 0x04, 0x03}); uint8_t min_major_version = kGetSpinelProtocolVersionResponse[kMajorVersionOffset]; uint8_t min_minor_version = kGetSpinelProtocolVersionResponse[kMinorVersionOffset]; uint8_t major_version; uint8_t minor_version; std::promise open_cb_promise; std::future open_cb_future{open_cb_promise.get_future()}; std::shared_ptr callback; std::vector received_frame; std::chrono::milliseconds timeout{kCallbackTimeoutMs}; callback = ndk::SharedRefBase::make( [&](const std::vector& in_aFrame) { if (in_aFrame.size() == kGetSpinelProtocolVersionResponse.size() && in_aFrame[kCmdOffset] == kGetSpinelProtocolVersionResponse[kCmdOffset]) { major_version = in_aFrame[kMajorVersionOffset]; minor_version = in_aFrame[kMinorVersionOffset]; open_cb_promise.set_value(); } }); ASSERT_NE(callback, nullptr); EXPECT_TRUE(thread_chip->open(callback).isOk()); EXPECT_TRUE(thread_chip->sendSpinelFrame(kGetSpinelProtocolVersion).isOk()); EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready); EXPECT_GE(major_version, min_major_version); if (major_version == min_major_version) { EXPECT_GE(minor_version, min_minor_version); } } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThreadNetworkAidl); INSTANTIATE_TEST_SUITE_P( Thread, ThreadNetworkAidl, testing::ValuesIn(android::getAidlHalInstanceNames(IThreadChip::descriptor)), android::PrintInstanceNameToString); int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); ProcessState::self()->setThreadPoolMaxThreadCount(1); ProcessState::self()->startThreadPool(); return RUN_ALL_TESTS(); }