NFLogListenerTest.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Copyright (C) 2017 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <atomic>
  17. #include <deque>
  18. #include <iostream>
  19. #include <mutex>
  20. #include <arpa/inet.h>
  21. #include <gmock/gmock.h>
  22. #include <gtest/gtest.h>
  23. #include <linux/netfilter/nfnetlink_log.h>
  24. #include <netdutils/MockSyscalls.h>
  25. #include "NFLogListener.h"
  26. using ::testing::_;
  27. using ::testing::DoAll;
  28. using ::testing::Exactly;
  29. using ::testing::Invoke;
  30. using ::testing::Return;
  31. using ::testing::SaveArg;
  32. using ::testing::StrictMock;
  33. namespace android {
  34. namespace net {
  35. using netdutils::Slice;
  36. using netdutils::StatusOr;
  37. using netdutils::makeSlice;
  38. using netdutils::status::ok;
  39. constexpr int kNFLogPacketMsgType = (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_PACKET;
  40. constexpr int kNetlinkMsgDoneType = (NFNL_SUBSYS_NONE << 8) | NLMSG_DONE;
  41. class MockNetlinkListener : public NetlinkListenerInterface {
  42. public:
  43. ~MockNetlinkListener() override = default;
  44. MOCK_METHOD1(send, netdutils::Status(const Slice msg));
  45. MOCK_METHOD2(subscribe, netdutils::Status(uint16_t type, const DispatchFn& fn));
  46. MOCK_METHOD1(unsubscribe, netdutils::Status(uint16_t type));
  47. MOCK_METHOD0(join, void());
  48. MOCK_METHOD1(registerSkErrorHandler, void(const SkErrorHandler& handler));
  49. };
  50. class NFLogListenerTest : public testing::Test {
  51. protected:
  52. NFLogListenerTest() {
  53. EXPECT_CALL(*mNLListener, subscribe(kNFLogPacketMsgType, _))
  54. .WillOnce(DoAll(SaveArg<1>(&mPacketFn), Return(ok)));
  55. EXPECT_CALL(*mNLListener, subscribe(kNetlinkMsgDoneType, _))
  56. .WillOnce(DoAll(SaveArg<1>(&mDoneFn), Return(ok)));
  57. mListener.reset(new NFLogListener(mNLListener));
  58. }
  59. ~NFLogListenerTest() {
  60. EXPECT_CALL(*mNLListener, unsubscribe(kNFLogPacketMsgType)).WillOnce(Return(ok));
  61. EXPECT_CALL(*mNLListener, unsubscribe(kNetlinkMsgDoneType)).WillOnce(Return(ok));
  62. }
  63. static StatusOr<size_t> sendOk(const Slice buf) { return buf.size(); }
  64. void subscribe(uint16_t type, const NFLogListenerInterface::DispatchFn& fn) {
  65. // Two sends for cfgCmdBind() & cfgMode(), one send at destruction time for cfgCmdUnbind()
  66. EXPECT_CALL(*mNLListener, send(_)).Times(Exactly(3)).WillRepeatedly(Invoke(sendOk));
  67. EXPECT_OK(mListener->subscribe(type, fn));
  68. }
  69. void sendEmptyMsg(uint16_t type) {
  70. struct {
  71. nlmsghdr nlmsg;
  72. nfgenmsg nfmsg;
  73. } msg = {};
  74. msg.nlmsg.nlmsg_type = kNFLogPacketMsgType;
  75. msg.nlmsg.nlmsg_len = sizeof(msg);
  76. msg.nfmsg.res_id = htons(type);
  77. mPacketFn(msg.nlmsg, drop(makeSlice(msg), sizeof(msg.nlmsg)));
  78. }
  79. NetlinkListenerInterface::DispatchFn mPacketFn;
  80. NetlinkListenerInterface::DispatchFn mDoneFn;
  81. std::shared_ptr<StrictMock<MockNetlinkListener>> mNLListener{
  82. new StrictMock<MockNetlinkListener>()};
  83. std::unique_ptr<NFLogListener> mListener;
  84. };
  85. TEST_F(NFLogListenerTest, subscribe) {
  86. constexpr uint16_t kType = 38;
  87. const auto dispatchFn = [](const nlmsghdr&, const nfgenmsg&, const Slice) {};
  88. subscribe(kType, dispatchFn);
  89. }
  90. TEST_F(NFLogListenerTest, nlmsgDone) {
  91. constexpr uint16_t kType = 38;
  92. const auto dispatchFn = [](const nlmsghdr&, const nfgenmsg&, const Slice) {};
  93. subscribe(kType, dispatchFn);
  94. mDoneFn({}, {});
  95. }
  96. TEST_F(NFLogListenerTest, dispatchOk) {
  97. int invocations = 0;
  98. constexpr uint16_t kType = 38;
  99. const auto dispatchFn = [&invocations, kType](const nlmsghdr&, const nfgenmsg& nfmsg,
  100. const Slice) {
  101. EXPECT_EQ(kType, ntohs(nfmsg.res_id));
  102. ++invocations;
  103. };
  104. subscribe(kType, dispatchFn);
  105. sendEmptyMsg(kType);
  106. EXPECT_EQ(1, invocations);
  107. }
  108. TEST_F(NFLogListenerTest, dispatchUnknownType) {
  109. constexpr uint16_t kType = 38;
  110. constexpr uint16_t kBadType = kType + 1;
  111. const auto dispatchFn = [](const nlmsghdr&, const nfgenmsg&, const Slice) {
  112. // Expect no invocations
  113. ASSERT_TRUE(false);
  114. };
  115. subscribe(kType, dispatchFn);
  116. sendEmptyMsg(kBadType);
  117. }
  118. } // namespace net
  119. } // namespace android