blob: 84ed32f0ca6f4a2d3e1244aa05c9e7e32973569c [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "routing-simulator/packet.h"
#include <sstream>
#include <chromeos/net-base/ip_address.h>
#include <gtest/gtest.h>
namespace routing_simulator {
namespace {
// Notes: When protocol is ICMP, there is no port so you cannot input string for
// a port. Otherwise, you can and if you don't input anything for a port, random
// port is generated.
// Tests the case when input string is invalid when input protocol is TCP in
// IPv4.
TEST(PacketTest, InvalidInputIPv4WithTCP) {
std::string test_input =
"ttp\n"
"Tcp\n"
"wlan0\n"
" \n"
"168.34.34.0\n"
" \n"
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00\n"
"168.34.0.0\n"
"port\n"
"1990\n"
"0\n"
"-3\n"
"35\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
std::string actual = fake_output.str();
std::string expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: ttp\n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Input destination ip: "
"Invalid destination ip: \n"
"Input destination ip: "
"Input source ip: "
"Invalid source ip: \n"
"Input source ip: "
"Please input source ip in IPv4\n"
"Input source ip: "
"Input destination port: "
"Invalid destination port: port\n"
"Input destination port: "
"Input source port: "
"Invalid source port: 0 is not from 1 to 65535\n"
"Input source port: "
"Invalid source port: -3 is not from 1 to 65535\n"
"Input source port: ";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kTcp);
EXPECT_EQ(packet.input_interface(), "wlan0");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString("168.34.34.0").value());
EXPECT_EQ(packet.source_ip(),
net_base::IPAddress::CreateFromString("168.34.0.0").value());
EXPECT_EQ(packet.destination_port(), 1990);
EXPECT_EQ(packet.source_port(), 35);
}
// Tests the case when input string is invalid when input protocol is ICMP in
// IPv4.
TEST(PacketTest, InvalidInputIPv4WithICMP) {
std::string test_input =
" \n"
"icmp\n"
" \n"
"wlan0\n"
"add\n"
"168.34.34.0\n"
"aaa\n"
"168.98.0.0\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
const auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
const auto actual = fake_output.str();
const auto expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: \n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Invalid input interface: only whitespaces\n"
"Input input interface: "
"Input destination ip: "
"Invalid destination ip: add\n"
"Input destination ip: "
"Input source ip: "
"Invalid source ip: aaa\n"
"Input source ip: ";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kIcmp);
EXPECT_EQ(packet.input_interface(), "wlan0");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString("168.34.34.0").value());
EXPECT_EQ(packet.source_ip(),
net_base::IPAddress::CreateFromString("168.98.0.0").value());
EXPECT_EQ(packet.destination_port(), 0);
EXPECT_EQ(packet.source_port(), 0);
}
// Tests the case when input is empty when input protocol is UDP in IPv4.
TEST(PacketTest, NoInputIPv4WithUDP) {
std::string test_input =
"\n"
"udp\n"
"\n"
"\n"
"168.34.34.0\n"
"\n"
"168.34.0.0\n"
"\n"
"\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
std::string actual = fake_output.str();
std::string expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: \n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Input interface is empty, assume it is an egress packet\n"
"Input destination ip: "
"Invalid destination ip: \n"
"Input destination ip: "
"Input source ip: "
"Invalid source ip: \n"
"Input source ip: "
"Input destination port: "
"No input: destination port is set to a randomly generated number " +
std::to_string(packet.destination_port()) +
"\n"
"Input source port: "
"No input: source port is set to a randomly generated number " +
std::to_string(packet.source_port()) + "\n";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kUdp);
EXPECT_EQ(packet.input_interface(), "");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString("168.34.34.0").value());
EXPECT_EQ(packet.source_ip(),
net_base::IPAddress::CreateFromString("168.34.0.0").value());
// Check if the generated port is not a well-known port.
EXPECT_LE(packet.destination_port(), 65535);
EXPECT_GE(packet.destination_port(), 1024);
EXPECT_LE(packet.source_port(), 65535);
EXPECT_GE(packet.source_port(), 1024);
}
// Tests the case when input string is empty when input protocol is ICMP in
// IPv4.
TEST(PacketTest, NoInputIPv4WithICMP) {
std::string test_input =
"\n"
"ICMP\n"
"\n"
"\n"
"168.34.34.0\n"
"\n"
"168.34.0.0\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
std::string actual = fake_output.str();
std::string expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: \n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Input interface is empty, assume it is an egress packet\n"
"Input destination ip: "
"Invalid destination ip: \n"
"Input destination ip: "
"Input source ip: "
"Invalid source ip: \n"
"Input source ip: ";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kIcmp);
EXPECT_EQ(packet.input_interface(), "");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString("168.34.34.0").value());
EXPECT_EQ(packet.source_ip(),
net_base::IPAddress::CreateFromString("168.34.0.0").value());
EXPECT_EQ(packet.destination_port(), 0);
EXPECT_EQ(packet.source_port(), 0);
}
// Tests the case when input string contains whitespaces when input protocol is
// TCP in IPv4.
TEST(PacketTest, HandleWhitespaceIPv4WithTCP) {
std::string test_input =
"t tp\n"
"TCP\n"
"wlan 0\n"
"wlan0\n"
" 168 .34 .34 .0\n"
"168.34.34.0\n"
" 168.34.0.0\n"
"4 5 \n"
"45\n"
" 899\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
std::string actual = fake_output.str();
std::string expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: t tp\n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Invalid input interface: it contains whitespaces wlan 0\n"
"Input input interface: "
"Input destination ip: "
"Invalid destination ip: 168 .34 .34 .0\n"
"Input destination ip: "
"Input source ip: "
"Input destination port: "
"Invalid destination port: 4 5\n"
"Input destination port: "
"Input source port: ";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kTcp);
EXPECT_EQ(packet.input_interface(), "wlan0");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString("168.34.34.0").value());
EXPECT_EQ(packet.source_ip(),
net_base::IPAddress::CreateFromString("168.34.0.0").value());
EXPECT_EQ(packet.destination_port(), 45);
EXPECT_EQ(packet.source_port(), 899);
}
// Tests the case when input string contains whitespaces when input protocol is
// ICMP in IPv4.
TEST(PacketTest, HandleWhitespaceIPv4WithICMP) {
std::string test_input =
"ic mp\n"
"ICMP\n"
"wlan0 \n"
" 168.34.34.0 \n"
"168.34. 0.0\n"
"168.34.0.0\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
std::string actual = fake_output.str();
std::string expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: ic mp\n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Input destination ip: "
"Input source ip: "
"Invalid source ip: 168.34. 0.0\n"
"Input source ip: ";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kIcmp);
EXPECT_EQ(packet.input_interface(), "wlan0");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString("168.34.34.0").value());
EXPECT_EQ(packet.source_ip(),
net_base::IPAddress::CreateFromString("168.34.0.0").value());
EXPECT_EQ(packet.destination_port(), 0);
EXPECT_EQ(packet.source_port(), 0);
}
// Tests the case when input string is invalid when input protocol is TCP in
// IPv6.
TEST(PacketTest, InvalidInputIPv6WithTCP) {
std::string test_input =
"ttp\n"
"Tcp\n"
"wlan0\n"
" \n"
"2a00:79e1:abc:f604:faac:65ff:fe56:100d\n"
" \n"
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00\n"
"port\n"
"1990\n"
"0\n"
"-3\n"
"35\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
std::string actual = fake_output.str();
std::string expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: ttp\n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Input destination ip: "
"Invalid destination ip: \n"
"Input destination ip: "
"Input source ip: "
"Invalid source ip: \n"
"Input source ip: "
"Input destination port: "
"Invalid destination port: port\n"
"Input destination port: "
"Input source port: "
"Invalid source port: 0 is not from 1 to 65535\n"
"Input source port: "
"Invalid source port: -3 is not from 1 to 65535\n"
"Input source port: ";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kTcp);
EXPECT_EQ(packet.input_interface(), "wlan0");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString(
"2a00:79e1:abc:f604:faac:65ff:fe56:100d")
.value());
EXPECT_EQ(packet.source_ip(), net_base::IPAddress::CreateFromString(
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00")
.value());
EXPECT_EQ(packet.destination_port(), 1990);
EXPECT_EQ(packet.source_port(), 35);
}
// Tests the case when input string is invalid when input protocol is ICMP in
// IPv6.
TEST(PacketTest, InvalidInputIPv6WithICMP) {
std::string test_input =
" \n"
"icmp\n"
" \n"
"wlan0\n"
"add\n"
"2a00:79e1:abc:f604:faac:65ff:fe56:100d\n"
"aaa\n"
"168.34.0.0\n"
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
const auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
const auto actual = fake_output.str();
const auto expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: \n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Invalid input interface: only whitespaces\n"
"Input input interface: "
"Input destination ip: "
"Invalid destination ip: add\n"
"Input destination ip: "
"Input source ip: "
"Invalid source ip: aaa\n"
"Input source ip: "
"Please input source ip in IPv6\n"
"Input source ip: ";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kIcmp);
EXPECT_EQ(packet.input_interface(), "wlan0");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString(
"2a00:79e1:abc:f604:faac:65ff:fe56:100d")
.value());
EXPECT_EQ(packet.source_ip(), net_base::IPAddress::CreateFromString(
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00")
.value());
EXPECT_EQ(packet.destination_port(), 0);
EXPECT_EQ(packet.source_port(), 0);
}
// Tests the case when input string is empty when input protocol is UCP in IPv6.
TEST(PacketTest, NoInputIPv6WithUDP) {
std::string test_input =
"\n"
"udp\n"
"\n"
"\n"
"2a00:79e1:abc:f604:faac:65ff:fe56:100d\n"
"\n"
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00\n"
"\n"
"\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
std::string actual = fake_output.str();
std::string expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: \n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Input interface is empty, assume it is an egress packet\n"
"Input destination ip: "
"Invalid destination ip: \n"
"Input destination ip: "
"Input source ip: "
"Invalid source ip: \n"
"Input source ip: "
"Input destination port: "
"No input: destination port is set to a randomly generated number " +
std::to_string(packet.destination_port()) +
"\n"
"Input source port: "
"No input: source port is set to a randomly generated number " +
std::to_string(packet.source_port()) + "\n";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kUdp);
EXPECT_EQ(packet.input_interface(), "");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString(
"2a00:79e1:abc:f604:faac:65ff:fe56:100d")
.value());
EXPECT_EQ(packet.source_ip(), net_base::IPAddress::CreateFromString(
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00")
.value());
// Check if the generated port is not a well-known port.
EXPECT_LE(packet.destination_port(), 65535);
EXPECT_GE(packet.destination_port(), 1024);
EXPECT_LE(packet.source_port(), 65535);
EXPECT_GE(packet.source_port(), 1024);
}
// Tests the case when input string is empty when input protocol is ICMP in
// IPv6.
TEST(PacketTest, NoInputIPv6WithICMP) {
std::string test_input =
"\n"
"ICMP\n"
"\n"
"\n"
"2a00:79e1:abc:f604:faac:65ff:fe56:100d\n"
"\n"
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
std::string actual = fake_output.str();
std::string expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: \n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Input interface is empty, assume it is an egress packet\n"
"Input destination ip: "
"Invalid destination ip: \n"
"Input destination ip: "
"Input source ip: "
"Invalid source ip: \n"
"Input source ip: ";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kIcmp);
EXPECT_EQ(packet.input_interface(), "");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString(
"2a00:79e1:abc:f604:faac:65ff:fe56:100d")
.value());
EXPECT_EQ(packet.source_ip(), net_base::IPAddress::CreateFromString(
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00")
.value());
EXPECT_EQ(packet.destination_port(), 0);
EXPECT_EQ(packet.source_port(), 0);
}
// Tests the case when input string contains whitespaces when input protocol is
// TCP in IPv6.
TEST(PacketTest, HandleWhitespaceIPv6WithTCP) {
std::string test_input =
"t tp\n"
"TCP\n"
"wlan 0\n"
"wlan0\n"
" 2a00 :79e1 :abc: f604 :faac:65ff:fe56:100d\n"
"2a00:79e1:abc:f604:faac:65ff:fe56:100d\n"
" 2b23:79e1:abc:f604:faac:65ff:fe56:1d00\n"
"4 5 \n"
"45\n"
" 899\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
std::string actual = fake_output.str();
std::string expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: t tp\n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Invalid input interface: it contains whitespaces wlan 0\n"
"Input input interface: "
"Input destination ip: "
"Invalid destination ip: 2a00 :79e1 :abc: f604 :faac:65ff:fe56:100d\n"
"Input destination ip: "
"Input source ip: "
"Input destination port: "
"Invalid destination port: 4 5\n"
"Input destination port: "
"Input source port: ";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kTcp);
EXPECT_EQ(packet.input_interface(), "wlan0");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString(
"2a00:79e1:abc:f604:faac:65ff:fe56:100d")
.value());
EXPECT_EQ(packet.source_ip(), net_base::IPAddress::CreateFromString(
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00")
.value());
EXPECT_EQ(packet.destination_port(), 45);
EXPECT_EQ(packet.source_port(), 899);
}
// Tests the case when input string contains whitespaces when input protocol is
// ICMP in IPv6.
TEST(PacketTest, HandleWhitespaceIPv6WithICMP) {
std::string test_input =
"ic mp\n"
"ICMP\n"
"wlan0 \n"
" 2a00:79e1:abc:f604:faac:65ff:fe56:100d \n"
"2b23:79e1:abc: f604:faac:65ff:fe56:1d00\n"
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00\n";
// Fake an input from stdin.
std::stringstream fake_input(test_input);
// Fake an output from stdout.
std::stringstream fake_output;
auto packet = Packet::CreatePacketFromStdin(fake_input, fake_output);
std::string actual = fake_output.str();
std::string expected =
"Input protocol (TCP/UDP/ICMP): "
"Invalid protocol: ic mp\n"
"Input protocol (TCP/UDP/ICMP): "
"Input input interface: "
"Input destination ip: "
"Input source ip: "
"Invalid source ip: 2b23:79e1:abc: f604:faac:65ff:fe56:1d00\n"
"Input source ip: ";
EXPECT_EQ(actual, expected);
EXPECT_EQ(packet.protocol(), Packet::Protocol::kIcmp);
EXPECT_EQ(packet.input_interface(), "wlan0");
EXPECT_EQ(packet.destination_ip(),
net_base::IPAddress::CreateFromString(
"2a00:79e1:abc:f604:faac:65ff:fe56:100d")
.value());
EXPECT_EQ(packet.source_ip(), net_base::IPAddress::CreateFromString(
"2b23:79e1:abc:f604:faac:65ff:fe56:1d00")
.value());
EXPECT_EQ(packet.destination_port(), 0);
EXPECT_EQ(packet.source_port(), 0);
}
} // namespace
} // namespace routing_simulator