1 //===-- PortMapTest.cpp ---------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Testing/Support/Error.h" 10 #include "gmock/gmock.h" 11 #include "gtest/gtest.h" 12 13 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h" 14 15 using namespace lldb_private::process_gdb_remote; 16 17 TEST(PortMapTest, Constructors) { 18 // Default construct to empty map 19 GDBRemoteCommunicationServerPlatform::PortMap p1; 20 ASSERT_TRUE(p1.empty()); 21 22 // Empty means no restrictions, return 0 and and bind to get a port 23 llvm::Expected<uint16_t> available_port = p1.GetNextAvailablePort(); 24 ASSERT_THAT_EXPECTED(available_port, llvm::HasValue(0)); 25 26 // Adding any port makes it not empty 27 p1.AllowPort(1); 28 ASSERT_FALSE(p1.empty()); 29 30 // So we will return the added port this time 31 available_port = p1.GetNextAvailablePort(); 32 ASSERT_THAT_EXPECTED(available_port, llvm::HasValue(1)); 33 34 // Construct from a range of ports 35 GDBRemoteCommunicationServerPlatform::PortMap p2(1, 4); 36 ASSERT_FALSE(p2.empty()); 37 38 // Use up all the ports 39 for (uint16_t expected = 1; expected < 4; ++expected) { 40 available_port = p2.GetNextAvailablePort(); 41 ASSERT_THAT_EXPECTED(available_port, llvm::HasValue(expected)); 42 p2.AssociatePortWithProcess(*available_port, 1); 43 } 44 45 // Now we fail since we're not an empty port map but all ports are used 46 available_port = p2.GetNextAvailablePort(); 47 ASSERT_THAT_EXPECTED(available_port, llvm::Failed()); 48 } 49 50 TEST(PortMapTest, FreePort) { 51 GDBRemoteCommunicationServerPlatform::PortMap p(1, 4); 52 // Use up all the ports 53 for (uint16_t port = 1; port < 4; ++port) { 54 p.AssociatePortWithProcess(port, 1); 55 } 56 57 llvm::Expected<uint16_t> available_port = p.GetNextAvailablePort(); 58 ASSERT_THAT_EXPECTED(available_port, llvm::Failed()); 59 60 // Can't free a port that isn't in the map 61 ASSERT_FALSE(p.FreePort(0)); 62 ASSERT_FALSE(p.FreePort(4)); 63 64 // After freeing a port it becomes available 65 ASSERT_TRUE(p.FreePort(2)); 66 available_port = p.GetNextAvailablePort(); 67 ASSERT_THAT_EXPECTED(available_port, llvm::HasValue(2)); 68 } 69 70 TEST(PortMapTest, FreePortForProcess) { 71 GDBRemoteCommunicationServerPlatform::PortMap p; 72 p.AllowPort(1); 73 p.AllowPort(2); 74 ASSERT_TRUE(p.AssociatePortWithProcess(1, 11)); 75 ASSERT_TRUE(p.AssociatePortWithProcess(2, 22)); 76 77 // All ports have been used 78 llvm::Expected<uint16_t> available_port = p.GetNextAvailablePort(); 79 ASSERT_THAT_EXPECTED(available_port, llvm::Failed()); 80 81 // Can't free a port for a process that doesn't have any 82 ASSERT_FALSE(p.FreePortForProcess(33)); 83 84 // You can move a used port to a new pid 85 ASSERT_TRUE(p.AssociatePortWithProcess(1, 99)); 86 87 ASSERT_TRUE(p.FreePortForProcess(22)); 88 available_port = p.GetNextAvailablePort(); 89 ASSERT_THAT_EXPECTED(available_port, llvm::Succeeded()); 90 ASSERT_EQ(2, *available_port); 91 92 // proces 22 no longer has a port 93 ASSERT_FALSE(p.FreePortForProcess(22)); 94 } 95 96 TEST(PortMapTest, AllowPort) { 97 GDBRemoteCommunicationServerPlatform::PortMap p; 98 99 // Allow port 1 and tie it to process 11 100 p.AllowPort(1); 101 ASSERT_TRUE(p.AssociatePortWithProcess(1, 11)); 102 103 // Allowing it a second time shouldn't change existing mapping 104 p.AllowPort(1); 105 llvm::Expected<uint16_t> available_port = p.GetNextAvailablePort(); 106 ASSERT_THAT_EXPECTED(available_port, llvm::Failed()); 107 108 // A new port is marked as free when allowed 109 p.AllowPort(2); 110 available_port = p.GetNextAvailablePort(); 111 ASSERT_THAT_EXPECTED(available_port, llvm::HasValue(2)); 112 113 // 11 should still be tied to port 1 114 ASSERT_TRUE(p.FreePortForProcess(11)); 115 } 116