/*
 * Copyright (C) 2017 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.
 */

#include <ifaddrs.h>
#include <net/if.h>
#include <sys/types.h>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <netdutils/MockSyscalls.h>

#include "InterfaceController.h"

using testing::ByMove;
using testing::Invoke;
using testing::Return;
using testing::StrictMock;
using testing::_;

namespace android {
namespace net {
namespace {

using netdutils::Fd;
using netdutils::ScopedMockSyscalls;
using netdutils::Slice;
using netdutils::Status;
using netdutils::StatusOr;
using netdutils::UniqueFd;
using netdutils::makeSlice;
using netdutils::status::ok;
using netdutils::statusFromErrno;

constexpr Fd kDevRandomFd(777);
constexpr Fd kStableSecretFd(9999);
const char kDevRandomPath[] = "/dev/random";
const char kTestIface[] = "wlan5";
const char kStableSecretProperty[] = "persist.netd.stable_secret";
const char kStableSecretPath[] = "/proc/sys/net/ipv6/conf/wlan5/stable_secret";
const char kTestIPv6Address[] = "\x20\x01\x0d\xb8\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10";
const char kTestIPv6AddressString[] = "2001:db8:506:708:90a:b0c:d0e:f10";

// getProperty() and setProperty() are forwarded to this mock
class MockProperties {
  public:
    MOCK_CONST_METHOD2(get, std::string(const std::string& key, const std::string& dflt));
    MOCK_CONST_METHOD2(set, Status(const std::string& key, const std::string& val));
};

}  // namespace

class StablePrivacyTest : public testing::Test {
  protected:
    void expectOpenFile(const std::string& path, const Fd fd, int err) {
        if (err == 0) {
            EXPECT_CALL(mSyscalls, open(path, _, _)).WillOnce(Return(ByMove(UniqueFd(fd))));
            EXPECT_CALL(mSyscalls, close(fd)).WillOnce(Return(ok));
        } else {
            EXPECT_CALL(mSyscalls, open(path, _, _))
                .WillOnce(Return(ByMove(statusFromErrno(err, "open() failed"))));
        }
    }

    void expectReadFromDevRandom(const std::string& data) {
        expectOpenFile(kDevRandomPath, kDevRandomFd, 0);
        EXPECT_CALL(mSyscalls, read(kDevRandomFd, _)).WillOnce(Invoke([data](Fd, const Slice buf) {
            EXPECT_EQ(data.size(), buf.size());
            return take(buf, copy(buf, makeSlice(data)));
        }));
    }

    void expectGetPropertyDefault(const std::string& key) {
        EXPECT_CALL(mProperties, get(key, _))
            .WillOnce(Invoke([](const std::string&, const std::string& dflt) { return dflt; }));
    }

    void expectGetProperty(const std::string& key, const std::string& val) {
        EXPECT_CALL(mProperties, get(key, _))
            .WillOnce(Invoke([val](const std::string&, const std::string&) { return val; }));
    }

    void expectSetProperty(const std::string& key, const std::string& val, Status status) {
        EXPECT_CALL(mProperties, set(key, val)).WillOnce(Return(status));
    }

    void expectWriteToFile(const Fd fd, const std::string& val, int err) {
        EXPECT_CALL(mSyscalls, write(fd, _))
            .WillOnce(Invoke([val, err](Fd, const Slice buf) -> StatusOr<size_t> {
                EXPECT_EQ(val, toString(buf));
                if (err) {
                    return statusFromErrno(err, "write() failed");
                }
                return val.size();
            }));
    }

    Status enableStablePrivacyAddresses(const std::string& iface) {
        return InterfaceController::enableStablePrivacyAddresses(iface, mGet, mSet);
    }

    StrictMock<ScopedMockSyscalls> mSyscalls;
    StrictMock<MockProperties> mProperties;

    const std::function<std::string(const std::string&, const std::string&)> mGet =
        [this](const std::string& key, const std::string& dflt) {
            return mProperties.get(key, dflt);
        };
    const std::function<Status(const std::string&, const std::string&)> mSet =
        [this](const std::string& key, const std::string& val) {
            return mProperties.set(key, val);
        };
};

TEST_F(StablePrivacyTest, PropertyOpenEnoent) {
    expectOpenFile(kStableSecretPath, kStableSecretFd, ENOENT);
    EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
}

TEST_F(StablePrivacyTest, PropertyOpenEaccess) {
    expectOpenFile(kStableSecretPath, kStableSecretFd, EACCES);
    EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
}

TEST_F(StablePrivacyTest, FirstBootWriteOkSetPropertyOk) {
    expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
    expectGetPropertyDefault(kStableSecretProperty);
    expectReadFromDevRandom(kTestIPv6Address);
    expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0);
    expectSetProperty(kStableSecretProperty, kTestIPv6AddressString, ok);
    EXPECT_EQ(ok, enableStablePrivacyAddresses(kTestIface));
}

TEST_F(StablePrivacyTest, FirstBootWriteOkSetPropertyFail) {
    const auto kError = statusFromErrno(EINVAL, "");
    expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
    expectGetPropertyDefault(kStableSecretProperty);
    expectReadFromDevRandom(kTestIPv6Address);
    expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0);
    expectSetProperty(kStableSecretProperty, kTestIPv6AddressString, kError);
    EXPECT_EQ(kError, enableStablePrivacyAddresses(kTestIface));
}

TEST_F(StablePrivacyTest, FirstBootWriteFail) {
    expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
    expectGetPropertyDefault(kStableSecretProperty);
    expectReadFromDevRandom(kTestIPv6Address);
    expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, ENOSPC);
    EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
}

TEST_F(StablePrivacyTest, ExistingPropertyWriteOk) {
    expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
    expectGetProperty(kStableSecretProperty, kTestIPv6AddressString);
    expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0);
    EXPECT_EQ(ok, enableStablePrivacyAddresses(kTestIface));
}

TEST_F(StablePrivacyTest, ExistingPropertyWriteFail) {
    expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
    expectGetProperty(kStableSecretProperty, kTestIPv6AddressString);
    expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, EACCES);
    EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
}

class GetIfaceListTest : public testing::Test {};

TEST_F(GetIfaceListTest, IfaceNames) {
    StatusOr<std::vector<std::string>> ifaceNames = InterfaceController::getIfaceNames();
    EXPECT_EQ(ok, ifaceNames.status());
    struct ifaddrs *ifaddr, *ifa;
    EXPECT_EQ(0, getifaddrs(&ifaddr));
    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        const auto val = std::find(
                ifaceNames.value().begin(), ifaceNames.value().end(), ifa->ifa_name);
        EXPECT_NE(ifaceNames.value().end(), val);
    }
    freeifaddrs(ifaddr);
}

TEST_F(GetIfaceListTest, IfaceExist) {
    StatusOr<std::map<std::string, uint32_t>> ifaceMap = InterfaceController::getIfaceList();
    EXPECT_EQ(ok, ifaceMap.status());
    struct ifaddrs *ifaddr, *ifa;
    EXPECT_EQ(0, getifaddrs(&ifaddr));
    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
        uint32_t ifaceIndex = if_nametoindex(ifa->ifa_name);
        const auto ifacePair = ifaceMap.value().find(ifa->ifa_name);
        EXPECT_NE(ifaceMap.value().end(), ifacePair);
        EXPECT_EQ(ifaceIndex, ifacePair->second);
    }
    freeifaddrs(ifaddr);
}

}  // namespace net
}  // namespace android
