Initial commit

This commit is contained in:
2025-12-08 12:12:07 +07:00
commit 0b2e8c4c16
1238 changed files with 160253 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
#
# libraries for tests
#
include_directories(../include)
add_definitions(-DCPU_FEATURES_TEST)
##------------------------------------------------------------------------------
add_library(string_view ../src/string_view.c)
##------------------------------------------------------------------------------
add_library(filesystem_for_testing filesystem_for_testing.cc)
target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM)
##------------------------------------------------------------------------------
add_library(hwcaps_for_testing hwcaps_for_testing.cc)
target_link_libraries(hwcaps_for_testing filesystem_for_testing)
##------------------------------------------------------------------------------
add_library(stack_line_reader ../src/stack_line_reader.c)
target_compile_definitions(stack_line_reader PUBLIC STACK_LINE_READER_BUFFER_SIZE=1024)
target_link_libraries(stack_line_reader string_view)
##------------------------------------------------------------------------------
add_library(stack_line_reader_for_test ../src/stack_line_reader.c)
target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16)
target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing)
##------------------------------------------------------------------------------
add_library(all_libraries ../src/hwcaps.c ../src/stack_line_reader.c)
target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view)
#
# tests
#
link_libraries(gtest gmock_main)
## bit_utils_test
add_executable(bit_utils_test bit_utils_test.cc)
target_link_libraries(bit_utils_test)
add_test(NAME bit_utils_test COMMAND bit_utils_test)
##------------------------------------------------------------------------------
## string_view_test
add_executable(string_view_test string_view_test.cc ../src/string_view.c)
target_link_libraries(string_view_test string_view)
add_test(NAME string_view_test COMMAND string_view_test)
##------------------------------------------------------------------------------
## stack_line_reader_test
add_executable(stack_line_reader_test stack_line_reader_test.cc)
target_link_libraries(stack_line_reader_test stack_line_reader_for_test)
add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test)
##------------------------------------------------------------------------------
## cpuinfo_x86_test
if(PROCESSOR_IS_X86)
add_executable(cpuinfo_x86_test
cpuinfo_x86_test.cc
../src/impl_x86_freebsd.c
../src/impl_x86_linux_or_android.c
../src/impl_x86_macos.c
../src/impl_x86_windows.c
)
target_compile_definitions(cpuinfo_x86_test PUBLIC CPU_FEATURES_MOCK_CPUID_X86)
if(APPLE)
target_compile_definitions(cpuinfo_x86_test PRIVATE HAVE_SYSCTLBYNAME)
endif()
target_link_libraries(cpuinfo_x86_test all_libraries)
add_test(NAME cpuinfo_x86_test COMMAND cpuinfo_x86_test)
endif()
##------------------------------------------------------------------------------
## cpuinfo_arm_test
if(PROCESSOR_IS_ARM)
add_executable(cpuinfo_arm_test cpuinfo_arm_test.cc ../src/impl_arm_linux_or_android.c)
target_link_libraries(cpuinfo_arm_test all_libraries)
add_test(NAME cpuinfo_arm_test COMMAND cpuinfo_arm_test)
endif()
##------------------------------------------------------------------------------
## cpuinfo_aarch64_test
if(PROCESSOR_IS_AARCH64)
add_executable(cpuinfo_aarch64_test
cpuinfo_aarch64_test.cc
../src/impl_aarch64_linux_or_android.c
../src/impl_aarch64_macos_or_iphone.c
../src/impl_aarch64_windows.c)
if(APPLE)
target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_SYSCTL_AARCH64)
target_compile_definitions(cpuinfo_aarch64_test PRIVATE HAVE_SYSCTLBYNAME)
endif()
target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_CPUID_AARCH64)
target_link_libraries(cpuinfo_aarch64_test all_libraries)
add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test)
endif()
##------------------------------------------------------------------------------
## cpuinfo_mips_test
if(PROCESSOR_IS_MIPS)
add_executable(cpuinfo_mips_test cpuinfo_mips_test.cc ../src/impl_mips_linux_or_android.c)
target_link_libraries(cpuinfo_mips_test all_libraries)
add_test(NAME cpuinfo_mips_test COMMAND cpuinfo_mips_test)
endif()
##------------------------------------------------------------------------------
## cpuinfo_ppc_test
if(PROCESSOR_IS_POWER)
add_executable(cpuinfo_ppc_test cpuinfo_ppc_test.cc ../src/impl_ppc_linux.c)
target_link_libraries(cpuinfo_ppc_test all_libraries)
add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test)
endif()
##------------------------------------------------------------------------------
## cpuinfo_s390x_test
if(PROCESSOR_IS_S390X)
add_executable(cpuinfo_s390x_test cpuinfo_s390x_test.cc ../src/impl_s390x_linux.c)
target_link_libraries(cpuinfo_s390x_test all_libraries)
add_test(NAME cpuinfo_s390x_test COMMAND cpuinfo_s390x_test)
endif()
##------------------------------------------------------------------------------
## cpuinfo_riscv_test
if(PROCESSOR_IS_RISCV)
add_executable(cpuinfo_riscv_test cpuinfo_riscv_test.cc ../src/impl_riscv_linux.c)
target_link_libraries(cpuinfo_riscv_test all_libraries)
add_test(NAME cpuinfo_riscv_test COMMAND cpuinfo_riscv_test)
endif()

View File

@@ -0,0 +1,53 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/bit_utils.h"
#include "gtest/gtest.h"
namespace cpu_features {
namespace {
TEST(UtilsTest, IsBitSet) {
for (size_t bit_set = 0; bit_set < 32; ++bit_set) {
const uint32_t value = 1UL << bit_set;
for (uint32_t i = 0; i < 32; ++i) {
EXPECT_EQ(IsBitSet(value, i), i == bit_set);
}
}
// testing 0, all bits should be 0.
for (uint32_t i = 0; i < 32; ++i) {
EXPECT_FALSE(IsBitSet(0, i));
}
// testing ~0, all bits should be 1.
for (uint32_t i = 0; i < 32; ++i) {
EXPECT_TRUE(IsBitSet(-1, i));
}
}
TEST(UtilsTest, ExtractBitRange) {
// Extracting all bits gives the same number.
EXPECT_EQ(ExtractBitRange(123, 31, 0), 123);
// Extracting 1 bit gives parity.
EXPECT_EQ(ExtractBitRange(123, 0, 0), 1);
EXPECT_EQ(ExtractBitRange(122, 0, 0), 0);
EXPECT_EQ(ExtractBitRange(0xF0, 7, 4), 0xF);
EXPECT_EQ(ExtractBitRange(0x42 << 2, 10, 2), 0x42);
}
} // namespace
} // namespace cpu_features

View File

