// Copyright 2017 The Fuchsia 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 <wlan/mlme/service.h>
#include <wlan/mlme/wlan.h>

#include <fuchsia/wlan/mlme/c/fidl.h>
#include <gtest/gtest.h>

#include <memory>
#include <utility>

#include "mock_device.h"

namespace wlan {

namespace wlan_mlme = ::fuchsia::wlan::mlme;

namespace {

struct ServiceTest : public ::testing::Test {
    ServiceTest() : device() {}

    MockDevice device;
};

template <typename T>
static fbl::unique_ptr<Packet> IntoPacket(const T& msg, uint32_t ordinal = 42) {
    // fidl2 doesn't have a way to get the serialized size yet. 4096 bytes should be enough for
    // everyone.
    constexpr size_t kBufLen = 4096;
    auto packet = GetSvcPacket(kBufLen);
    memset(packet->data(), 0, kBufLen);
    SerializeServiceMsg(packet.get(), ordinal, msg.get());
    return fbl::move(packet);
}

TEST(MlmeMsg, General) {
    // Construct simple message and write it to a Packet.
    auto fidl_msg = wlan_mlme::DeauthenticateRequest::New();
    common::kBcastMac.CopyTo(fidl_msg->peer_sta_address.mutable_data());
    auto pkt = IntoPacket(fidl_msg);

    // Verify correctness.
    MlmeMsg<wlan_mlme::DeauthenticateRequest> mlme_msg;
    auto status = MlmeMsg<wlan_mlme::DeauthenticateRequest>::FromPacket(fbl::move(pkt), &mlme_msg);
    ASSERT_EQ(status, ZX_OK);
    auto deauth_conf = mlme_msg.body();
    ASSERT_NE(deauth_conf, nullptr);
    ASSERT_EQ(memcmp(deauth_conf->peer_sta_address.data(), common::kBcastMac.byte, 6), 0);
}

TEST(MlmeMsg, Generalize) {
    // Construct simple message and write it to a Packet.
    auto fidl_msg = wlan_mlme::DeauthenticateRequest::New();
    common::kBcastMac.CopyTo(fidl_msg->peer_sta_address.mutable_data());
    auto pkt = IntoPacket(fidl_msg);

    MlmeMsg<wlan_mlme::DeauthenticateRequest> mlme_msg;
    auto status = MlmeMsg<wlan_mlme::DeauthenticateRequest>::FromPacket(fbl::move(pkt), &mlme_msg);
    ASSERT_EQ(status, ZX_OK);

    // Generalize message and attempt to specialize to wrong type.
    auto& generic_mlme_msg = static_cast<BaseMlmeMsg&>(mlme_msg);
    ASSERT_EQ(generic_mlme_msg.As<wlan_mlme::ScanRequest>(), nullptr);

    // Specialize message to correct type.
    auto deauth_conf = generic_mlme_msg.As<wlan_mlme::DeauthenticateRequest>();
    ASSERT_NE(deauth_conf, nullptr);
    ASSERT_EQ(memcmp(deauth_conf->body()->peer_sta_address.data(), common::kBcastMac.byte, 6), 0);
}

TEST(MlmeMsg, CorruptedPacket) {
    // Construct simple message but shorten it.
    auto fidl_msg = wlan_mlme::DeauthenticateRequest::New();
    common::kBcastMac.CopyTo(fidl_msg->peer_sta_address.mutable_data());
    auto pkt = IntoPacket(fidl_msg);
    pkt->set_len(pkt->len() - 1);

    // Verify correctness.
    MlmeMsg<wlan_mlme::DeauthenticateRequest> mlme_msg;
    auto status = MlmeMsg<wlan_mlme::DeauthenticateRequest>::FromPacket(fbl::move(pkt), &mlme_msg);
    ASSERT_NE(status, ZX_OK);
}

TEST_F(ServiceTest, SendAuthInd) {
    const common::MacAddr peer_sta({0x48, 0x0f, 0xcf, 0x54, 0xb9, 0xb1});
    wlan_mlme::AuthenticationTypes auth_type = wlan_mlme::AuthenticationTypes::OPEN_SYSTEM;

    service::SendAuthIndication(&device, peer_sta, auth_type);

    ASSERT_EQ(device.svc_queue.size(), static_cast<size_t>(1));
    auto inds = device.GetServicePackets(IsMlmeMsg<fuchsia_wlan_mlme_MLMEAuthenticateIndOrdinal>);
    ASSERT_EQ(inds.size(), static_cast<size_t>(1));
    ASSERT_EQ(inds[0]->peer(), Packet::Peer::kService);
    MlmeMsg<wlan_mlme::AuthenticateIndication> msg;
    auto status = MlmeMsg<wlan_mlme::AuthenticateIndication>::FromPacket(fbl::move(inds[0]), &msg);
    ASSERT_EQ(status, ZX_OK);

    ASSERT_EQ(std::memcmp(msg.body()->peer_sta_address.data(), peer_sta.byte, 6), 0);
    ASSERT_EQ(msg.body()->auth_type, wlan_mlme::AuthenticationTypes::OPEN_SYSTEM);
}

TEST_F(ServiceTest, SendAssocInd) {
    // -- prepare
    const common::MacAddr peer_sta({0x48, 0x0f, 0xcf, 0x54, 0xb9, 0xb1});
    uint16_t listen_interval = 100;

    constexpr uint8_t sside_bytes[] = {0u, 7u, 'F', 'U', 'C', 'H', 'S', 'I', 'A'};
    auto ssid_elem = reinterpret_cast<const SsidElement*>(sside_bytes);

    constexpr uint8_t rsne_bytes[] = {0x30, 8u, 1, 2, 3, 4, 5, 6, 7, 8};
    auto rsn_elem = reinterpret_cast<const RsnElement*>(rsne_bytes);

    // -- execute
    service::SendAssocIndication(&device, peer_sta, listen_interval, *ssid_elem, rsn_elem);

    // -- verify
    ASSERT_EQ(device.svc_queue.size(), static_cast<size_t>(1));
    auto inds = device.GetServicePackets(IsMlmeMsg<fuchsia_wlan_mlme_MLMEAssociateIndOrdinal>);
    ASSERT_EQ(inds.size(), static_cast<size_t>(1));
    ASSERT_EQ(inds[0]->peer(), Packet::Peer::kService);
    MlmeMsg<wlan_mlme::AssociateIndication> msg;
    auto status = MlmeMsg<wlan_mlme::AssociateIndication>::FromPacket(fbl::move(inds[0]), &msg);
    ASSERT_EQ(status, ZX_OK);

    ASSERT_EQ(std::memcmp(msg.body()->peer_sta_address.data(), peer_sta.byte, 6), 0);
    ASSERT_EQ(msg.body()->listen_interval, 100);
    ASSERT_EQ(std::memcmp(msg.body()->ssid->data(), sside_bytes + 2, sizeof(sside_bytes) - 2), 0);
    ASSERT_EQ(std::memcmp(msg.body()->rsn->data(), rsne_bytes, sizeof(rsne_bytes)), 0);
}

TEST_F(ServiceTest, SendAssocInd_EmptyRsne) {
    // -- prepare
    const common::MacAddr peer_sta({0x48, 0x0f, 0xcf, 0x54, 0xb9, 0xb1});
    uint16_t listen_interval = 100;

    constexpr uint8_t sside_bytes[] = {0u, 7u, 'F', 'U', 'C', 'H', 'S', 'I', 'A'};
    auto ssid_elem = reinterpret_cast<const SsidElement*>(sside_bytes);

    RsnElement* rsn_elem = nullptr;

    // -- execute
    service::SendAssocIndication(&device, peer_sta, listen_interval, *ssid_elem, rsn_elem);

    // -- verify
    ASSERT_EQ(device.svc_queue.size(), static_cast<size_t>(1));
    auto inds = device.GetServicePackets(IsMlmeMsg<fuchsia_wlan_mlme_MLMEAssociateIndOrdinal>);
    ASSERT_EQ(inds.size(), static_cast<size_t>(1));
    ASSERT_EQ(inds[0]->peer(), Packet::Peer::kService);
    MlmeMsg<wlan_mlme::AssociateIndication> msg;
    auto status = MlmeMsg<wlan_mlme::AssociateIndication>::FromPacket(fbl::move(inds[0]), &msg);
    ASSERT_EQ(status, ZX_OK);

    ASSERT_EQ(std::memcmp(msg.body()->peer_sta_address.data(), peer_sta.byte, 6), 0);
    ASSERT_EQ(msg.body()->listen_interval, 100);
    ASSERT_EQ(std::memcmp(msg.body()->ssid->data(), sside_bytes + 2, sizeof(sside_bytes) - 2), 0);
    ASSERT_TRUE(msg.body()->rsn.is_null());
}

}  // namespace
}  // namespace wlan
