//========- unittests/Support/Host.cpp - Host.cpp tests --------------========// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "llvm/Support/Host.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "gtest/gtest.h" #define ASSERT_NO_ERROR(x) \ if (std::error_code ASSERT_NO_ERROR_ec = x) { \ SmallString<128> MessageStorage; \ raw_svector_ostream Message(MessageStorage); \ Message << #x ": did not return errc::success.\n" \ << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ } else { \ } using namespace llvm; class HostTest : public testing::Test { Triple Host; protected: bool isSupportedArchAndOS() { // Initially this is only testing detection of the number of // physical cores, which is currently only supported/tested for // x86_64 Linux and Darwin. return (Host.getArch() == Triple::x86_64 && (Host.isOSDarwin() || Host.getOS() == Triple::Linux)); } HostTest() : Host(Triple::normalize(sys::getProcessTriple())) {} }; TEST_F(HostTest, NumPhysicalCores) { int Num = sys::getHostNumPhysicalCores(); if (isSupportedArchAndOS()) ASSERT_GT(Num, 0); else ASSERT_EQ(Num, -1); } TEST(getLinuxHostCPUName, ARM) { StringRef CortexA9ProcCpuinfo = R"( processor : 0 model name : ARMv7 Processor rev 10 (v7l) BogoMIPS : 1393.66 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x2 CPU part : 0xc09 CPU revision : 10 processor : 1 model name : ARMv7 Processor rev 10 (v7l) BogoMIPS : 1393.66 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x2 CPU part : 0xc09 CPU revision : 10 Hardware : Generic OMAP4 (Flattened Device Tree) Revision : 0000 Serial : 0000000000000000 )"; EXPECT_EQ(sys::detail::getHostCPUNameForARM(CortexA9ProcCpuinfo), "cortex-a9"); EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" "CPU part : 0xc0f"), "cortex-a15"); // Verify that both CPU implementer and CPU part are checked: EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n" "CPU part : 0xc0f"), "generic"); EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" "CPU part : 0x06f"), "krait"); } TEST(getLinuxHostCPUName, AArch64) { EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" "CPU part : 0xd03"), "cortex-a53"); // Verify that both CPU implementer and CPU part are checked: EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n" "CPU part : 0xd03"), "generic"); EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" "CPU part : 0x201"), "kryo"); EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" "CPU part : 0x800"), "cortex-a73"); EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" "CPU part : 0x801"), "cortex-a73"); EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" "CPU part : 0xc00"), "falkor"); EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" "CPU part : 0xc01"), "saphira"); // MSM8992/4 weirdness StringRef MSM8992ProcCpuInfo = R"( Processor : AArch64 Processor rev 3 (aarch64) processor : 0 processor : 1 processor : 2 processor : 3 processor : 4 processor : 5 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 CPU implementer : 0x41 CPU architecture: 8 CPU variant : 0x0 CPU part : 0xd03 CPU revision : 3 Hardware : Qualcomm Technologies, Inc MSM8992 )"; EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo), "cortex-a53"); // Exynos big.LITTLE weirdness const std::string ExynosProcCpuInfo = R"( processor : 0 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 CPU implementer : 0x41 CPU architecture: 8 CPU variant : 0x0 CPU part : 0xd03 processor : 1 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 CPU implementer : 0x53 CPU architecture: 8 )"; // Verify default for Exynos. EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + "CPU variant : 0xc\n" "CPU part : 0xafe"), "exynos-m1"); // Verify Exynos M1. EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + "CPU variant : 0x1\n" "CPU part : 0x001"), "exynos-m1"); // Verify Exynos M2. EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + "CPU variant : 0x4\n" "CPU part : 0x001"), "exynos-m2"); const std::string ThunderX2T99ProcCpuInfo = R"( processor : 0 BogoMIPS : 400.00 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics CPU implementer : 0x43 CPU architecture: 8 CPU variant : 0x1 CPU part : 0x0af )"; // Verify different versions of ThunderX2T99. EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + "CPU implementer : 0x42\n" "CPU part : 0x516"), "thunderx2t99"); EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + "CPU implementer : 0x42\n" "CPU part : 0x0516"), "thunderx2t99"); EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + "CPU implementer : 0x43\n" "CPU part : 0x516"), "thunderx2t99"); EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + "CPU implementer : 0x43\n" "CPU part : 0x0516"), "thunderx2t99"); EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + "CPU implementer : 0x42\n" "CPU part : 0xaf"), "thunderx2t99"); EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + "CPU implementer : 0x42\n" "CPU part : 0x0af"), "thunderx2t99"); EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + "CPU implementer : 0x43\n" "CPU part : 0xaf"), "thunderx2t99"); EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + "CPU implementer : 0x43\n" "CPU part : 0x0af"), "thunderx2t99"); // Verify ThunderXT88. const std::string ThunderXT88ProcCpuInfo = R"( processor : 0 BogoMIPS : 200.00 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 CPU implementer : 0x43 CPU architecture: 8 CPU variant : 0x1 CPU part : 0x0a1 )"; EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo + "CPU implementer : 0x43\n" "CPU part : 0x0a1"), "thunderxt88"); EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo + "CPU implementer : 0x43\n" "CPU part : 0xa1"), "thunderxt88"); // Verify HiSilicon processors. EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x48\n" "CPU part : 0xd01"), "tsv110"); } #if defined(__APPLE__) TEST_F(HostTest, getMacOSHostVersion) { using namespace llvm::sys; llvm::Triple HostTriple(getProcessTriple()); if (!HostTriple.isMacOSX()) return; SmallString<128> TestDirectory; ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory)); SmallString<128> OutputFile(TestDirectory); path::append(OutputFile, "out"); const char *SwVersPath = "/usr/bin/sw_vers"; StringRef argv[] = {SwVersPath, "-productVersion"}; StringRef OutputPath = OutputFile.str(); const Optional Redirects[] = {/*STDIN=*/None, /*STDOUT=*/OutputPath, /*STDERR=*/None}; int RetCode = ExecuteAndWait(SwVersPath, argv, /*env=*/llvm::None, Redirects); ASSERT_EQ(0, RetCode); int FD = 0; ASSERT_NO_ERROR(fs::openFileForRead(OutputPath, FD)); off_t Size = ::lseek(FD, 0, SEEK_END); ASSERT_NE(-1, Size); ::lseek(FD, 0, SEEK_SET); std::unique_ptr Buffer = llvm::make_unique(Size); ASSERT_EQ(::read(FD, Buffer.get(), Size), Size); ::close(FD); // Ensure that the two versions match. StringRef SystemVersion(Buffer.get(), Size); unsigned SystemMajor, SystemMinor, SystemMicro; ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersion)) .getMacOSXVersion(SystemMajor, SystemMinor, SystemMicro), true); unsigned HostMajor, HostMinor, HostMicro; ASSERT_EQ(HostTriple.getMacOSXVersion(HostMajor, HostMinor, HostMicro), true); // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin' // triples. ASSERT_EQ(std::tie(SystemMajor, SystemMinor), std::tie(HostMajor, HostMinor)); ASSERT_NO_ERROR(fs::remove(OutputPath)); ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } #endif