blob: 415d505864dd1c400c2cf09578fa0050d1914e3e [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PATCHPANEL_FAKE_SYSTEM_H_
#define PATCHPANEL_FAKE_SYSTEM_H_
#include <fcntl.h>
#include <linux/if_tun.h>
#include <linux/sockios.h>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <base/files/file_path.h>
#include <base/files/scoped_file.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "patchpanel/system.h"
namespace patchpanel {
class FakeSystem : public System {
public:
FakeSystem() = default;
~FakeSystem() override = default;
// Capture Ioctls operations and arguments. Always succeeds.
int Ioctl(int fd, ioctl_req_t request, const char* argp) override {
ioctl_reqs.push_back(request);
switch (request) {
case SIOCBRADDBR:
case SIOCBRDELBR: {
ioctl_ifreq_args.push_back({std::string(argp), {}});
break;
}
}
return 0;
}
int Ioctl(int fd, ioctl_req_t request, uint64_t arg) override {
ioctl_reqs.push_back(request);
return 0;
}
int Ioctl(int fd, ioctl_req_t request, struct ifreq* ifr) override {
ioctl_reqs.push_back(request);
switch (request) {
case SIOCBRADDIF:
case TUNSETIFF:
case SIOCSIFADDR:
case SIOCSIFNETMASK:
case SIOCSIFHWADDR:
case SIOCGIFFLAGS:
case SIOCSIFFLAGS: {
ioctl_ifreq_args.push_back({std::string(ifr->ifr_name), *ifr});
break;
}
}
return 0;
}
int Ioctl(int fd, ioctl_req_t request, struct rtentry* route) override {
ioctl_reqs.push_back(request);
switch (request) {
case SIOCADDRT:
case SIOCDELRT: {
ioctl_rtentry_args.push_back({"", *route});
// Copy the string pointed by rtentry.rt_dev because Add/DeleteIPv4Route
// pass this value to ioctl() on the stack.
if (route->rt_dev) {
auto& cap = ioctl_rtentry_args.back();
cap.first = std::string(route->rt_dev);
cap.second.rt_dev = const_cast<char*>(cap.first.c_str());
}
break;
}
}
return 0;
}
int Ioctl(int fd, ioctl_req_t request, struct in6_rtmsg* route) override {
ioctl_reqs.push_back(request);
return 0;
}
base::ScopedFD OpenTunDev() override {
return base::ScopedFD(open("/dev/null", O_RDONLY | O_CLOEXEC));
}
MOCK_METHOD(int, SocketPair, (int, int, int, int[2]), (override));
MOCK_METHOD(bool,
SysNetSet,
(SysNet, std::string_view, std::string_view),
(override));
MOCK_METHOD(std::string,
SysNetGet,
(SysNet, std::string_view),
(const, override));
MOCK_METHOD(int, IfNametoindex, (std::string_view), (override));
MOCK_METHOD(std::string, IfIndextoname, (int), (override));
MOCK_METHOD(bool,
WriteConfigFile,
(base::FilePath, std::string_view),
(override));
bool IsEbpfEnabled() const override { return true; }
std::vector<ioctl_req_t> ioctl_reqs;
std::vector<std::pair<std::string, struct rtentry>> ioctl_rtentry_args;
std::vector<std::pair<std::string, struct ifreq>> ioctl_ifreq_args;
};
} // namespace patchpanel
#endif // PATCHPANEL_FAKE_SYSTEM_H_