1 //===-- PlatformTest.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 "gtest/gtest.h"
10 
11 #include "Plugins/Platform/POSIX/PlatformPOSIX.h"
12 #include "TestingSupport/SubsystemRAII.h"
13 #include "lldb/Core/PluginManager.h"
14 #include "lldb/Host/FileSystem.h"
15 #include "lldb/Host/HostInfo.h"
16 #include "lldb/Target/Platform.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 class TestPlatform : public PlatformPOSIX {
22 public:
23   TestPlatform() : PlatformPOSIX(false) {}
24   using Platform::Clear;
25 };
26 
27 class PlatformArm : public TestPlatform {
28 public:
29   PlatformArm() = default;
30 
31   std::vector<ArchSpec>
32   GetSupportedArchitectures(const ArchSpec &process_host_arch) override {
33     return {ArchSpec("arm64-apple-ps4")};
34   }
35 
36   llvm::StringRef GetPluginName() override { return "arm"; }
37   llvm::StringRef GetDescription() override { return "arm"; }
38 };
39 
40 class PlatformIntel : public TestPlatform {
41 public:
42   PlatformIntel() = default;
43 
44   std::vector<ArchSpec>
45   GetSupportedArchitectures(const ArchSpec &process_host_arch) override {
46     return {ArchSpec("x86_64-apple-ps4")};
47   }
48 
49   llvm::StringRef GetPluginName() override { return "intel"; }
50   llvm::StringRef GetDescription() override { return "intel"; }
51 };
52 
53 class PlatformThumb : public TestPlatform {
54 public:
55   static void Initialize() {
56     PluginManager::RegisterPlugin("thumb", "thumb",
57                                   PlatformThumb::CreateInstance);
58   }
59   static void Terminate() {
60     PluginManager::UnregisterPlugin(PlatformThumb::CreateInstance);
61   }
62 
63   static PlatformSP CreateInstance(bool force, const ArchSpec *arch) {
64     return std::make_shared<PlatformThumb>();
65   }
66 
67   std::vector<ArchSpec>
68   GetSupportedArchitectures(const ArchSpec &process_host_arch) override {
69     return {ArchSpec("thumbv7-apple-ps4"), ArchSpec("thumbv7f-apple-ps4")};
70   }
71 
72   llvm::StringRef GetPluginName() override { return "thumb"; }
73   llvm::StringRef GetDescription() override { return "thumb"; }
74 };
75 
76 class PlatformTest : public ::testing::Test {
77   SubsystemRAII<FileSystem, HostInfo> subsystems;
78   void SetUp() override { TestPlatform::Clear(); }
79 };
80 
81 TEST_F(PlatformTest, GetPlatformForArchitecturesHost) {
82   const PlatformSP host_platform_sp = std::make_shared<PlatformArm>();
83   Platform::SetHostPlatform(host_platform_sp);
84   ASSERT_EQ(Platform::GetHostPlatform(), host_platform_sp);
85 
86   const std::vector<ArchSpec> archs = {ArchSpec("arm64-apple-ps4"),
87                                        ArchSpec("arm64e-apple-ps4")};
88   std::vector<PlatformSP> candidates;
89 
90   // The host platform matches all architectures.
91   PlatformSP platform_sp =
92       Platform::GetPlatformForArchitectures(archs, {}, {}, candidates);
93   ASSERT_TRUE(platform_sp);
94   EXPECT_EQ(platform_sp, host_platform_sp);
95 }
96 
97 TEST_F(PlatformTest, GetPlatformForArchitecturesSelected) {
98   const PlatformSP host_platform_sp = std::make_shared<PlatformIntel>();
99   Platform::SetHostPlatform(host_platform_sp);
100   ASSERT_EQ(Platform::GetHostPlatform(), host_platform_sp);
101 
102   const std::vector<ArchSpec> archs = {ArchSpec("arm64-apple-ps4"),
103                                        ArchSpec("arm64e-apple-ps4")};
104   std::vector<PlatformSP> candidates;
105 
106   // The host platform matches no architectures. No selected platform.
107   PlatformSP platform_sp =
108       Platform::GetPlatformForArchitectures(archs, {}, {}, candidates);
109   ASSERT_FALSE(platform_sp);
110 
111   // The selected platform matches all architectures.
112   const PlatformSP selected_platform_sp = std::make_shared<PlatformArm>();
113   platform_sp = Platform::GetPlatformForArchitectures(
114       archs, {}, selected_platform_sp, candidates);
115   ASSERT_TRUE(platform_sp);
116   EXPECT_EQ(platform_sp, selected_platform_sp);
117 }
118 
119 TEST_F(PlatformTest, GetPlatformForArchitecturesSelectedOverHost) {
120   const PlatformSP host_platform_sp = std::make_shared<PlatformIntel>();
121   Platform::SetHostPlatform(host_platform_sp);
122   ASSERT_EQ(Platform::GetHostPlatform(), host_platform_sp);
123 
124   const std::vector<ArchSpec> archs = {ArchSpec("arm64-apple-ps4"),
125                                        ArchSpec("x86_64-apple-ps4")};
126   std::vector<PlatformSP> candidates;
127 
128   // The host platform matches one architecture. No selected platform.
129   PlatformSP platform_sp =
130       Platform::GetPlatformForArchitectures(archs, {}, {}, candidates);
131   ASSERT_TRUE(platform_sp);
132   EXPECT_EQ(platform_sp, host_platform_sp);
133 
134   // The selected and host platform each match one architecture.
135   // The selected platform is preferred.
136   const PlatformSP selected_platform_sp = std::make_shared<PlatformArm>();
137   platform_sp = Platform::GetPlatformForArchitectures(
138       archs, {}, selected_platform_sp, candidates);
139   ASSERT_TRUE(platform_sp);
140   EXPECT_EQ(platform_sp, selected_platform_sp);
141 }
142 
143 TEST_F(PlatformTest, GetPlatformForArchitecturesCandidates) {
144   PlatformThumb::Initialize();
145 
146   const PlatformSP host_platform_sp = std::make_shared<PlatformIntel>();
147   Platform::SetHostPlatform(host_platform_sp);
148   ASSERT_EQ(Platform::GetHostPlatform(), host_platform_sp);
149   const PlatformSP selected_platform_sp = std::make_shared<PlatformArm>();
150 
151   const std::vector<ArchSpec> archs = {ArchSpec("thumbv7-apple-ps4"),
152                                        ArchSpec("thumbv7f-apple-ps4")};
153   std::vector<PlatformSP> candidates;
154 
155   // The host platform matches one architecture. No selected platform.
156   PlatformSP platform_sp = Platform::GetPlatformForArchitectures(
157       archs, {}, selected_platform_sp, candidates);
158   ASSERT_TRUE(platform_sp);
159   EXPECT_EQ(platform_sp->GetName(), "thumb");
160 
161   PlatformThumb::Terminate();
162 }
163