@@ -0,0 +1,396 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_aarch64.h"
#include <set>
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
#if defined(CPU_FEATURES_OS_WINDOWS)
#include "internal/windows_utils.h"
#endif // CPU_FEATURES_OS_WINDOWS
namespace cpu_features {
class FakeCpuAarch64 {
public:
#if defined(CPU_FEATURES_OS_WINDOWS)
bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
return windows_isprocessorfeaturepresent_.count(dwProcessorFeature);
}
void SetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
windows_isprocessorfeaturepresent_.insert(dwProcessorFeature);
}
WORD GetWindowsNativeSystemInfoProcessorRevision() const {
return processor_revision_;
}
void SetWindowsNativeSystemInfoProcessorRevision(WORD wProcessorRevision) {
processor_revision_ = wProcessorRevision;
}
private:
std::set<DWORD> windows_isprocessorfeaturepresent_;
WORD processor_revision_{};
#endif // CPU_FEATURES_OS_WINDOWS
};
static FakeCpuAarch64* g_fake_cpu_instance = nullptr;
static FakeCpuAarch64& cpu() {
assert(g_fake_cpu_instance != nullptr);
return *g_fake_cpu_instance;
}
#if defined(CPU_FEATURES_OS_WINDOWS)
extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD dwProcessorFeature) {
return cpu().GetWindowsIsProcessorFeaturePresent(dwProcessorFeature);
}
extern "C" WORD GetWindowsNativeSystemInfoProcessorRevision() {
return cpu().GetWindowsNativeSystemInfoProcessorRevision();
}
#endif // CPU_FEATURES_OS_WINDOWS
namespace {
class CpuidAarch64Test : public ::testing::Test {
protected:
void SetUp() override {
assert(g_fake_cpu_instance == nullptr);
g_fake_cpu_instance = new FakeCpuAarch64();
}
void TearDown() override {
delete g_fake_cpu_instance;
g_fake_cpu_instance = nullptr;
}
};
TEST(CpuinfoAarch64Test, Aarch64FeaturesEnum) {
const char* last_name = GetAarch64FeaturesEnumName(AARCH64_LAST_);
EXPECT_STREQ(last_name, "unknown_feature");
for (int i = static_cast<int>(AARCH64_FP);
i != static_cast<int>(AARCH64_LAST_); ++i) {
const auto feature = static_cast<Aarch64FeaturesEnum>(i);
const char* name = GetAarch64FeaturesEnumName(feature);
ASSERT_FALSE(name == nullptr);
EXPECT_STRNE(name, "");
EXPECT_STRNE(name, last_name);
}
}
#if defined(CPU_FEATURES_OS_LINUX)
void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
#if defined(CPU_FEATURES_OS_MACOS)
class FakeCpu {
public:
bool GetDarwinSysCtlByName(std::string name) const {
return darwin_sysctlbyname_.count(name);
}
int GetDarwinSysCtlByNameValue(std::string name) const {
std::map<std::string, int>::const_iterator iter = darwin_sysctlbynamevalue_.find(name);
if (iter != std::end(darwin_sysctlbynamevalue_)) {
return iter->second;
}
return 0;
}
void SetDarwinSysCtlByName(std::string name) {
darwin_sysctlbyname_.insert(name);
}
void SetDarwinSysCtlByNameValue(std::string name, int value) {
darwin_sysctlbynamevalue_[name] = value;
}
private:
std::set<std::string> darwin_sysctlbyname_;
std::map<std::string, int> darwin_sysctlbynamevalue_;
};
static FakeCpu* g_fake_cpu_instance = nullptr;
static FakeCpu& cpu() {
assert(g_fake_cpu_instance != nullptr);
return *g_fake_cpu_instance;
}
extern "C" bool GetDarwinSysCtlByName(const char* name) {
return cpu().GetDarwinSysCtlByName(name);
}
extern "C" int GetDarwinSysCtlByNameValue(const char *name) {
return cpu().GetDarwinSysCtlByNameValue(name);
}
class CpuinfoAarch64Test : public ::testing::Test {
protected:
void SetUp() override {
assert(g_fake_cpu_instance == nullptr);
g_fake_cpu_instance = new FakeCpu();
}
void TearDown() override {
delete g_fake_cpu_instance;
g_fake_cpu_instance = nullptr;
}
};
TEST_F(CpuinfoAarch64Test, FromDarwinSysctlFromName) {
cpu().SetDarwinSysCtlByName("hw.optional.floatingpoint");
cpu().SetDarwinSysCtlByName("hw.optional.neon");
cpu().SetDarwinSysCtlByName("hw.optional.neon_hpfp");
cpu().SetDarwinSysCtlByName("hw.optional.neon_fp16");
cpu().SetDarwinSysCtlByName("hw.optional.armv8_1_atomics");
cpu().SetDarwinSysCtlByName("hw.optional.armv8_crc32");
cpu().SetDarwinSysCtlByName("hw.optional.armv8_2_fhm");
cpu().SetDarwinSysCtlByName("hw.optional.armv8_2_sha512");
cpu().SetDarwinSysCtlByName("hw.optional.armv8_2_sha3");
cpu().SetDarwinSysCtlByName("hw.optional.amx_version");
cpu().SetDarwinSysCtlByName("hw.optional.ucnormal_mem");
cpu().SetDarwinSysCtlByName("hw.optional.arm64");
cpu().SetDarwinSysCtlByNameValue("hw.cputype", 16777228);
cpu().SetDarwinSysCtlByNameValue("hw.cpusubtype", 2);
cpu().SetDarwinSysCtlByNameValue("hw.cpu64bit", 1);
cpu().SetDarwinSysCtlByNameValue("hw.cpufamily", 458787763);
cpu().SetDarwinSysCtlByNameValue("hw.cpusubfamily", 2);
const auto info = GetAarch64Info();
EXPECT_EQ(info.implementer, 0x100000C);
EXPECT_EQ(info.variant, 2);
EXPECT_EQ(info.part, 0x1B588BB3);
EXPECT_EQ(info.revision, 2);
EXPECT_TRUE(info.features.fp);
EXPECT_FALSE(info.features.asimd);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_FALSE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_TRUE(info.features.crc32);
EXPECT_TRUE(info.features.atomics);
EXPECT_TRUE(info.features.fphp);
EXPECT_FALSE(info.features.asimdhp);
EXPECT_FALSE(info.features.cpuid);
EXPECT_FALSE(info.features.asimdrdm);
EXPECT_FALSE(info.features.jscvt);
EXPECT_FALSE(info.features.fcma);
EXPECT_FALSE(info.features.lrcpc);
EXPECT_FALSE(info.features.dcpop);
EXPECT_TRUE(info.features.sha3);
EXPECT_FALSE(info.features.sm3);
EXPECT_FALSE(info.features.sm4);
EXPECT_FALSE(info.features.asimddp);
EXPECT_TRUE(info.features.sha512);
EXPECT_FALSE(info.features.sve);
EXPECT_TRUE(info.features.asimdfhm);
EXPECT_FALSE(info.features.dit);
EXPECT_FALSE(info.features.uscat);
EXPECT_FALSE(info.features.ilrcpc);
EXPECT_FALSE(info.features.flagm);
EXPECT_FALSE(info.features.ssbs);
EXPECT_FALSE(info.features.sb);
EXPECT_FALSE(info.features.paca);
EXPECT_FALSE(info.features.pacg);
}
#else
TEST(CpuinfoAarch64Test, FromHardwareCap) {
ResetHwcaps();
SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetAarch64Info();
EXPECT_TRUE(info.features.fp);
EXPECT_FALSE(info.features.asimd);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_TRUE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
EXPECT_FALSE(info.features.atomics);
EXPECT_FALSE(info.features.fphp);
EXPECT_FALSE(info.features.asimdhp);
EXPECT_FALSE(info.features.cpuid);
EXPECT_FALSE(info.features.asimdrdm);
EXPECT_FALSE(info.features.jscvt);
EXPECT_FALSE(info.features.fcma);
EXPECT_FALSE(info.features.lrcpc);
EXPECT_FALSE(info.features.dcpop);
EXPECT_FALSE(info.features.sha3);
EXPECT_FALSE(info.features.sm3);
EXPECT_FALSE(info.features.sm4);
EXPECT_FALSE(info.features.asimddp);
EXPECT_FALSE(info.features.sha512);
EXPECT_FALSE(info.features.sve);
EXPECT_FALSE(info.features.asimdfhm);
EXPECT_FALSE(info.features.dit);
EXPECT_FALSE(info.features.uscat);
EXPECT_FALSE(info.features.ilrcpc);
EXPECT_FALSE(info.features.flagm);
EXPECT_FALSE(info.features.ssbs);
EXPECT_FALSE(info.features.sb);
EXPECT_FALSE(info.features.paca);
EXPECT_FALSE(info.features.pacg);
}
TEST(CpuinfoAarch64Test, FromHardwareCap2) {
ResetHwcaps();
SetHardwareCapabilities(AARCH64_HWCAP_FP,
AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetAarch64Info();
EXPECT_TRUE(info.features.fp);
EXPECT_TRUE(info.features.sve2);
EXPECT_TRUE(info.features.bti);
EXPECT_FALSE(info.features.dcpodp);
EXPECT_FALSE(info.features.sveaes);
EXPECT_FALSE(info.features.svepmull);
EXPECT_FALSE(info.features.svebitperm);
EXPECT_FALSE(info.features.svesha3);
EXPECT_FALSE(info.features.svesm4);
EXPECT_FALSE(info.features.flagm2);
EXPECT_FALSE(info.features.frint);
EXPECT_FALSE(info.features.svei8mm);
EXPECT_FALSE(info.features.svef32mm);
EXPECT_FALSE(info.features.svef64mm);
EXPECT_FALSE(info.features.svebf16);
EXPECT_FALSE(info.features.i8mm);
EXPECT_FALSE(info.features.bf16);
EXPECT_FALSE(info.features.dgh);
EXPECT_FALSE(info.features.rng);
}
#endif // CPU_FEATURES_OS_MACOS
TEST(CpuinfoAarch64Test, ARMCortexA53) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(Processor : AArch64 Processor rev 3 (aarch64)
processor : 0
processor : 1
processor : 2
processor : 3
processor : 4
processor : 5
processor : 6
processor : 7
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: AArch64
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 3)");
const auto info = GetAarch64Info();
EXPECT_EQ(info.implementer, 0x41);
EXPECT_EQ(info.variant, 0x0);
EXPECT_EQ(info.part, 0xd03);
EXPECT_EQ(info.revision, 3);
EXPECT_TRUE(info.features.fp);
EXPECT_TRUE(info.features.asimd);
EXPECT_TRUE(info.features.evtstrm);
EXPECT_TRUE(info.features.aes);
EXPECT_TRUE(info.features.pmull);
EXPECT_TRUE(info.features.sha1);
EXPECT_TRUE(info.features.sha2);
EXPECT_TRUE(info.features.crc32);
EXPECT_FALSE(info.features.atomics);
EXPECT_FALSE(info.features.fphp);
EXPECT_FALSE(info.features.asimdhp);
EXPECT_FALSE(info.features.cpuid);
EXPECT_FALSE(info.features.asimdrdm);
EXPECT_FALSE(info.features.jscvt);
EXPECT_FALSE(info.features.fcma);
EXPECT_FALSE(info.features.lrcpc);
EXPECT_FALSE(info.features.dcpop);
EXPECT_FALSE(info.features.sha3);
EXPECT_FALSE(info.features.sm3);
EXPECT_FALSE(info.features.sm4);
EXPECT_FALSE(info.features.asimddp);
EXPECT_FALSE(info.features.sha512);
EXPECT_FALSE(info.features.sve);
EXPECT_FALSE(info.features.asimdfhm);
EXPECT_FALSE(info.features.dit);
EXPECT_FALSE(info.features.uscat);
EXPECT_FALSE(info.features.ilrcpc);
EXPECT_FALSE(info.features.flagm);
EXPECT_FALSE(info.features.ssbs);
EXPECT_FALSE(info.features.sb);
EXPECT_FALSE(info.features.paca);
EXPECT_FALSE(info.features.pacg);
EXPECT_FALSE(info.features.dcpodp);
EXPECT_FALSE(info.features.sve2);
EXPECT_FALSE(info.features.sveaes);
EXPECT_FALSE(info.features.svepmull);
EXPECT_FALSE(info.features.svebitperm);
EXPECT_FALSE(info.features.svesha3);
EXPECT_FALSE(info.features.svesm4);
EXPECT_FALSE(info.features.flagm2);
EXPECT_FALSE(info.features.frint);
EXPECT_FALSE(info.features.svei8mm);
EXPECT_FALSE(info.features.svef32mm);
EXPECT_FALSE(info.features.svef64mm);
EXPECT_FALSE(info.features.svebf16);
EXPECT_FALSE(info.features.i8mm);
EXPECT_FALSE(info.features.bf16);
EXPECT_FALSE(info.features.dgh);
EXPECT_FALSE(info.features.rng);
EXPECT_FALSE(info.features.bti);
EXPECT_FALSE(info.features.mte);
EXPECT_FALSE(info.features.ecv);
EXPECT_FALSE(info.features.afp);
EXPECT_FALSE(info.features.rpres);
}
#endif // CPU_FEATURES_OS_LINUX
#if defined(CPU_FEATURES_OS_WINDOWS)
TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) {
cpu().SetWindowsNativeSystemInfoProcessorRevision(0x03);
cpu().SetWindowsIsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE);
cpu().SetWindowsIsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE);
cpu().SetWindowsIsProcessorFeaturePresent(
PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE);
const auto info = GetAarch64Info();
EXPECT_EQ(info.revision, 0x03);
EXPECT_TRUE(info.features.fp);
EXPECT_TRUE(info.features.asimd);
EXPECT_TRUE(info.features.crc32);
EXPECT_FALSE(info.features.aes);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.atomics);
EXPECT_FALSE(info.features.asimddp);
EXPECT_FALSE(info.features.jscvt);
EXPECT_FALSE(info.features.lrcpc);
}
#endif // CPU_FEATURES_OS_WINDOWS
} // namespace
} // namespace cpu_features

