1 //========- unittests/Support/Host.cpp - Host.cpp tests --------------========// 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/Support/Host.h" 10 #include "llvm/Config/llvm-config.h" 11 #include "llvm/ADT/SmallVector.h" 12 #include "llvm/ADT/Triple.h" 13 #include "llvm/Support/FileSystem.h" 14 #include "llvm/Support/Path.h" 15 #include "llvm/Support/Program.h" 16 17 #include "gtest/gtest.h" 18 19 #define ASSERT_NO_ERROR(x) ASSERT_EQ(x, std::error_code()) 20 21 using namespace llvm; 22 23 class HostTest : public testing::Test { 24 Triple Host; 25 26 protected: 27 bool isSupportedArchAndOS() { 28 // Initially this is only testing detection of the number of 29 // physical cores, which is currently only supported/tested for 30 // x86_64 Linux and Darwin. 31 return (Host.getArch() == Triple::x86_64 && 32 (Host.isOSDarwin() || Host.getOS() == Triple::Linux)); 33 } 34 35 HostTest() : Host(Triple::normalize(sys::getProcessTriple())) {} 36 }; 37 38 TEST_F(HostTest, NumPhysicalCores) { 39 int Num = sys::getHostNumPhysicalCores(); 40 41 if (isSupportedArchAndOS()) 42 ASSERT_GT(Num, 0); 43 else 44 ASSERT_EQ(Num, -1); 45 } 46 47 TEST(getLinuxHostCPUName, ARM) { 48 StringRef CortexA9ProcCpuinfo = R"( 49 processor : 0 50 model name : ARMv7 Processor rev 10 (v7l) 51 BogoMIPS : 1393.66 52 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 53 CPU implementer : 0x41 54 CPU architecture: 7 55 CPU variant : 0x2 56 CPU part : 0xc09 57 CPU revision : 10 58 59 processor : 1 60 model name : ARMv7 Processor rev 10 (v7l) 61 BogoMIPS : 1393.66 62 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 63 CPU implementer : 0x41 64 CPU architecture: 7 65 CPU variant : 0x2 66 CPU part : 0xc09 67 CPU revision : 10 68 69 Hardware : Generic OMAP4 (Flattened Device Tree) 70 Revision : 0000 71 Serial : 0000000000000000 72 )"; 73 74 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CortexA9ProcCpuinfo), 75 "cortex-a9"); 76 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" 77 "CPU part : 0xc0f"), 78 "cortex-a15"); 79 // Verify that both CPU implementer and CPU part are checked: 80 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n" 81 "CPU part : 0xc0f"), 82 "generic"); 83 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 84 "CPU part : 0x06f"), 85 "krait"); 86 } 87 88 TEST(getLinuxHostCPUName, AArch64) { 89 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" 90 "CPU part : 0xd03"), 91 "cortex-a53"); 92 // Verify that both CPU implementer and CPU part are checked: 93 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n" 94 "CPU part : 0xd03"), 95 "generic"); 96 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 97 "CPU part : 0x201"), 98 "kryo"); 99 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 100 "CPU part : 0x800"), 101 "cortex-a73"); 102 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 103 "CPU part : 0x801"), 104 "cortex-a73"); 105 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 106 "CPU part : 0xc00"), 107 "falkor"); 108 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 109 "CPU part : 0xc01"), 110 "saphira"); 111 112 // MSM8992/4 weirdness 113 StringRef MSM8992ProcCpuInfo = R"( 114 Processor : AArch64 Processor rev 3 (aarch64) 115 processor : 0 116 processor : 1 117 processor : 2 118 processor : 3 119 processor : 4 120 processor : 5 121 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 122 CPU implementer : 0x41 123 CPU architecture: 8 124 CPU variant : 0x0 125 CPU part : 0xd03 126 CPU revision : 3 127 128 Hardware : Qualcomm Technologies, Inc MSM8992 129 )"; 130 131 EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo), 132 "cortex-a53"); 133 134 // Exynos big.LITTLE weirdness 135 const std::string ExynosProcCpuInfo = R"( 136 processor : 0 137 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 138 CPU implementer : 0x41 139 CPU architecture: 8 140 CPU variant : 0x0 141 CPU part : 0xd03 142 143 processor : 1 144 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 145 CPU implementer : 0x53 146 CPU architecture: 8 147 )"; 148 149 // Verify default for Exynos. 150 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + 151 "CPU variant : 0xc\n" 152 "CPU part : 0xafe"), 153 "exynos-m1"); 154 // Verify Exynos M1. 155 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + 156 "CPU variant : 0x1\n" 157 "CPU part : 0x001"), 158 "exynos-m1"); 159 // Verify Exynos M2. 160 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + 161 "CPU variant : 0x4\n" 162 "CPU part : 0x001"), 163 "exynos-m2"); 164 165 const std::string ThunderX2T99ProcCpuInfo = R"( 166 processor : 0 167 BogoMIPS : 400.00 168 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics 169 CPU implementer : 0x43 170 CPU architecture: 8 171 CPU variant : 0x1 172 CPU part : 0x0af 173 )"; 174 175 // Verify different versions of ThunderX2T99. 176 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 177 "CPU implementer : 0x42\n" 178 "CPU part : 0x516"), 179 "thunderx2t99"); 180 181 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 182 "CPU implementer : 0x42\n" 183 "CPU part : 0x0516"), 184 "thunderx2t99"); 185 186 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 187 "CPU implementer : 0x43\n" 188 "CPU part : 0x516"), 189 "thunderx2t99"); 190 191 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 192 "CPU implementer : 0x43\n" 193 "CPU part : 0x0516"), 194 "thunderx2t99"); 195 196 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 197 "CPU implementer : 0x42\n" 198 "CPU part : 0xaf"), 199 "thunderx2t99"); 200 201 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 202 "CPU implementer : 0x42\n" 203 "CPU part : 0x0af"), 204 "thunderx2t99"); 205 206 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 207 "CPU implementer : 0x43\n" 208 "CPU part : 0xaf"), 209 "thunderx2t99"); 210 211 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 212 "CPU implementer : 0x43\n" 213 "CPU part : 0x0af"), 214 "thunderx2t99"); 215 216 // Verify ThunderXT88. 217 const std::string ThunderXT88ProcCpuInfo = R"( 218 processor : 0 219 BogoMIPS : 200.00 220 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 221 CPU implementer : 0x43 222 CPU architecture: 8 223 CPU variant : 0x1 224 CPU part : 0x0a1 225 )"; 226 227 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo + 228 "CPU implementer : 0x43\n" 229 "CPU part : 0x0a1"), 230 "thunderxt88"); 231 232 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo + 233 "CPU implementer : 0x43\n" 234 "CPU part : 0xa1"), 235 "thunderxt88"); 236 237 // Verify HiSilicon processors. 238 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x48\n" 239 "CPU part : 0xd01"), 240 "tsv110"); 241 } 242 243 #if defined(__APPLE__) || defined(_AIX) 244 static bool runAndGetCommandOutput( 245 const char *ExePath, ArrayRef<llvm::StringRef> argv, 246 std::unique_ptr<char[]> &Buffer, off_t &Size) { 247 bool Success = false; 248 [ExePath, argv, &Buffer, &Size, &Success] { 249 using namespace llvm::sys; 250 SmallString<128> TestDirectory; 251 ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory)); 252 253 SmallString<128> OutputFile(TestDirectory); 254 path::append(OutputFile, "out"); 255 StringRef OutputPath = OutputFile.str(); 256 257 const Optional<StringRef> Redirects[] = { 258 /*STDIN=*/None, /*STDOUT=*/OutputPath, /*STDERR=*/None}; 259 int RetCode = ExecuteAndWait(ExePath, argv, /*env=*/llvm::None, Redirects); 260 ASSERT_EQ(0, RetCode); 261 262 int FD = 0; 263 ASSERT_NO_ERROR(fs::openFileForRead(OutputPath, FD)); 264 Size = ::lseek(FD, 0, SEEK_END); 265 ASSERT_NE(-1, Size); 266 ::lseek(FD, 0, SEEK_SET); 267 Buffer = llvm::make_unique<char[]>(Size); 268 ASSERT_EQ(::read(FD, Buffer.get(), Size), Size); 269 ::close(FD); 270 271 ASSERT_NO_ERROR(fs::remove(OutputPath)); 272 ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); 273 Success = true; 274 }(); 275 return Success; 276 } 277 278 TEST_F(HostTest, DummyRunAndGetCommandOutputUse) { 279 // Suppress defined-but-not-used warnings when the tests using the helper are 280 // disabled. 281 (void) runAndGetCommandOutput; 282 } 283 #endif 284 285 #if defined(__APPLE__) 286 TEST_F(HostTest, getMacOSHostVersion) { 287 using namespace llvm::sys; 288 llvm::Triple HostTriple(getProcessTriple()); 289 if (!HostTriple.isMacOSX()) 290 return; 291 292 const char *SwVersPath = "/usr/bin/sw_vers"; 293 StringRef argv[] = {SwVersPath, "-productVersion"}; 294 std::unique_ptr<char[]> Buffer; 295 off_t Size; 296 ASSERT_EQ(runAndGetCommandOutput(SwVersPath, argv, Buffer, Size), true); 297 StringRef SystemVersion(Buffer.get(), Size); 298 299 // Ensure that the two versions match. 300 unsigned SystemMajor, SystemMinor, SystemMicro; 301 ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersion)) 302 .getMacOSXVersion(SystemMajor, SystemMinor, SystemMicro), 303 true); 304 unsigned HostMajor, HostMinor, HostMicro; 305 ASSERT_EQ(HostTriple.getMacOSXVersion(HostMajor, HostMinor, HostMicro), true); 306 307 // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin' 308 // triples. 309 ASSERT_EQ(std::tie(SystemMajor, SystemMinor), std::tie(HostMajor, HostMinor)); 310 } 311 #endif 312 313 #if defined(_AIX) 314 TEST_F(HostTest, AIXVersionDetect) { 315 using namespace llvm::sys; 316 317 llvm::Triple HostTriple(getProcessTriple()); 318 ASSERT_EQ(HostTriple.getOS(), Triple::AIX); 319 320 llvm::Triple ConfiguredHostTriple(LLVM_HOST_TRIPLE); 321 ASSERT_EQ(ConfiguredHostTriple.getOS(), Triple::AIX); 322 323 const char *ExePath = "/usr/bin/oslevel"; 324 StringRef argv[] = {ExePath}; 325 std::unique_ptr<char[]> Buffer; 326 off_t Size; 327 ASSERT_EQ(runAndGetCommandOutput(ExePath, argv, Buffer, Size), true); 328 StringRef SystemVersion(Buffer.get(), Size); 329 330 unsigned SystemMajor, SystemMinor, SystemMicro; 331 llvm::Triple((Twine("powerpc-ibm-aix") + SystemVersion)) 332 .getOSVersion(SystemMajor, SystemMinor, SystemMicro); 333 334 // Ensure that the host triple version (major) and release (minor) numbers, 335 // unless explicitly configured, match with those of the current system. 336 if (!ConfiguredHostTriple.getOSMajorVersion()) { 337 unsigned HostMajor, HostMinor, HostMicro; 338 HostTriple.getOSVersion(HostMajor, HostMinor, HostMicro); 339 ASSERT_EQ(std::tie(SystemMajor, SystemMinor), 340 std::tie(HostMajor, HostMinor)); 341 } 342 343 llvm::Triple TargetTriple(getDefaultTargetTriple()); 344 if (TargetTriple.getOS() != Triple::AIX) 345 return; 346 347 // Ensure that the target triple version (major) and release (minor) numbers 348 // match with those of the current system. 349 llvm::Triple ConfiguredTargetTriple(LLVM_DEFAULT_TARGET_TRIPLE); 350 if (ConfiguredTargetTriple.getOSMajorVersion()) 351 return; // The version was configured explicitly; skip. 352 353 unsigned TargetMajor, TargetMinor, TargetMicro; 354 TargetTriple.getOSVersion(TargetMajor, TargetMinor, TargetMicro); 355 ASSERT_EQ(std::tie(SystemMajor, SystemMinor), 356 std::tie(TargetMajor, TargetMinor)); 357 } 358 #endif 359