// Copyright 2021 Google LLC
//
// 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 "net_iface_mock.h"
#include "nic_mock.h"
#include "platforms/nemora/portable/default_addresses.h"
#include "platforms/nemora/portable/ncsi.h"
#include "platforms/nemora/portable/ncsi_fsm.h"
#include "platforms/nemora/portable/net_types.h"

#include <ncsi_state_machine.h>
#include <net_config.h>
#include <net_sockio.h>
#include <netinet/ether.h>
#include <netinet/in.h>

#include <gmock/gmock.h>

namespace
{

constexpr uint32_t ETHER_NCSI = 0x88f8;

class MockConfig : public net::ConfigBase
{
  public:
    int get_mac_addr(mac_addr_t* mac) override
    {
        std::memcpy(mac, &mac_addr, sizeof(mac_addr_t));

        return 0;
    }

    int set_mac_addr(const mac_addr_t& mac) override
    {
        mac_addr = mac;

        return 0;
    }

    int set_nic_hostless(bool is_hostless) override
    {
        is_nic_hostless = is_hostless;

        return 0;
    }

    mac_addr_t mac_addr;
    bool is_nic_hostless = true;
};

class NICConnection : public net::SockIO
{
  public:
    int write(const void* buf, size_t len) override
    {
        conseq_reads = 0;
        ++n_writes;
        std::memcpy(last_write.data, buf, len);
        last_write.len = len;
        const auto* hdr = reinterpret_cast<const struct ether_header*>(buf);
        if (ETHER_NCSI == ntohs(hdr->ether_type))
        {
            ++n_handles;
            next_read.len = nic_mock.handle_request(last_write, &next_read);
        }

        return len;
    }

    int recv(void* buf, size_t maxlen) override
    {
        ++n_reads;
        ++conseq_reads;

        if (read_timeout > 0)
        {
            if (conseq_reads > read_timeout)
            {
                return 0;
            }
        }

        if (maxlen < next_read.len)
        {
            ++n_read_errs;
            return 0;
        }

        std::memcpy(buf, next_read.data, next_read.len);

        return next_read.len;
    }

    mock::NIC nic_mock{false, 2};
    int n_writes = 0;
    int n_reads = 0;
    int n_handles = 0;
    int n_read_errs = 0;

    // Max number of consequitive reads without writes.
    int read_timeout = -1;
    int conseq_reads = 0;

    ncsi_buf_t last_write = {};
    ncsi_buf_t next_read = {};
};

} // namespace

class TestNcsi : public testing::Test
{
  public:
    void SetUp() override
    {
        ncsi_sm.set_sockio(&ncsi_sock);
        ncsi_sm.set_net_config(&net_config_mock);
        ncsi_sm.set_retest_delay(0);
        ncsi_sock.nic_mock.set_mac(nic_mac);
        ncsi_sock.nic_mock.set_hostless(true);
        ncsi_sock.read_timeout = 10;
    }

  protected:
    void ExpectFiltersNotConfigured()
    {
        for (uint8_t i = 0; i < ncsi_sock.nic_mock.get_channel_count(); ++i)
        {
            EXPECT_FALSE(ncsi_sock.nic_mock.is_filter_configured(i));
        }
    }

    void ExpectFiltersConfigured()
    {
        // Check that filters are configured on all channels.
        for (uint8_t i = 0; i < ncsi_sock.nic_mock.get_channel_count(); ++i)
        {
            EXPECT_TRUE(ncsi_sock.nic_mock.is_filter_configured(i));
            const ncsi_oem_filter_t& ch_filter =
                ncsi_sock.nic_mock.get_filter(i);

            for (unsigned i = 0; i < sizeof(nic_mac.octet); ++i)
            {
                EXPECT_EQ(nic_mac.octet[i], ch_filter.mac[i]);
            }

            EXPECT_EQ(ch_filter.ip, 0);
            const uint16_t filter_port = ntohs(ch_filter.port);
            EXPECT_EQ(filter_port, DEFAULT_ADDRESSES_RX_PORT);
        }
    }

    MockConfig net_config_mock;
    NICConnection ncsi_sock;
    ncsi::StateMachine ncsi_sm;
    const mac_addr_t nic_mac = {{0xde, 0xca, 0xfb, 0xad, 0x01, 0x02}};

    // Number of states in each state machine
    static constexpr int l2_num_states = 26;
    static constexpr int l3l4_num_states = 2;
    static constexpr int test_num_states = 9;

    // Total number of states in all three state machines.
    static constexpr int total_num_states =
        l2_num_states + l3l4_num_states + test_num_states;
};

TEST_F(TestNcsi, TestMACAddrPropagation)
{
    ncsi_sm.run(total_num_states);
    EXPECT_EQ(ncsi_sock.n_read_errs, 0);
    EXPECT_EQ(ncsi_sock.n_handles, ncsi_sock.n_writes);
    EXPECT_EQ(0, std::memcmp(nic_mac.octet, net_config_mock.mac_addr.octet,
                             sizeof(nic_mac.octet)));

    // Since network is not configured, the filters should not be configured
    // either.
    ExpectFiltersNotConfigured();
}

TEST_F(TestNcsi, TestFilterConfiguration)
{
    ncsi_sm.run(total_num_states);
    EXPECT_EQ(ncsi_sock.n_read_errs, 0);
    EXPECT_EQ(ncsi_sock.n_handles, ncsi_sock.n_writes);

    ExpectFiltersConfigured();
}

TEST_F(TestNcsi, TestFilterReset)
{
    ncsi_sm.run(total_num_states);
    EXPECT_EQ(ncsi_sock.n_read_errs, 0);
    EXPECT_EQ(ncsi_sock.n_handles, ncsi_sock.n_writes);

    // Since network is not configured, the filters should not be configured
    // either.
    ExpectFiltersNotConfigured();

    ncsi_sm.run(total_num_states);

    ExpectFiltersConfigured();
}

TEST_F(TestNcsi, TestRetest)
{
    ncsi_sm.run(total_num_states + test_num_states);

    // Verify that the test state machine was stepped through twice,
    // by counting how many times the last command of the state machine
    // has been executed.
    const uint8_t last_test_command = NCSI_GET_LINK_STATUS;
    const auto& cmd_log = ncsi_sock.nic_mock.get_command_log();
    int num_test_runs = 0;
    for (const auto& ncsi_frame : cmd_log)
    {
        if (ncsi_frame.get_control_packet_type() == last_test_command)
        {
            ++num_test_runs;
        }
    }

    EXPECT_EQ(num_test_runs, 2);
}

TEST_F(TestNcsi, TestHostlessSwitch)
{
    // By default the NIC is in hostless mode.
    // Verify that net config flag changes after FSM run.
    net_config_mock.is_nic_hostless = false;
    ncsi_sm.run(total_num_states);
    EXPECT_EQ(ncsi_sock.n_read_errs, 0);
    EXPECT_EQ(ncsi_sock.n_handles, ncsi_sock.n_writes);
    EXPECT_TRUE(net_config_mock.is_nic_hostless);

    // Now disable the hostless mode and verify that net config
    // flag changes to false.
    ncsi_sock.nic_mock.set_hostless(false);
    ncsi_sm.run(total_num_states);
    EXPECT_EQ(ncsi_sock.n_read_errs, 0);
    EXPECT_EQ(ncsi_sock.n_handles, ncsi_sock.n_writes);
    EXPECT_FALSE(net_config_mock.is_nic_hostless);
}