View File

@@ -0,0 +1,384 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_arm.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
namespace cpu_features {
namespace {
TEST(CpuinfoArmTest, ArmFeaturesEnum) {
const char *last_name = GetArmFeaturesEnumName(ARM_LAST_);
EXPECT_STREQ(last_name, "unknown_feature");
for (int i = static_cast<int>(ARM_SWP); i != static_cast<int>(ARM_LAST_); ++i) {
const auto feature = static_cast<ArmFeaturesEnum>(i);
const char *name = GetArmFeaturesEnumName(feature);
ASSERT_FALSE(name == nullptr);
EXPECT_STRNE(name, "");
EXPECT_STRNE(name, last_name);
}
}
TEST(CpuinfoArmTest, FromHardwareCap) {
ResetHwcaps();
SetHardwareCapabilities(ARM_HWCAP_NEON, ARM_HWCAP2_AES | ARM_HWCAP2_CRC32);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.vfp); // triggered by vfpv3
EXPECT_TRUE(info.features.vfpv3); // triggered by neon
EXPECT_TRUE(info.features.neon);
EXPECT_TRUE(info.features.aes);
EXPECT_TRUE(info.features.crc32);
EXPECT_FALSE(info.features.vfpv4);
EXPECT_FALSE(info.features.iwmmxt);
EXPECT_FALSE(info.features.crunch);
EXPECT_FALSE(info.features.thumbee);
EXPECT_FALSE(info.features.vfpv3d16);
EXPECT_FALSE(info.features.idiva);
EXPECT_FALSE(info.features.idivt);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
// check some random features with EnumValue():
EXPECT_TRUE(GetArmFeaturesEnumValue(&info.features, ARM_VFP));
EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, ARM_VFPV4));
// out of bound EnumValue() check
EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, (ArmFeaturesEnum)~0x0));
}
TEST(CpuinfoArmTest, ODroidFromCpuInfo) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor : 0
model name : ARMv7 Processor rev 3 (v71)
BogoMIPS : 120.00
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc0f
CPU revision : 3)");
const auto info = GetArmInfo();
EXPECT_EQ(info.implementer, 0x41);
EXPECT_EQ(info.variant, 0x2);
EXPECT_EQ(info.part, 0xc0f);
EXPECT_EQ(info.revision, 3);
EXPECT_EQ(info.architecture, 7);
EXPECT_FALSE(info.features.swp);
EXPECT_TRUE(info.features.half);
EXPECT_TRUE(info.features.thumb);
EXPECT_FALSE(info.features._26bit);
EXPECT_TRUE(info.features.fastmult);
EXPECT_FALSE(info.features.fpa);
EXPECT_TRUE(info.features.vfp);
EXPECT_TRUE(info.features.edsp);
EXPECT_FALSE(info.features.java);
EXPECT_FALSE(info.features.iwmmxt);
EXPECT_FALSE(info.features.crunch);
EXPECT_FALSE(info.features.thumbee);
EXPECT_TRUE(info.features.neon);
EXPECT_TRUE(info.features.vfpv3);
EXPECT_FALSE(info.features.vfpv3d16);
EXPECT_TRUE(info.features.tls);
EXPECT_TRUE(info.features.vfpv4);
EXPECT_TRUE(info.features.idiva);
EXPECT_TRUE(info.features.idivt);
EXPECT_TRUE(info.features.vfpd32);
EXPECT_TRUE(info.features.lpae);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_FALSE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
}
// Linux test-case
TEST(CpuinfoArmTest, RaspberryPiZeroFromCpuInfo) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor : 0
model name : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS : 697.95
Features : half thumb fastmult vfp edsp java tls
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xb76
CPU revision : 7
Hardware : BCM2835
Revision : 9000c1
Serial : 000000006cd946f3)");
const auto info = GetArmInfo();
EXPECT_EQ(info.implementer, 0x41);
EXPECT_EQ(info.variant, 0x0);
EXPECT_EQ(info.part, 0xb76);
EXPECT_EQ(info.revision, 7);
EXPECT_EQ(info.architecture, 6);
EXPECT_FALSE(info.features.swp);
EXPECT_TRUE(info.features.half);
EXPECT_TRUE(info.features.thumb);
EXPECT_FALSE(info.features._26bit);
EXPECT_TRUE(info.features.fastmult);
EXPECT_FALSE(info.features.fpa);
EXPECT_TRUE(info.features.vfp);
EXPECT_TRUE(info.features.edsp);
EXPECT_TRUE(info.features.java);
EXPECT_FALSE(info.features.iwmmxt);
EXPECT_FALSE(info.features.crunch);
EXPECT_FALSE(info.features.thumbee);
EXPECT_FALSE(info.features.neon);
EXPECT_FALSE(info.features.vfpv3);
EXPECT_FALSE(info.features.vfpv3d16);
EXPECT_TRUE(info.features.tls);
EXPECT_FALSE(info.features.vfpv4);
EXPECT_FALSE(info.features.idiva);
EXPECT_FALSE(info.features.idivt);
EXPECT_FALSE(info.features.vfpd32);
EXPECT_FALSE(info.features.lpae);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_FALSE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
}
TEST(CpuinfoArmTest, MarvellArmadaFromCpuInfo) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor : 0
model name : ARMv7 Processor rev 1 (v7l)
BogoMIPS : 50.00
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x4
CPU part : 0xc09
CPU revision : 1
processor : 1
model name : ARMv7 Processor rev 1 (v7l)
BogoMIPS : 50.00
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x4
CPU part : 0xc09
CPU revision : 1
Hardware : Marvell Armada 380/385 (Device Tree)
Revision : 0000
Serial : 0000000000000000)");
const auto info = GetArmInfo();
EXPECT_EQ(info.implementer, 0x41);
EXPECT_EQ(info.variant, 0x4);
EXPECT_EQ(info.part, 0xc09);
EXPECT_EQ(info.revision, 1);
EXPECT_EQ(info.architecture, 7);
EXPECT_FALSE(info.features.swp);
EXPECT_TRUE(info.features.half);
EXPECT_TRUE(info.features.thumb);
EXPECT_FALSE(info.features._26bit);
EXPECT_TRUE(info.features.fastmult);
EXPECT_FALSE(info.features.fpa);
EXPECT_TRUE(info.features.vfp);
EXPECT_TRUE(info.features.edsp);
EXPECT_FALSE(info.features.java);
EXPECT_FALSE(info.features.iwmmxt);
EXPECT_FALSE(info.features.crunch);
EXPECT_FALSE(info.features.thumbee);
EXPECT_TRUE(info.features.neon);
EXPECT_TRUE(info.features.vfpv3);
EXPECT_FALSE(info.features.vfpv3d16);
EXPECT_TRUE(info.features.tls);
EXPECT_FALSE(info.features.vfpv4);
EXPECT_FALSE(info.features.idiva);
EXPECT_FALSE(info.features.idivt);
EXPECT_TRUE(info.features.vfpd32);
EXPECT_FALSE(info.features.lpae);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_FALSE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
}
// Android test-case
// http://code.google.com/p/android/issues/detail?id=10812
TEST(CpuinfoArmTest, InvalidArmv7) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(Processor : ARMv6-compatible processor rev 6 (v6l)
BogoMIPS : 199.47
Features : swp half thumb fastmult vfp edsp java
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xb76
CPU revision : 6
Hardware : SPICA
Revision : 0020
Serial : 33323613546d00ec )");
const auto info = GetArmInfo();
EXPECT_EQ(info.architecture, 6);
EXPECT_TRUE(info.features.swp);
EXPECT_TRUE(info.features.half);
EXPECT_TRUE(info.features.thumb);
EXPECT_FALSE(info.features._26bit);
EXPECT_TRUE(info.features.fastmult);
EXPECT_FALSE(info.features.fpa);
EXPECT_TRUE(info.features.vfp);
EXPECT_TRUE(info.features.edsp);
EXPECT_TRUE(info.features.java);
EXPECT_FALSE(info.features.iwmmxt);
EXPECT_FALSE(info.features.crunch);
EXPECT_FALSE(info.features.thumbee);
EXPECT_FALSE(info.features.neon);
EXPECT_FALSE(info.features.vfpv3);
EXPECT_FALSE(info.features.vfpv3d16);
EXPECT_FALSE(info.features.tls);
EXPECT_FALSE(info.features.vfpv4);
EXPECT_FALSE(info.features.idiva);
EXPECT_FALSE(info.features.idivt);
EXPECT_FALSE(info.features.vfpd32);
EXPECT_FALSE(info.features.lpae);
EXPECT_FALSE(info.features.evtstrm);
EXPECT_FALSE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
}
// Android test-case
// https://crbug.com/341598.
TEST(CpuinfoArmTest, InvalidNeon) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(Processor: ARMv7 Processory rev 0 (v71)
processor: 0
BogoMIPS: 13.50
Processor: 1
BogoMIPS: 13.50
Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
CPU implementer : 0x51
CPU architecture: 7
CPU variant: 0x1
CPU part: 0x04d
CPU revision: 0
Hardware: SAMSUNG M2
Revision: 0010
Serial: 00001e030000354e)");
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.swp);
EXPECT_FALSE(info.features.neon);
}
// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
// support.
TEST(CpuinfoArmTest, Nexus4_0x510006f2) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(CPU implementer : 0x51
CPU architecture: 7
CPU variant : 0x0
CPU part : 0x6f
CPU revision : 2)");
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.idiva);
EXPECT_TRUE(info.features.idivt);
EXPECT_EQ(GetArmCpuId(&info), 0x510006f2);
}
// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
// support.
TEST(CpuinfoArmTest, Nexus4_0x510006f3) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(CPU implementer : 0x51
CPU architecture: 7
CPU variant : 0x0
CPU part : 0x6f
CPU revision : 3)");
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.idiva);
EXPECT_TRUE(info.features.idivt);
EXPECT_EQ(GetArmCpuId(&info), 0x510006f3);
}
// The 2013 Nexus 7 (Qualcomm Krait) kernel configuration forgets to report IDIV
// support.
TEST(CpuinfoArmTest, Nexus7_2013_0x511006f0) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(CPU implementer : 0x51
CPU architecture: 7
CPU variant : 0x1
CPU part : 0x06f
CPU revision : 0)");
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.idiva);
EXPECT_TRUE(info.features.idivt);
EXPECT_EQ(GetArmCpuId(&info), 0x511006f0);
}
// The emulator-specific Android 4.2 kernel fails to report support for the
// 32-bit ARM IDIV instruction. Technically, this is a feature of the virtual
// CPU implemented by the emulator.
TEST(CpuinfoArmTest, EmulatorSpecificIdiv) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(Processor : ARMv7 Processor rev 0 (v7l)
BogoMIPS : 629.14
Features : swp half thumb fastmult vfp edsp neon vfpv3
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x0
CPU part : 0xc08
CPU revision : 0
Hardware : Goldfish
Revision : 0000
Serial : 0000000000000000)");
const auto info = GetArmInfo();
EXPECT_TRUE(info.features.idiva);
}
} // namespace
} // namespace cpu_features

