// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "quiche/quic/qbone/bonnet/tun_device.h"

#include <linux/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>

#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/qbone/platform/mock_kernel.h"

namespace quic::test {
namespace {

using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Return;
using ::testing::StrEq;
using ::testing::Unused;

const char kDeviceName[] = "tun0";
const int kSupportedFeatures =
    IFF_TUN | IFF_TAP | IFF_MULTI_QUEUE | IFF_ONE_QUEUE | IFF_NO_PI;

// Quite a bit of EXPECT_CALL().Times(AnyNumber()).WillRepeatedly() are used to
// make sure we can correctly set common expectations and override the
// expectation with later call to EXPECT_CALL(). ON_CALL cannot be used here
// since when EPXECT_CALL overrides ON_CALL, it ignores the parameter matcher
// which results in unexpected call even if ON_CALL exists.
class TunDeviceTest : public QuicTest {
 protected:
  void SetUp() override {
    EXPECT_CALL(mock_kernel_, socket(AF_INET6, _, _))
        .Times(AnyNumber())
        .WillRepeatedly([this](Unused, Unused, Unused) {
          EXPECT_CALL(mock_kernel_, close(next_fd_)).WillOnce(Return(0));
          return next_fd_++;
        });
  }

  // Set the expectations for calling Init().
  void SetInitExpectations(int mtu, bool persist) {
    EXPECT_CALL(mock_kernel_, open(StrEq("/dev/net/tun"), _))
        .Times(AnyNumber())
        .WillRepeatedly([this](Unused, Unused) {
          EXPECT_CALL(mock_kernel_, close(next_fd_)).WillOnce(Return(0));
          return next_fd_++;
        });
    EXPECT_CALL(mock_kernel_, ioctl(_, TUNGETFEATURES, _))
        .Times(AnyNumber())
        .WillRepeatedly([](Unused, Unused, void* argp) {
          auto* actual_flags = reinterpret_cast<int*>(argp);
          *actual_flags = kSupportedFeatures;
          return 0;
        });
    EXPECT_CALL(mock_kernel_, ioctl(_, TUNSETIFF, _))
        .Times(AnyNumber())
        .WillRepeatedly([](Unused, Unused, void* argp) {
          auto* ifr = reinterpret_cast<struct ifreq*>(argp);
          EXPECT_EQ(IFF_TUN | IFF_MULTI_QUEUE | IFF_NO_PI, ifr->ifr_flags);
          EXPECT_THAT(ifr->ifr_name, StrEq(kDeviceName));
          return 0;
        });
    EXPECT_CALL(mock_kernel_, ioctl(_, TUNSETPERSIST, _))
        .Times(AnyNumber())
        .WillRepeatedly([persist](Unused, Unused, void* argp) {
          auto* ifr = reinterpret_cast<struct ifreq*>(argp);
          if (persist) {
            EXPECT_THAT(ifr->ifr_name, StrEq(kDeviceName));
          } else {
            EXPECT_EQ(nullptr, ifr);
          }
          return 0;
        });
    EXPECT_CALL(mock_kernel_, ioctl(_, SIOCSIFMTU, _))
        .Times(AnyNumber())
        .WillRepeatedly([mtu](Unused, Unused, void* argp) {
          auto* ifr = reinterpret_cast<struct ifreq*>(argp);
          EXPECT_EQ(mtu, ifr->ifr_mtu);
          EXPECT_THAT(ifr->ifr_name, StrEq(kDeviceName));
          return 0;
        });
  }

  // Expect that Up() will be called. Force the call to fail when fail == true.
  void ExpectUp(bool fail) {
    EXPECT_CALL(mock_kernel_, ioctl(_, SIOCSIFFLAGS, _))
        .WillOnce([fail](Unused, Unused, void* argp) {
          auto* ifr = reinterpret_cast<struct ifreq*>(argp);
          EXPECT_TRUE(ifr->ifr_flags & IFF_UP);
          EXPECT_THAT(ifr->ifr_name, StrEq(kDeviceName));
          if (fail) {
            return -1;
          } else {
            return 0;
          }
        });
  }

  // Expect that Down() will be called *after* the interface is up. Force the
  // call to fail when fail == true.
  void ExpectDown(bool fail) {
    EXPECT_CALL(mock_kernel_, ioctl(_, SIOCSIFFLAGS, _))
        .WillOnce([fail](Unused, Unused, void* argp) {
          auto* ifr = reinterpret_cast<struct ifreq*>(argp);
          EXPECT_FALSE(ifr->ifr_flags & IFF_UP);
          EXPECT_THAT(ifr->ifr_name, StrEq(kDeviceName));
          if (fail) {
            return -1;
          } else {
            return 0;
          }
        });
  }

