mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-05-17 11:26:37 +00:00

Previously if you did: $ lldb-server platform --server <...> --min-gdbserver-port 12346 --max-gdbserver-port 12347 (meaning only use port 12346 for gdbservers) Then tried to launch two gdbservers on the same connection, the second one would return port 65535. Which is a real port number but it actually means lldb-server didn't find one it was allowed to use. send packet: $qLaunchGDBServer;<...> read packet: $pid:1919;port:12346;#c0 <...> send packet: $qLaunchGDBServer;<...> read packet: $pid:1927;port:65535;#c7 This situation should be an error even if port 65535 does happen to be available on the current machine. To fix this make PortMap it's own class within GDBRemoteCommunicationServerPlatform. This almost the same as the old typedef but for GetNextAvailablePort() returning an llvm::Expected. This means we have to handle not finding a port, by returning an error packet. Also add unit tests for this new PortMap class. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D91634
116 lines
3.8 KiB
C++
116 lines
3.8 KiB
C++
//===-- PortMapTest.cpp ---------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Testing/Support/Error.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h"
|
|
|
|
using namespace lldb_private::process_gdb_remote;
|
|
|
|
TEST(PortMapTest, Constructors) {
|
|
// Default construct to empty map
|
|
GDBRemoteCommunicationServerPlatform::PortMap p1;
|
|
ASSERT_TRUE(p1.empty());
|
|
|
|
// Empty means no restrictions, return 0 and and bind to get a port
|
|
llvm::Expected<uint16_t> available_port = p1.GetNextAvailablePort();
|
|
ASSERT_THAT_EXPECTED(available_port, llvm::HasValue(0));
|
|
|
|
// Adding any port makes it not empty
|
|
p1.AllowPort(1);
|
|
ASSERT_FALSE(p1.empty());
|
|
|
|
// So we will return the added port this time
|
|
available_port = p1.GetNextAvailablePort();
|
|
ASSERT_THAT_EXPECTED(available_port, llvm::HasValue(1));
|
|
|
|
// Construct from a range of ports
|
|
GDBRemoteCommunicationServerPlatform::PortMap p2(1, 4);
|
|
ASSERT_FALSE(p2.empty());
|
|
|
|
// Use up all the ports
|
|
for (uint16_t expected = 1; expected < 4; ++expected) {
|
|
available_port = p2.GetNextAvailablePort();
|
|
ASSERT_THAT_EXPECTED(available_port, llvm::HasValue(expected));
|
|
p2.AssociatePortWithProcess(*available_port, 1);
|
|
}
|
|
|
|
// Now we fail since we're not an empty port map but all ports are used
|
|
available_port = p2.GetNextAvailablePort();
|
|
ASSERT_THAT_EXPECTED(available_port, llvm::Failed());
|
|
}
|
|
|
|
TEST(PortMapTest, FreePort) {
|
|
GDBRemoteCommunicationServerPlatform::PortMap p(1, 4);
|
|
// Use up all the ports
|
|
for (uint16_t port = 1; port < 4; ++port) {
|
|
p.AssociatePortWithProcess(port, 1);
|
|
}
|
|
|
|
llvm::Expected<uint16_t> available_port = p.GetNextAvailablePort();
|
|
ASSERT_THAT_EXPECTED(available_port, llvm::Failed());
|
|
|
|
// Can't free a port that isn't in the map
|
|
ASSERT_FALSE(p.FreePort(0));
|
|
ASSERT_FALSE(p.FreePort(4));
|
|
|
|
// After freeing a port it becomes available
|
|
ASSERT_TRUE(p.FreePort(2));
|
|
available_port = p.GetNextAvailablePort();
|
|
ASSERT_THAT_EXPECTED(available_port, llvm::HasValue(2));
|
|
}
|
|
|
|
TEST(PortMapTest, FreePortForProcess) {
|
|
GDBRemoteCommunicationServerPlatform::PortMap p;
|
|
p.AllowPort(1);
|
|
p.AllowPort(2);
|
|
ASSERT_TRUE(p.AssociatePortWithProcess(1, 11));
|
|
ASSERT_TRUE(p.AssociatePortWithProcess(2, 22));
|
|
|
|
// All ports have been used
|
|
llvm::Expected<uint16_t> available_port = p.GetNextAvailablePort();
|
|
ASSERT_THAT_EXPECTED(available_port, llvm::Failed());
|
|
|
|
// Can't free a port for a process that doesn't have any
|
|
ASSERT_FALSE(p.FreePortForProcess(33));
|
|
|
|
// You can move a used port to a new pid
|
|
ASSERT_TRUE(p.AssociatePortWithProcess(1, 99));
|
|
|
|
ASSERT_TRUE(p.FreePortForProcess(22));
|
|
available_port = p.GetNextAvailablePort();
|
|
ASSERT_THAT_EXPECTED(available_port, llvm::Succeeded());
|
|
ASSERT_EQ(2, *available_port);
|
|
|
|
// proces 22 no longer has a port
|
|
ASSERT_FALSE(p.FreePortForProcess(22));
|
|
}
|
|
|
|
TEST(PortMapTest, AllowPort) {
|
|
GDBRemoteCommunicationServerPlatform::PortMap p;
|
|
|
|
// Allow port 1 and tie it to process 11
|
|
p.AllowPort(1);
|
|
ASSERT_TRUE(p.AssociatePortWithProcess(1, 11));
|
|
|
|
// Allowing it a second time shouldn't change existing mapping
|
|
p.AllowPort(1);
|
|
llvm::Expected<uint16_t> available_port = p.GetNextAvailablePort();
|
|
ASSERT_THAT_EXPECTED(available_port, llvm::Failed());
|
|
|
|
// A new port is marked as free when allowed
|
|
p.AllowPort(2);
|
|
available_port = p.GetNextAvailablePort();
|
|
ASSERT_THAT_EXPECTED(available_port, llvm::HasValue(2));
|
|
|
|
// 11 should still be tied to port 1
|
|
ASSERT_TRUE(p.FreePortForProcess(11));
|
|
}
|