View File

@@ -0,0 +1,176 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_mips.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
namespace cpu_features {
namespace {
TEST(CpuinfoMipsTest, MipsFeaturesEnum) {
const char *last_name = GetMipsFeaturesEnumName(MIPS_LAST_);
EXPECT_STREQ(last_name, "unknown_feature");
for (int i = static_cast<int>(MIPS_MSA); i != static_cast<int>(MIPS_LAST_); ++i) {
const auto feature = static_cast<MipsFeaturesEnum>(i);
const char *name = GetMipsFeaturesEnumName(feature);
ASSERT_FALSE(name == nullptr);
EXPECT_STRNE(name, "");
EXPECT_STRNE(name, last_name);
}
}
TEST(CpuinfoMipsTest, FromHardwareCapBoth) {
ResetHwcaps();
SetHardwareCapabilities(MIPS_HWCAP_MSA | MIPS_HWCAP_R6, 0);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetMipsInfo();
EXPECT_TRUE(info.features.msa);
EXPECT_FALSE(info.features.eva);
EXPECT_TRUE(info.features.r6);
}
TEST(CpuinfoMipsTest, FromHardwareCapOnlyOne) {
ResetHwcaps();
SetHardwareCapabilities(MIPS_HWCAP_MSA, 0);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetMipsInfo();
EXPECT_TRUE(info.features.msa);
EXPECT_FALSE(info.features.eva);
}
TEST(CpuinfoMipsTest, Ci40) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(system type : IMG Pistachio SoC (B0)
machine : IMG Marduk Ci40 with cc2520
processor : 0
cpu model : MIPS interAptiv (multi) V2.0 FPU V0.0
BogoMIPS : 363.72
wait instruction : yes
microsecond timers : yes
tlb_entries : 64
extra interrupt vector : yes
hardware watchpoint : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
isa : mips1 mips2 mips32r1 mips32r2
ASEs implemented : mips16 dsp mt eva
shadow register sets : 1
kscratch registers : 0
package : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
VPE : 0
)");
const auto info = GetMipsInfo();
EXPECT_FALSE(info.features.msa);
EXPECT_TRUE(info.features.eva);
EXPECT_FALSE(info.features.r6);
EXPECT_TRUE(info.features.mips16);
EXPECT_FALSE(info.features.mdmx);
EXPECT_FALSE(info.features.mips3d);
EXPECT_FALSE(info.features.smart);
EXPECT_TRUE(info.features.dsp);
}
TEST(CpuinfoMipsTest, AR7161) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(system type : Atheros AR7161 rev 2
machine : NETGEAR WNDR3700/WNDR3800/WNDRMAC
processor : 0
cpu model : MIPS 24Kc V7.4
BogoMIPS : 452.19
wait instruction : yes
microsecond timers : yes
tlb_entries : 16
extra interrupt vector : yes
hardware watchpoint : yes, count: 4, address/irw mask: [0x0000, 0x0f98, 0x0f78, 0x0df8]
ASEs implemented : mips16
shadow register sets : 1
kscratch registers : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
)");
const auto info = GetMipsInfo();
EXPECT_FALSE(info.features.msa);
EXPECT_FALSE(info.features.eva);
EXPECT_TRUE(info.features.mips16);
}
TEST(CpuinfoMipsTest, Goldfish) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(system type : MIPS-Goldfish
Hardware : goldfish
Revison : 1
processor : 0
cpu model : MIPS 24Kc V0.0 FPU V0.0
BogoMIPS : 1042.02
wait instruction : yes
microsecond timers : yes
tlb_entries : 16
extra interrupt vector : yes
hardware watchpoint : yes, count: 1, address/irw mask: [0x0ff8]
ASEs implemented :
shadow register sets : 1
core : 0
VCED exceptions : not available
VCEI exceptions : not available
)");
const auto info = GetMipsInfo();
EXPECT_FALSE(info.features.msa);
EXPECT_FALSE(info.features.eva);
}
TEST(CpuinfoMipsTest, BCM1250) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(system type : SiByte BCM91250A (SWARM)
processor : 0
cpu model : SiByte SB1 V0.2 FPU V0.2
BogoMIPS : 532.48
wait instruction : no
microsecond timers : yes
tlb_entries : 64
extra interrupt vector : yes
hardware watchpoint : yes, count: 1, address/irw mask: [0x0ff8]
isa : mips1 mips2 mips3 mips4 mips5 mips32r1 mips32r2 mips64r1 mips64r2
ASEs implemented : mdmx mips3d
shadow register sets : 1
kscratch registers : 0
package : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
)");
const auto info = GetMipsInfo();
EXPECT_FALSE(info.features.msa);
EXPECT_FALSE(info.features.eva);
EXPECT_FALSE(info.features.mips16);
EXPECT_TRUE(info.features.mdmx);
EXPECT_TRUE(info.features.mips3d);
EXPECT_FALSE(info.features.smart);
EXPECT_FALSE(info.features.dsp);
}
} // namespace
} // namespace cpu_features