  MockKernel mock_kernel_;
  int next_fd_ = 100;
};

// A TunTapDevice can be initialized and up
TEST_F(TunDeviceTest, BasicWorkFlow) {
  SetInitExpectations(/* mtu = */ 1500, /* persist = */ false);
  TunTapDevice tun_device(kDeviceName, 1500, false, true, false, &mock_kernel_);
  EXPECT_TRUE(tun_device.Init());
  EXPECT_GT(tun_device.GetFileDescriptor(), -1);

  ExpectUp(/* fail = */ false);
  EXPECT_TRUE(tun_device.Up());
  ExpectDown(/* fail = */ false);
}

TEST_F(TunDeviceTest, FailToOpenTunDevice) {
  SetInitExpectations(/* mtu = */ 1500, /* persist = */ false);
  EXPECT_CALL(mock_kernel_, open(StrEq("/dev/net/tun"), _))
      .WillOnce(Return(-1));
  TunTapDevice tun_device(kDeviceName, 1500, false, true, false, &mock_kernel_);
  EXPECT_FALSE(tun_device.Init());
  EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
  ExpectDown(false);
}

TEST_F(TunDeviceTest, FailToCheckFeature) {
  SetInitExpectations(/* mtu = */ 1500, /* persist = */ false);
  EXPECT_CALL(mock_kernel_, ioctl(_, TUNGETFEATURES, _)).WillOnce(Return(-1));
  TunTapDevice tun_device(kDeviceName, 1500, false, true, false, &mock_kernel_);
  EXPECT_FALSE(tun_device.Init());
  EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
  ExpectDown(false);
}

TEST_F(TunDeviceTest, TooFewFeature) {
  SetInitExpectations(/* mtu = */ 1500, /* persist = */ false);
  EXPECT_CALL(mock_kernel_, ioctl(_, TUNGETFEATURES, _))
      .WillOnce([](Unused, Unused, void* argp) {
        int* actual_features = reinterpret_cast<int*>(argp);
        *actual_features = IFF_TUN | IFF_ONE_QUEUE;
        return 0;
      });
  TunTapDevice tun_device(kDeviceName, 1500, false, true, false, &mock_kernel_);
  EXPECT_FALSE(tun_device.Init());
  EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
  ExpectDown(false);
}

TEST_F(TunDeviceTest, FailToSetFlag) {
  SetInitExpectations(/* mtu = */ 1500, /* persist = */ true);
  EXPECT_CALL(mock_kernel_, ioctl(_, TUNSETIFF, _)).WillOnce(Return(-1));
  TunTapDevice tun_device(kDeviceName, 1500, true, true, false, &mock_kernel_);
  EXPECT_FALSE(tun_device.Init());
  EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}

TEST_F(TunDeviceTest, FailToPersistDevice) {
  SetInitExpectations(/* mtu = */ 1500, /* persist = */ true);
  EXPECT_CALL(mock_kernel_, ioctl(_, TUNSETPERSIST, _)).WillOnce(Return(-1));
  TunTapDevice tun_device(kDeviceName, 1500, true, true, false, &mock_kernel_);
  EXPECT_FALSE(tun_device.Init());
  EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}

TEST_F(TunDeviceTest, FailToOpenSocket) {
  SetInitExpectations(/* mtu = */ 1500, /* persist = */ true);
  EXPECT_CALL(mock_kernel_, socket(AF_INET6, _, _)).WillOnce(Return(-1));
  TunTapDevice tun_device(kDeviceName, 1500, true, true, false, &mock_kernel_);
  EXPECT_FALSE(tun_device.Init());
  EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}

TEST_F(TunDeviceTest, FailToSetMtu) {
  SetInitExpectations(/* mtu = */ 1500, /* persist = */ true);
  EXPECT_CALL(mock_kernel_, ioctl(_, SIOCSIFMTU, _)).WillOnce(Return(-1));
  TunTapDevice tun_device(kDeviceName, 1500, true, true, false, &mock_kernel_);
  EXPECT_FALSE(tun_device.Init());
  EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
}

TEST_F(TunDeviceTest, FailToUp) {
  SetInitExpectations(/* mtu = */ 1500, /* persist = */ true);
  TunTapDevice tun_device(kDeviceName, 1500, true, true, false, &mock_kernel_);
  EXPECT_TRUE(tun_device.Init());
  EXPECT_GT(tun_device.GetFileDescriptor(), -1);

  ExpectUp(/* fail = */ true);
  EXPECT_FALSE(tun_device.Up());
}

}  // namespace
}  // namespace quic::test
