// Copyright 2019 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.

// Instantiations of filter tests with filter tree builder.

#include <zxtest/zxtest.h>

#include <type_traits>
#include <unordered_map>

#include "filter_builder_impl.h"
#include "filter_test.h"

namespace netdump::test {

static Tokenizer tkz{};
static parser::FilterTreeBuilder bld{tkz};

template <typename T>
class TokenMap;

template <>
class TokenMap<LengthComparator> {
 public:
  const std::unordered_map<LengthComparator, TokenPtr> map{{LEQ, tkz.LESS}, {GEQ, tkz.GREATER}};
};

template <>
class TokenMap<AddressFieldType> {
 public:
  const std::unordered_map<AddressFieldType, TokenPtr> map{
      {SRC_ADDR, tkz.SRC}, {DST_ADDR, tkz.DST}, {EITHER_ADDR, tkz.HOST}};
};

template <>
class TokenMap<PortFieldType> {
 public:
  const std::unordered_map<PortFieldType, TokenPtr> map{
      {SRC_PORT, tkz.SRC}, {DST_PORT, tkz.DST}, {EITHER_PORT, tkz.PORT}};
};

template <typename T>
static inline TokenPtr lookup_token(T key) {
  TokenMap<T> tm{};
  auto token = tm.map.find(key);
  ZX_DEBUG_ASSERT(token != tm.map.end());
  return token->second;
}

template <class Flt>
class CallFilterBuilder;

template <>
class CallFilterBuilder<FrameLengthFilter> {
 public:
  inline FilterPtr operator()(uint16_t length, LengthComparator comparator) {
    return bld.frame_length(htons(length), lookup_token(comparator));
  }
};

template <>
class CallFilterBuilder<EthFilter> {
 public:
  inline FilterPtr operator()(uint16_t ethtype) { return bld.ethertype(htons(ethtype)); }
  inline FilterPtr operator()(EthFilter::MacAddress mac, AddressFieldType type) {
    std::reverse(mac.begin(), mac.end());
    return bld.mac(mac, lookup_token(type));
  }
};

template <>
class CallFilterBuilder<IpFilter> {
 public:
  inline FilterPtr operator()(uint8_t version) { return bld.ip_version(version); }
  inline FilterPtr operator()(uint8_t version, uint8_t protocol) {
    return bld.ip_protocol(version, protocol);
  }
  inline FilterPtr operator()(uint8_t version, uint16_t length, LengthComparator comparator) {
    return bld.ip_pkt_length(version, htons(length), lookup_token(comparator));
  }
  inline FilterPtr operator()(uint32_t ipv4_addr, AddressFieldType type) {
    return bld.ipv4_address(htonl(ipv4_addr), lookup_token(type));
  }
  inline FilterPtr operator()(IpFilter::IPv6Address ipv6_addr, AddressFieldType type) {
    std::reverse(ipv6_addr.begin(), ipv6_addr.end());
    return bld.ipv6_address(ipv6_addr, lookup_token(type));
  }
};

template <>
class CallFilterBuilder<PortFilter> {
 public:
  inline FilterPtr operator()(std::vector<PortRange> ranges, PortFieldType type) {
    for (auto it = ranges.begin(); it < ranges.end(); ++it) {
      it->first = htons(it->first);
      it->second = htons(it->second);
    }
    return bld.ports(std::move(ranges), lookup_token(type));
  }
};

template <>
class CallFilterBuilder<NegFilter> {
 public:
  inline FilterPtr operator()(FilterPtr filter) { return bld.negation(std::move(filter)); }
};

template <>
class CallFilterBuilder<ConjFilter> {
 public:
  inline FilterPtr operator()(FilterPtr left, FilterPtr right) {
    return bld.conjunction(std::move(left), std::move(right));
  }
};

template <>
class CallFilterBuilder<DisjFilter> {
 public:
  inline FilterPtr operator()(FilterPtr left, FilterPtr right) {
    return bld.disjunction(std::move(left), std::move(right));
  }
};

#define NETDUMP_TEST(test, flt) \
  TEST(NetdumpFilterBuilderTest, test) { test(CallFilterBuilder<flt>()); }

NETDUMP_TEST(FrameLengthTest, FrameLengthFilter)
NETDUMP_TEST(EthtypeTest, EthFilter)
NETDUMP_TEST(MacTest, EthFilter)
NETDUMP_TEST(VersionTest, IpFilter)
NETDUMP_TEST(IPLengthTest, IpFilter)
NETDUMP_TEST(ProtocolTest, IpFilter)
NETDUMP_TEST(IPv4AddrTest, IpFilter)
NETDUMP_TEST(IPv6AddrTest, IpFilter)
NETDUMP_TEST(IPv4PortsTest, PortFilter)
NETDUMP_TEST(IPv6PortsTest, PortFilter)

#undef NETDUMP_TEST

TEST(NetdumpFilterBuilderTest, UnsupportedIpVersionAssertTest) {
  UnsupportedIpVersionAssertTest(CallFilterBuilder<IpFilter>(), CallFilterBuilder<IpFilter>(),
                                 CallFilterBuilder<IpFilter>());
}

TEST(NetdumpFilterBuilderTest, CompositionTest) {
  CompositionTest(CallFilterBuilder<NegFilter>(), CallFilterBuilder<ConjFilter>(),
                  CallFilterBuilder<DisjFilter>());
}

}  // namespace netdump::test