View File

@@ -0,0 +1,131 @@
// Copyright 2018 IBM.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_ppc.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
#include "internal/string_view.h"
namespace cpu_features {
namespace {
TEST(CpustringsPPCTest, PPCFeaturesEnum) {
const char *last_name = GetPPCFeaturesEnumName(PPC_LAST_);
EXPECT_STREQ(last_name, "unknown_feature");
for (int i = static_cast<int>(PPC_32); i != static_cast<int>(PPC_LAST_); ++i) {
const auto feature = static_cast<PPCFeaturesEnum>(i);
const char *name = GetPPCFeaturesEnumName(feature);
ASSERT_FALSE(name == nullptr);
EXPECT_STRNE(name, "");
EXPECT_STRNE(name, last_name);
}
}
TEST(CpustringsPPCTest, FromHardwareCap) {
ResetHwcaps();
SetHardwareCapabilities(PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_VSX,
PPC_FEATURE2_ARCH_3_00);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetPPCInfo();
EXPECT_TRUE(info.features.fpu);
EXPECT_FALSE(info.features.mmu);
EXPECT_TRUE(info.features.vsx);
EXPECT_TRUE(info.features.arch300);
EXPECT_FALSE(info.features.power4);
EXPECT_FALSE(info.features.altivec);
EXPECT_FALSE(info.features.vcrypto);
EXPECT_FALSE(info.features.htm);
}
TEST(CpustringsPPCTest, Blade) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(processor : 14
cpu : POWER7 (architected), altivec supported
clock : 3000.000000MHz
revision : 2.1 (pvr 003f 0201)
processor : 15
cpu : POWER7 (architected), altivec supported
clock : 3000.000000MHz
revision : 2.1 (pvr 003f 0201)
timebase : 512000000
platform : pSeries
model : IBM,8406-70Y
machine : CHRP IBM,8406-70Y)");
SetPlatformPointer("power7");
SetBasePlatformPointer("power8");
const auto strings = GetPPCPlatformStrings();
ASSERT_STREQ(strings.platform, "pSeries");
ASSERT_STREQ(strings.model, "IBM,8406-70Y");
ASSERT_STREQ(strings.machine, "CHRP IBM,8406-70Y");
ASSERT_STREQ(strings.cpu, "POWER7 (architected), altivec supported");
ASSERT_STREQ(strings.type.platform, "power7");
ASSERT_STREQ(strings.type.base_platform, "power8");
}
TEST(CpustringsPPCTest, Firestone) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(processor : 126
cpu : POWER8 (raw), altivec supported
clock : 2061.000000MHz
revision : 2.0 (pvr 004d 0200)
processor : 127
cpu : POWER8 (raw), altivec supported
clock : 2061.000000MHz
revision : 2.0 (pvr 004d 0200)
timebase : 512000000
platform : PowerNV
model : 8335-GTA
machine : PowerNV 8335-GTA
firmware : OPAL v3)");
const auto strings = GetPPCPlatformStrings();
ASSERT_STREQ(strings.platform, "PowerNV");
ASSERT_STREQ(strings.model, "8335-GTA");
ASSERT_STREQ(strings.machine, "PowerNV 8335-GTA");
ASSERT_STREQ(strings.cpu, "POWER8 (raw), altivec supported");
}
TEST(CpustringsPPCTest, w8) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(processor : 143
cpu : POWER9, altivec supported
clock : 2300.000000MHz
revision : 2.2 (pvr 004e 1202)
timebase : 512000000
platform : PowerNV
model : 0000000000000000
machine : PowerNV 0000000000000000
firmware : OPAL
MMU : Radix)");
const auto strings = GetPPCPlatformStrings();
ASSERT_STREQ(strings.platform, "PowerNV");
ASSERT_STREQ(strings.model, "0000000000000000");
ASSERT_STREQ(strings.machine, "PowerNV 0000000000000000");
ASSERT_STREQ(strings.cpu, "POWER9, altivec supported");
}
} // namespace
} // namespace cpu_features

View File

@@ -0,0 +1,180 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_riscv.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
namespace cpu_features {
namespace {
TEST(CpuinfoRiscvTest, Sipeed_Lichee_RV_FromCpuInfo) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor : 0
hart : 0
isa : rv64imafdc
mmu : sv39
uarch : thead,c906)");
const auto info = GetRiscvInfo();
EXPECT_STREQ(info.uarch, "c906");
EXPECT_STREQ(info.vendor, "thead");
EXPECT_FALSE(info.features.RV32I);
EXPECT_TRUE(info.features.RV64I);
EXPECT_TRUE(info.features.M);
EXPECT_TRUE(info.features.A);
EXPECT_TRUE(info.features.F);
EXPECT_TRUE(info.features.D);
EXPECT_FALSE(info.features.Q);
EXPECT_TRUE(info.features.C);
EXPECT_FALSE(info.features.V);
}
// https://github.com/ThomasKaiser/sbc-bench/blob/284e82b016ec1beeac42a5fcbe556b670f68441a/results/Kendryte-K510-4.17.0.cpuinfo
TEST(CpuinfoRiscvTest, Kendryte_K510_FromCpuInfo) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
hart : 0
isa : rv64i2p0m2p0a2p0f2p0d2p0c2p0xv5-0p0
mmu : sv39
hart : 1
isa : rv64i2p0m2p0a2p0f2p0d2p0c2p0xv5-0p0
mmu : sv39");
const auto info = GetRiscvInfo();
EXPECT_STREQ(info.uarch, "");
EXPECT_STREQ(info.vendor, "");
EXPECT_FALSE(info.features.RV32I);
EXPECT_TRUE(info.features.RV64I);
EXPECT_TRUE(info.features.M);
EXPECT_TRUE(info.features.A);
EXPECT_TRUE(info.features.F);
EXPECT_TRUE(info.features.D);
EXPECT_FALSE(info.features.Q);
EXPECT_TRUE(info.features.C);
EXPECT_FALSE(info.features.V);
}
// https://github.com/ThomasKaiser/sbc-bench/blob/284e82b016ec1beeac42a5fcbe556b670f68441a/results/T-Head-C910-5.10.4.cpuinfo
TEST(CpuinfoRiscvTest, T_Head_C910_FromCpuInfo) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
processor : 0
hart : 0
isa : rv64imafdcsu
mmu : sv39
cpu-freq : 1.2Ghz
cpu-icache : 64KB
cpu-dcache : 64KB
cpu-l2cache : 2MB
cpu-tlb : 1024 4-ways
cpu-cacheline : 64Bytes
cpu-vector : 0.7.1
processor : 1
hart : 1
isa : rv64imafdcsu
mmu : sv39
cpu-freq : 1.2Ghz
cpu-icache : 64KB
cpu-dcache : 64KB
cpu-l2cache : 2MB
cpu-tlb : 1024 4-ways
cpu-cacheline : 64Bytes
cpu-vector : 0.7.1");
const auto info = GetRiscvInfo();
EXPECT_STREQ(info.uarch, "");
EXPECT_STREQ(info.vendor, "");
EXPECT_FALSE(info.features.RV32I);
EXPECT_TRUE(info.features.RV64I);
EXPECT_TRUE(info.features.M);
EXPECT_TRUE(info.features.A);
EXPECT_TRUE(info.features.F);
EXPECT_TRUE(info.features.D);
EXPECT_FALSE(info.features.Q);
EXPECT_TRUE(info.features.C);
EXPECT_FALSE(info.features.V);
}
TEST(CpuinfoRiscvTest, UnknownFromCpuInfo) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
processor : 0
hart : 2
isa : rv64imafdc
mmu : sv39
uarch : sifive,bullet0
processor : 1
hart : 1
isa : rv64imafdc
mmu : sv39
uarch : sifive,bullet0
processor : 2
hart : 3
isa : rv64imafdc
mmu : sv39
uarch : sifive,bullet0
processor : 3
hart : 4
isa : rv64imafdc
mmu : sv39
uarch : sifive,bullet0)");
const auto info = GetRiscvInfo();
EXPECT_STREQ(info.uarch, "bullet0");
EXPECT_STREQ(info.vendor, "sifive");
EXPECT_FALSE(info.features.RV32I);
EXPECT_TRUE(info.features.RV64I);
EXPECT_TRUE(info.features.M);
EXPECT_TRUE(info.features.A);
EXPECT_TRUE(info.features.F);
EXPECT_TRUE(info.features.D);
EXPECT_FALSE(info.features.Q);
EXPECT_TRUE(info.features.C);
EXPECT_FALSE(info.features.V);
}
TEST(CpuinfoRiscvTest, QemuCpuInfo) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(
processor : 0
hart : 0
isa : rv64imafdcvh_zba_zbb_zbc_zbs
mmu : sv48)");
const auto info = GetRiscvInfo();
EXPECT_FALSE(info.features.RV32I);
EXPECT_TRUE(info.features.RV64I);
EXPECT_TRUE(info.features.M);
EXPECT_TRUE(info.features.A);
EXPECT_TRUE(info.features.F);
EXPECT_TRUE(info.features.D);
EXPECT_FALSE(info.features.Q);
EXPECT_TRUE(info.features.C);
EXPECT_TRUE(info.features.V);
}
} // namespace
} // namespace cpu_features

View File

@@ -0,0 +1,82 @@
// Copyright 2022 IBM.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cpuinfo_s390x.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
namespace cpu_features {
namespace {
TEST(CpustringsS390XTest, S390XFeaturesEnum) {
const char *last_name = GetS390XFeaturesEnumName(S390X_LAST_);
EXPECT_STREQ(last_name, "unknown_feature");
for (int i = static_cast<int>(S390_ZARCH); i != static_cast<int>(S390X_LAST_); ++i) {
const auto feature = static_cast<S390XFeaturesEnum>(i);
const char *name = GetS390XFeaturesEnumName(feature);
ASSERT_FALSE(name == nullptr);
EXPECT_STRNE(name, "");
EXPECT_STRNE(name, last_name);
}
}
TEST(CpustringsS390XTest, FromHardwareCap) {
ResetHwcaps();
SetHardwareCapabilities(HWCAP_S390_ESAN3 | HWCAP_S390_HPAGE |
HWCAP_S390_NNPA | HWCAP_S390_SIE, 0);
GetEmptyFilesystem(); // disabling /proc/cpuinfo
const auto info = GetS390XInfo();
EXPECT_TRUE(info.features.esan3);
EXPECT_TRUE(info.features.edat);
EXPECT_TRUE(info.features.nnpa);
EXPECT_TRUE(info.features.sie);
EXPECT_FALSE(info.features.msa);
EXPECT_FALSE(info.features.stfle);
EXPECT_FALSE(info.features.vxp2);
EXPECT_FALSE(info.features.pcimio);
}
TEST(CpustringsS390XTest, z16) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(vendor_id : IBM/S390
# processors : 24
bogomips per cpu: 26315.00
max thread id : 1
features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx vxd vxe gs vxe2 vxp sort dflt vxp2 nnpa pcimio sie )");
SetPlatformPointer("z16");
const auto strings = GetS390XPlatformStrings();
EXPECT_EQ(strings.num_processors, 24);
ASSERT_STREQ(strings.type.platform, "z16");
}
TEST(CpustringsS390XTest, z15) {
ResetHwcaps();
auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo",
R"(vendor_id : IBM/S390
# processors : 2
bogomips per cpu: 24038.00
max thread id : 1
features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx vxd vxe gs vxe2 vxp sort dflt sie)");
SetPlatformPointer("z15");
const auto strings = GetS390XPlatformStrings();
EXPECT_EQ(strings.num_processors, 2);
ASSERT_STREQ(strings.type.platform, "z15");
}
} // namespace
} // namespace cpu_features

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "filesystem_for_testing.h"
#include <cassert>
#include <climits>
#include <cstdio>
#include <cstring>
#include <utility>
namespace cpu_features {
FakeFile::FakeFile(int file_descriptor, const char* content)
: file_descriptor_(file_descriptor), content_(content) {}
FakeFile::~FakeFile() { assert(!opened_); }
void FakeFile::Open() {
assert(!opened_);
opened_ = true;
}
void FakeFile::Close() {
assert(opened_);
opened_ = false;
}
int FakeFile::Read(int fd, void* buf, size_t count) {
assert(count < INT_MAX);
assert(fd == file_descriptor_);
const size_t remainder = content_.size() - head_index_;
const size_t read = count > remainder ? remainder : count;
memcpy(buf, content_.data() + head_index_, read);
head_index_ += read;
assert(read < INT_MAX);
return (int)read;
}
void FakeFilesystem::Reset() { files_.clear(); }
FakeFile* FakeFilesystem::CreateFile(const std::string& filename,
const char* content) {
auto& file = files_[filename];
file =
std::unique_ptr<FakeFile>(new FakeFile(next_file_descriptor_++, content));
return file.get();
}
FakeFile* FakeFilesystem::FindFileOrNull(const std::string& filename) const {
const auto itr = files_.find(filename);
return itr == files_.end() ? nullptr : itr->second.get();
}
FakeFile* FakeFilesystem::FindFileOrDie(const int file_descriptor) const {
for (const auto& filename_file_pair : files_) {
FakeFile* const file_ptr = filename_file_pair.second.get();
if (file_ptr->GetFileDescriptor() == file_descriptor) {
return file_ptr;
}
}
assert(false);
return nullptr;
}
static FakeFilesystem* kFilesystem = new FakeFilesystem();
FakeFilesystem& GetEmptyFilesystem() {
kFilesystem->Reset();
return *kFilesystem;
}
extern "C" int CpuFeatures_OpenFile(const char* filename) {
auto* const file = kFilesystem->FindFileOrNull(filename);
if (file) {
file->Open();
return file->GetFileDescriptor();
}
return -1;
}
extern "C" void CpuFeatures_CloseFile(int file_descriptor) {
kFilesystem->FindFileOrDie(file_descriptor)->Close();
}
extern "C" int CpuFeatures_ReadFile(int file_descriptor, void* buffer,
size_t buffer_size) {
return kFilesystem->FindFileOrDie(file_descriptor)
->Read(file_descriptor, buffer, buffer_size);
}
} // namespace cpu_features

View File

@@ -0,0 +1,61 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Implements a fake filesystem, useful for tests.
#ifndef CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_
#define CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_
#include <memory>
#include <string>
#include <unordered_map>
#include "internal/filesystem.h"
namespace cpu_features {
class FakeFile {
public:
explicit FakeFile(int file_descriptor, const char* content);
~FakeFile();
void Open();
void Close();
int Read(int fd, void* buf, size_t count);
int GetFileDescriptor() const { return file_descriptor_; }
private:
const int file_descriptor_;
const std::string content_;
bool opened_ = false;
size_t head_index_ = 0;
};
class FakeFilesystem {
public:
void Reset();
FakeFile* CreateFile(const std::string& filename, const char* content);
FakeFile* FindFileOrDie(const int file_descriptor) const;
FakeFile* FindFileOrNull(const std::string& filename) const;
private:
int next_file_descriptor_ = 0;
std::unordered_map<std::string, std::unique_ptr<FakeFile>> files_;
};
FakeFilesystem& GetEmptyFilesystem();
} // namespace cpu_features
#endif // CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_

View File

@@ -0,0 +1,52 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "hwcaps_for_testing.h"
#include <string.h>
#include "internal/string_view.h"
namespace cpu_features {
namespace {
static auto* const g_hardware_capabilities = new HardwareCapabilities();
static const char* g_platform_pointer = nullptr;
static const char* g_base_platform_pointer = nullptr;
} // namespace
void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2) {
g_hardware_capabilities->hwcaps = hwcaps;
g_hardware_capabilities->hwcaps2 = hwcaps2;
}
void SetPlatformPointer(const char* string) { g_platform_pointer = string; }
void SetBasePlatformPointer(const char* string) {
g_base_platform_pointer = string;
}
void ResetHwcaps() {
SetHardwareCapabilities(0, 0);
SetPlatformPointer(nullptr);
SetBasePlatformPointer(nullptr);
}
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) {
return *g_hardware_capabilities;
}
const char* CpuFeatures_GetPlatformPointer(void) { return g_platform_pointer; }
const char* CpuFeatures_GetBasePlatformPointer(void) {
return g_base_platform_pointer;
}
} // namespace cpu_features

View File

@@ -0,0 +1,31 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
#define CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
#include "internal/hwcaps.h"
namespace cpu_features {
void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2);
void SetPlatformPointer(const char* string);
void SetBasePlatformPointer(const char* string);
// To be called before each test.
void ResetHwcaps();
} // namespace cpu_features
#endif // CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_

View File

@@ -0,0 +1,132 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/stack_line_reader.h"
#include "filesystem_for_testing.h"
#include "gtest/gtest.h"
namespace cpu_features {
bool operator==(const StringView& a, const StringView& b) {
return CpuFeatures_StringView_IsEquals(a, b);
}
namespace {
std::string ToString(StringView view) { return {view.ptr, view.size}; }
TEST(StackLineReaderTest, Empty) {
auto& fs = GetEmptyFilesystem();
auto* file = fs.CreateFile("/proc/cpuinfo", "");
StackLineReader reader;
StackLineReader_Initialize(&reader, file->GetFileDescriptor());
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_TRUE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str(""));
}
}
TEST(StackLineReaderTest, ManySmallLines) {
auto& fs = GetEmptyFilesystem();
auto* file = fs.CreateFile("/proc/cpuinfo", "a\nb\nc");
StackLineReader reader;
StackLineReader_Initialize(&reader, file->GetFileDescriptor());
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("a"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("b"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_TRUE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("c"));
}
}
TEST(StackLineReaderTest, TruncatedLine) {
auto& fs = GetEmptyFilesystem();
auto* file = fs.CreateFile("/proc/cpuinfo", R"(First
Second
More than 16 characters, this will be truncated.
last)");
StackLineReader reader;
StackLineReader_Initialize(&reader, file->GetFileDescriptor());
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("First"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("Second"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_FALSE(result.full_line);
EXPECT_EQ(result.line, str("More than 16 cha"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_TRUE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str("last"));
}
}
TEST(StackLineReaderTest, TruncatedLines) {
auto& fs = GetEmptyFilesystem();
auto* file = fs.CreateFile("/proc/cpuinfo", R"(More than 16 characters
Another line that is too long)");
StackLineReader reader;
StackLineReader_Initialize(&reader, file->GetFileDescriptor());
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_FALSE(result.full_line);
EXPECT_EQ(result.line, str("More than 16 cha"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_FALSE(result.eof);
EXPECT_FALSE(result.full_line);
EXPECT_EQ(result.line, str("Another line tha"));
}
{
const auto result = StackLineReader_NextLine(&reader);
EXPECT_TRUE(result.eof);
EXPECT_TRUE(result.full_line);
EXPECT_EQ(result.line, str(""));
}
}
} // namespace
} // namespace cpu_features

View File

@@ -0,0 +1,202 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/string_view.h"
#include "gtest/gtest.h"
namespace cpu_features {
bool operator==(const StringView& a, const StringView& b) {
return CpuFeatures_StringView_IsEquals(a, b);
}
namespace {
TEST(StringViewTest, Empty) {
EXPECT_EQ(kEmptyStringView.ptr, nullptr);
EXPECT_EQ(kEmptyStringView.size, 0);
}
TEST(StringViewTest, Build) {
const auto view = str("test");
EXPECT_EQ(view.ptr[0], 't');
EXPECT_EQ(view.size, 4);
}
TEST(StringViewTest, CpuFeatures_StringView_IndexOfChar) {
// Found.
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'e'), 1);
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 't'), 0);
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("beef"), 'e'), 1);
// Not found.
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'z'), -1);
// Empty.
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(kEmptyStringView, 'z'), -1);
}
TEST(StringViewTest, CpuFeatures_StringView_IndexOf) {
// Found.
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("es")), 1);
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("test")), 0);
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("tesstest"), str("test")), 4);
// Not found.
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("aa")), -1);
// Empty.
EXPECT_EQ(CpuFeatures_StringView_IndexOf(kEmptyStringView, str("aa")), -1);
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("aa"), kEmptyStringView), -1);
}
TEST(StringViewTest, CpuFeatures_StringView_StartsWith) {
EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("te")));
EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("test")));
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("st")));
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("est")));
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("")));
EXPECT_FALSE(
CpuFeatures_StringView_StartsWith(str("test"), kEmptyStringView));
EXPECT_FALSE(
CpuFeatures_StringView_StartsWith(kEmptyStringView, str("test")));
}
TEST(StringViewTest, CpuFeatures_StringView_IsEquals) {
EXPECT_TRUE(
CpuFeatures_StringView_IsEquals(kEmptyStringView, kEmptyStringView));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("")));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str(""), kEmptyStringView));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("test"), str("test")));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("a"), str("a")));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("b")));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("aa"), str("a")));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("aa")));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), kEmptyStringView));
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("a")));
}
TEST(StringViewTest, CpuFeatures_StringView_PopFront) {
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 2), str("st"));
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 0), str("test"));
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 4), str(""));
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 100), str(""));
}
TEST(StringViewTest, CpuFeatures_StringView_PopBack) {
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 2), str("te"));
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 0), str("test"));
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 4), str(""));
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 100), str(""));
}
TEST(StringViewTest, CpuFeatures_StringView_KeepFront) {
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 2), str("te"));
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 0), str(""));
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 4), str("test"));
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 6), str("test"));
}
TEST(StringViewTest, CpuFeatures_StringView_Front) {
EXPECT_EQ(CpuFeatures_StringView_Front(str("apple")), 'a');
EXPECT_EQ(CpuFeatures_StringView_Front(str("a")), 'a');
}
TEST(StringViewTest, CpuFeatures_StringView_Back) {
EXPECT_EQ(CpuFeatures_StringView_Back(str("apple")), 'e');
EXPECT_EQ(CpuFeatures_StringView_Back(str("a")), 'a');
}
TEST(StringViewTest, CpuFeatures_StringView_TrimWhitespace) {
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last ")),
str("first middle last"));
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last ")),
str("first middle last"));
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last")),
str("first middle last"));
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last")),
str("first middle last"));
}
TEST(StringViewTest, CpuFeatures_StringView_ParsePositiveNumber) {
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("42")), 42);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a")), 42);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A")), 42);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A2a")), 10794);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a2A")), 10794);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-10")), -1);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-0x2A")), -1);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("abc")), -1);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("")), -1);
}
TEST(StringViewTest, CpuFeatures_StringView_CopyString) {
char buf[4];
buf[0] = 'X';
// Empty
CpuFeatures_StringView_CopyString(str(""), buf, sizeof(buf));
EXPECT_STREQ(buf, "");
// Less
CpuFeatures_StringView_CopyString(str("a"), buf, sizeof(buf));
EXPECT_STREQ(buf, "a");
// exact
CpuFeatures_StringView_CopyString(str("abc"), buf, sizeof(buf));
EXPECT_STREQ(buf, "abc");
// More
CpuFeatures_StringView_CopyString(str("abcd"), buf, sizeof(buf));
EXPECT_STREQ(buf, "abc");
}
TEST(StringViewTest, CpuFeatures_StringView_HasWord) {
// Find flags at beginning, middle and end.
EXPECT_TRUE(
CpuFeatures_StringView_HasWord(str("first middle last"), "first", ' '));
EXPECT_TRUE(
CpuFeatures_StringView_HasWord(str("first middle last"), "middle", ' '));
EXPECT_TRUE(
CpuFeatures_StringView_HasWord(str("first middle last"), "last", ' '));
// Find flags at beginning, middle and end with a different separator
EXPECT_TRUE(
CpuFeatures_StringView_HasWord(str("first-middle-last"), "first", '-'));
EXPECT_TRUE(
CpuFeatures_StringView_HasWord(str("first-middle-last"), "middle", '-'));
EXPECT_TRUE(
CpuFeatures_StringView_HasWord(str("first-middle-last"), "last", '-'));
// Do not match partial flags
EXPECT_FALSE(
CpuFeatures_StringView_HasWord(str("first middle last"), "irst", ' '));
EXPECT_FALSE(
CpuFeatures_StringView_HasWord(str("first middle last"), "mid", ' '));
EXPECT_FALSE(
CpuFeatures_StringView_HasWord(str("first middle last"), "las", ' '));
}
TEST(StringViewTest, CpuFeatures_StringView_GetAttributeKeyValue) {
const StringView line = str(" key : first middle last ");
StringView key, value;
EXPECT_TRUE(CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value));
EXPECT_EQ(key, str("key"));
EXPECT_EQ(value, str("first middle last"));
}
TEST(StringViewTest, FailingGetAttributeKeyValue) {
const StringView line = str("key first middle last");
StringView key, value;
EXPECT_FALSE(CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value));
}
} // namespace
} // namespace cpu_features