mirror of
https://github.com/google/cpu_features.git
synced 2025-07-03 14:13:18 +02:00
Adding code. Closes #0.
This commit is contained in:
74
test/CMakeLists.txt
Normal file
74
test/CMakeLists.txt
Normal file
@ -0,0 +1,74 @@
|
||||
#
|
||||
# libraries for tests
|
||||
#
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11
|
||||
|
||||
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)
|
||||
##------------------------------------------------------------------------------
|
||||
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/stack_line_reader.c ../src/linux_features_aggregator.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)
|
||||
##------------------------------------------------------------------------------
|
||||
## linux_features_aggregator_test
|
||||
add_executable(linux_features_aggregator_test linux_features_aggregator_test.cc)
|
||||
target_link_libraries(linux_features_aggregator_test all_libraries)
|
||||
add_test(NAME linux_features_aggregator_test COMMAND linux_features_aggregator_test)
|
||||
##------------------------------------------------------------------------------
|
||||
## cpuinfo_x86_test
|
||||
add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c)
|
||||
target_link_libraries(cpuinfo_x86_test all_libraries)
|
||||
add_test(NAME cpuinfo_x86_test COMMAND cpuinfo_x86_test)
|
||||
##------------------------------------------------------------------------------
|
||||
## cpuinfo_arm_test
|
||||
add_executable(cpuinfo_arm_test cpuinfo_arm_test.cc ../src/cpuinfo_arm.c)
|
||||
target_link_libraries(cpuinfo_arm_test all_libraries)
|
||||
add_test(NAME cpuinfo_arm_test COMMAND cpuinfo_arm_test)
|
||||
##------------------------------------------------------------------------------
|
||||
## cpuinfo_aarch64_test
|
||||
add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc ../src/cpuinfo_aarch64.c)
|
||||
target_link_libraries(cpuinfo_aarch64_test all_libraries)
|
||||
add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test)
|
||||
##------------------------------------------------------------------------------
|
||||
## cpuinfo_mips_test
|
||||
add_executable(cpuinfo_mips_test cpuinfo_mips_test.cc ../src/cpuinfo_mips.c)
|
||||
target_link_libraries(cpuinfo_mips_test all_libraries)
|
||||
add_test(NAME cpuinfo_mips_test COMMAND cpuinfo_mips_test)
|
53
test/bit_utils_test.cc
Normal file
53
test/bit_utils_test.cc
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 (size_t i = 0; i < 32; ++i) {
|
||||
EXPECT_EQ(IsBitSet(value, i), i == bit_set);
|
||||
}
|
||||
}
|
||||
|
||||
// testing 0, all bits should be 0.
|
||||
for (size_t i = 0; i < 32; ++i) {
|
||||
EXPECT_FALSE(IsBitSet(0, i));
|
||||
}
|
||||
|
||||
// testing ~0, all bits should be 1.
|
||||
for (size_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
|
74
test/cpuinfo_aarch64_test.cc
Normal file
74
test/cpuinfo_aarch64_test.cc
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 "filesystem_for_testing.h"
|
||||
#include "hwcaps_for_testing.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace cpu_features {
|
||||
namespace {
|
||||
|
||||
void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
|
||||
|
||||
TEST(CpuinfoAarch64Test, FromHardwareCap) {
|
||||
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_TRUE(info.features.aes);
|
||||
EXPECT_FALSE(info.features.pmull);
|
||||
EXPECT_FALSE(info.features.sha1);
|
||||
EXPECT_FALSE(info.features.sha2);
|
||||
EXPECT_FALSE(info.features.crc32);
|
||||
}
|
||||
|
||||
TEST(CpuinfoAarch64Test, ARMCortexA53) {
|
||||
DisableHardwareCapabilities();
|
||||
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.aes);
|
||||
EXPECT_TRUE(info.features.pmull);
|
||||
EXPECT_TRUE(info.features.sha1);
|
||||
EXPECT_TRUE(info.features.sha2);
|
||||
EXPECT_TRUE(info.features.crc32);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpu_features
|
182
test/cpuinfo_arm_test.cc
Normal file
182
test/cpuinfo_arm_test.cc
Normal file
@ -0,0 +1,182 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 "hwcaps_for_testing.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace cpu_features {
|
||||
namespace {
|
||||
|
||||
void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
|
||||
|
||||
TEST(CpuinfoArmTest, FromHardwareCap) {
|
||||
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.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);
|
||||
}
|
||||
|
||||
TEST(CpuinfoArmTest, ODroidFromCpuInfo) {
|
||||
DisableHardwareCapabilities();
|
||||
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_TRUE(info.features.vfp);
|
||||
EXPECT_FALSE(info.features.iwmmxt);
|
||||
EXPECT_TRUE(info.features.neon);
|
||||
EXPECT_TRUE(info.features.vfpv3);
|
||||
EXPECT_FALSE(info.features.vfpv3d16);
|
||||
EXPECT_TRUE(info.features.vfpv4);
|
||||
EXPECT_TRUE(info.features.idiva);
|
||||
EXPECT_TRUE(info.features.idivt);
|
||||
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);
|
||||
}
|
||||
|
||||
// http://code.google.com/p/android/issues/detail?id=10812
|
||||
TEST(CpuinfoArmTest, InvalidArmv7) {
|
||||
DisableHardwareCapabilities();
|
||||
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);
|
||||
}
|
||||
|
||||
// https://crbug.com/341598.
|
||||
TEST(CpuinfoArmTest, InvalidNeon) {
|
||||
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_FALSE(info.features.neon);
|
||||
}
|
||||
|
||||
// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
|
||||
// support.
|
||||
TEST(CpuinfoArmTest, Nexus4_0x510006f2) {
|
||||
DisableHardwareCapabilities();
|
||||
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);
|
||||
}
|
||||
|
||||
// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV
|
||||
// support.
|
||||
TEST(CpuinfoArmTest, Nexus4_0x510006f3) {
|
||||
DisableHardwareCapabilities();
|
||||
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);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
DisableHardwareCapabilities();
|
||||
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
|
125
test/cpuinfo_mips_test.cc
Normal file
125
test/cpuinfo_mips_test.cc
Normal file
@ -0,0 +1,125 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 "hwcaps_for_testing.h"
|
||||
#include "internal/stack_line_reader.h"
|
||||
#include "internal/string_view.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace cpu_features {
|
||||
|
||||
namespace {
|
||||
|
||||
void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); }
|
||||
|
||||
TEST(CpuinfoMipsTest, FromHardwareCapBoth) {
|
||||
SetHardwareCapabilities(MIPS_HWCAP_EVA | MIPS_HWCAP_MSA, 0);
|
||||
GetEmptyFilesystem(); // disabling /proc/cpuinfo
|
||||
const auto info = GetMipsInfo();
|
||||
EXPECT_TRUE(info.features.msa);
|
||||
EXPECT_TRUE(info.features.eva);
|
||||
}
|
||||
|
||||
TEST(CpuinfoMipsTest, FromHardwareCapOnlyOne) {
|
||||
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) {
|
||||
DisableHardwareCapabilities();
|
||||
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);
|
||||
}
|
||||
|
||||
TEST(CpuinfoMipsTest, AR7161) {
|
||||
DisableHardwareCapabilities();
|
||||
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);
|
||||
}
|
||||
|
||||
TEST(CpuinfoMipsTest, Goldfish) {
|
||||
DisableHardwareCapabilities();
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpu_features
|
172
test/cpuinfo_x86_test.cc
Normal file
172
test/cpuinfo_x86_test.cc
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 <cassert>
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "cpuinfo_x86.h"
|
||||
#include "internal/cpuid_x86.h"
|
||||
|
||||
namespace cpu_features {
|
||||
|
||||
class FakeCpu {
|
||||
public:
|
||||
Leaf CpuId(uint32_t leaf_id) const {
|
||||
const auto itr = cpuid_leaves_.find(leaf_id);
|
||||
EXPECT_TRUE(itr != cpuid_leaves_.end()) << "Missing leaf " << leaf_id;
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
uint32_t GetXCR0Eax() const { return xcr0_eax_; }
|
||||
|
||||
void SetLeaves(std::map<uint32_t, Leaf> configuration) {
|
||||
cpuid_leaves_ = std::move(configuration);
|
||||
}
|
||||
|
||||
void SetOsBackupsExtendedRegisters(bool os_backups_extended_registers) {
|
||||
xcr0_eax_ = os_backups_extended_registers ? -1 : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<uint32_t, Leaf> cpuid_leaves_;
|
||||
uint32_t xcr0_eax_;
|
||||
};
|
||||
|
||||
auto* g_fake_cpu = new FakeCpu();
|
||||
|
||||
extern "C" Leaf CpuId(uint32_t leaf_id) { return g_fake_cpu->CpuId(leaf_id); }
|
||||
extern "C" uint32_t GetXCR0Eax(void) { return g_fake_cpu->GetXCR0Eax(); }
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(CpuidX86Test, SandyBridge) {
|
||||
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
|
||||
g_fake_cpu->SetLeaves({
|
||||
{0x00000000, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||
{0x00000001, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
|
||||
{0x00000007, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||
});
|
||||
const auto info = GetX86Info();
|
||||
EXPECT_STREQ(info.vendor, "GenuineIntel");
|
||||
EXPECT_EQ(info.family, 0x06);
|
||||
EXPECT_EQ(info.model, 0x02A);
|
||||
EXPECT_EQ(info.stepping, 0x06);
|
||||
// Leaf 7 is zeroed out so none of the Leaf 7 flags are set.
|
||||
const auto features = info.features;
|
||||
EXPECT_FALSE(features.erms);
|
||||
EXPECT_FALSE(features.avx2);
|
||||
EXPECT_FALSE(features.avx512f);
|
||||
EXPECT_FALSE(features.avx512cd);
|
||||
EXPECT_FALSE(features.avx512er);
|
||||
EXPECT_FALSE(features.avx512pf);
|
||||
EXPECT_FALSE(features.avx512bw);
|
||||
EXPECT_FALSE(features.avx512dq);
|
||||
EXPECT_FALSE(features.avx512vl);
|
||||
EXPECT_FALSE(features.avx512ifma);
|
||||
EXPECT_FALSE(features.avx512vbmi);
|
||||
EXPECT_FALSE(features.avx512vbmi2);
|
||||
EXPECT_FALSE(features.avx512vnni);
|
||||
EXPECT_FALSE(features.avx512bitalg);
|
||||
EXPECT_FALSE(features.avx512vpopcntdq);
|
||||
EXPECT_FALSE(features.avx512_4vnniw);
|
||||
EXPECT_FALSE(features.avx512_4vbmi2);
|
||||
// All old cpu features should be set.
|
||||
EXPECT_TRUE(features.aes);
|
||||
EXPECT_TRUE(features.ssse3);
|
||||
EXPECT_TRUE(features.sse4_1);
|
||||
EXPECT_TRUE(features.sse4_2);
|
||||
EXPECT_TRUE(features.avx);
|
||||
}
|
||||
|
||||
TEST(CpuidX86Test, SandyBridgeTestOsSupport) {
|
||||
g_fake_cpu->SetLeaves({
|
||||
{0x00000000, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||
{0x00000001, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
|
||||
{0x00000007, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||
});
|
||||
// avx is disabled if os does not support backing up ymm registers.
|
||||
g_fake_cpu->SetOsBackupsExtendedRegisters(false);
|
||||
EXPECT_FALSE(GetX86Info().features.avx);
|
||||
// avx is disabled if os does not support backing up ymm registers.
|
||||
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
|
||||
EXPECT_TRUE(GetX86Info().features.avx);
|
||||
}
|
||||
|
||||
TEST(CpuidX86Test, SkyLake) {
|
||||
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
|
||||
g_fake_cpu->SetLeaves({
|
||||
{0x00000000, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||
{0x00000001, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
|
||||
{0x00000007, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
|
||||
});
|
||||
const auto info = GetX86Info();
|
||||
EXPECT_STREQ(info.vendor, "GenuineIntel");
|
||||
EXPECT_EQ(info.family, 0x06);
|
||||
EXPECT_EQ(info.model, 0x04E);
|
||||
EXPECT_EQ(info.stepping, 0x03);
|
||||
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL);
|
||||
}
|
||||
|
||||
TEST(CpuidX86Test, Branding) {
|
||||
g_fake_cpu->SetLeaves({
|
||||
{0x00000000, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||
{0x00000001, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
|
||||
{0x00000007, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}},
|
||||
{0x80000000, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
|
||||
{0x80000001, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}},
|
||||
{0x80000002, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}},
|
||||
{0x80000003, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}},
|
||||
{0x80000004, Leaf{0x352E3220, 0x7A484730, 0x00000000, 0x00000000}},
|
||||
});
|
||||
char brand_string[49];
|
||||
FillX86BrandString(brand_string);
|
||||
EXPECT_STREQ(brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz");
|
||||
}
|
||||
|
||||
// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt
|
||||
TEST(CpuidX86Test, AMD_K15) {
|
||||
g_fake_cpu->SetLeaves({
|
||||
{0x00000000, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||
{0x00000001, Leaf{0x00630F81, 0x00040800, 0x3E98320B, 0x178BFBFF}},
|
||||
{0x00000007, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||
{0x80000000, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||
{0x80000001, Leaf{0x00630F81, 0x10000000, 0x0FEBBFFF, 0x2FD3FBFF}},
|
||||
{0x80000002, Leaf{0x20444D41, 0x372D3841, 0x4B303736, 0x64615220}},
|
||||
{0x80000003, Leaf{0x206E6F65, 0x202C3752, 0x43203031, 0x75706D6F}},
|
||||
{0x80000004, Leaf{0x43206574, 0x7365726F, 0x2B433420, 0x00204736}},
|
||||
{0x80000005, Leaf{0xFF40FF18, 0xFF40FF30, 0x10040140, 0x60030140}},
|
||||
});
|
||||
const auto info = GetX86Info();
|
||||
|
||||
EXPECT_STREQ(info.vendor, "AuthenticAMD");
|
||||
EXPECT_EQ(info.family, 0x15);
|
||||
EXPECT_EQ(info.model, 0x38);
|
||||
EXPECT_EQ(info.stepping, 0x01);
|
||||
EXPECT_EQ(GetX86Microarchitecture(&info),
|
||||
X86Microarchitecture::AMD_BULLDOZER);
|
||||
|
||||
char brand_string[49];
|
||||
FillX86BrandString(brand_string);
|
||||
EXPECT_STREQ(brand_string, "AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G ");
|
||||
}
|
||||
|
||||
// TODO(user): test what happens when xsave/osxsave are not present.
|
||||
// TODO(user): test what happens when xmm/ymm/zmm os support are not
|
||||
// present.
|
||||
|
||||
} // namespace
|
||||
} // namespace cpu_features
|
102
test/filesystem_for_testing.cc
Normal file
102
test/filesystem_for_testing.cc
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 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 OpenFile(const char* filename) {
|
||||
auto* const file = kFilesystem->FindFileOrNull(filename);
|
||||
if (file) {
|
||||
file->Open();
|
||||
return file->GetFileDescriptor();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" void CloseFile(int file_descriptor) {
|
||||
kFilesystem->FindFileOrDie(file_descriptor)->Close();
|
||||
}
|
||||
|
||||
extern "C" int ReadFile(int file_descriptor, void* buf, size_t count) {
|
||||
return kFilesystem->FindFileOrDie(file_descriptor)
|
||||
->Read(file_descriptor, buf, count);
|
||||
}
|
||||
|
||||
} // namespace cpu_features
|
61
test/filesystem_for_testing.h
Normal file
61
test/filesystem_for_testing.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 THIRD_PARTY_CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_
|
||||
#define THIRD_PARTY_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:
|
||||
size_t next_file_descriptor_ = 0;
|
||||
std::unordered_map<std::string, std::unique_ptr<FakeFile>> files_;
|
||||
};
|
||||
|
||||
FakeFilesystem& GetEmptyFilesystem();
|
||||
|
||||
} // namespace cpu_features
|
||||
|
||||
#endif // THIRD_PARTY_CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_
|
32
test/hwcaps_for_testing.cc
Normal file
32
test/hwcaps_for_testing.cc
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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"
|
||||
|
||||
namespace cpu_features {
|
||||
|
||||
namespace {
|
||||
static auto* const g_hardware_capabilities = new HardwareCapabilities();
|
||||
} // namespace
|
||||
|
||||
void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2) {
|
||||
g_hardware_capabilities->hwcaps = hwcaps;
|
||||
g_hardware_capabilities->hwcaps2 = hwcaps2;
|
||||
}
|
||||
|
||||
HardwareCapabilities GetHardwareCapabilities(void) {
|
||||
return *g_hardware_capabilities;
|
||||
}
|
||||
|
||||
} // namespace cpu_features
|
26
test/hwcaps_for_testing.h
Normal file
26
test/hwcaps_for_testing.h
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 THIRD_PARTY_CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
|
||||
#define THIRD_PARTY_CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
|
||||
|
||||
#include "internal/hwcaps.h"
|
||||
|
||||
namespace cpu_features {
|
||||
|
||||
void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2);
|
||||
|
||||
} // namespace cpu_features
|
||||
|
||||
#endif // THIRD_PARTY_CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
|
90
test/linux_features_aggregator_test.cc
Normal file
90
test/linux_features_aggregator_test.cc
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 <array>
|
||||
|
||||
#include "internal/linux_features_aggregator.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace cpu_features {
|
||||
|
||||
namespace {
|
||||
|
||||
struct Features {
|
||||
bool a = false;
|
||||
bool b = false;
|
||||
bool c = false;
|
||||
};
|
||||
|
||||
DECLARE_SETTER(Features, a)
|
||||
DECLARE_SETTER(Features, b)
|
||||
DECLARE_SETTER(Features, c)
|
||||
|
||||
class LinuxFeatureAggregatorTest : public testing::Test {
|
||||
public:
|
||||
const std::array<CapabilityConfig, 3> kConfigs = {
|
||||
{{{0b0001, 0b0000}, "a", &set_a},
|
||||
{{0b0010, 0b0000}, "b", &set_b},
|
||||
{{0b0000, 0b1100}, "c", &set_c}}};
|
||||
};
|
||||
|
||||
TEST_F(LinuxFeatureAggregatorTest, FromFlagsEmpty) {
|
||||
Features features;
|
||||
SetFromFlags(kConfigs.size(), kConfigs.data(), str(""), &features);
|
||||
EXPECT_FALSE(features.a);
|
||||
EXPECT_FALSE(features.b);
|
||||
EXPECT_FALSE(features.c);
|
||||
}
|
||||
|
||||
TEST_F(LinuxFeatureAggregatorTest, FromFlagsAllSet) {
|
||||
Features features;
|
||||
SetFromFlags(kConfigs.size(), kConfigs.data(), str("a c b"), &features);
|
||||
EXPECT_TRUE(features.a);
|
||||
EXPECT_TRUE(features.b);
|
||||
EXPECT_TRUE(features.c);
|
||||
}
|
||||
|
||||
TEST_F(LinuxFeatureAggregatorTest, FromFlagsOnlyA) {
|
||||
Features features;
|
||||
SetFromFlags(kConfigs.size(), kConfigs.data(), str("a"), &features);
|
||||
EXPECT_TRUE(features.a);
|
||||
EXPECT_FALSE(features.b);
|
||||
EXPECT_FALSE(features.c);
|
||||
}
|
||||
|
||||
TEST_F(LinuxFeatureAggregatorTest, FromHwcapsNone) {
|
||||
HardwareCapabilities capability;
|
||||
capability.hwcaps = 0; // matches none
|
||||
capability.hwcaps2 = 0; // matches none
|
||||
Features features;
|
||||
OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability, &features);
|
||||
EXPECT_FALSE(features.a);
|
||||
EXPECT_FALSE(features.b);
|
||||
EXPECT_FALSE(features.c);
|
||||
}
|
||||
|
||||
TEST_F(LinuxFeatureAggregatorTest, FromHwcapsSet) {
|
||||
HardwareCapabilities capability;
|
||||
capability.hwcaps = 0b0010; // matches b but not a
|
||||
capability.hwcaps2 = 0b1111; // matches c
|
||||
Features features;
|
||||
OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability, &features);
|
||||
EXPECT_FALSE(features.a);
|
||||
EXPECT_TRUE(features.b);
|
||||
EXPECT_TRUE(features.c);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpu_features
|
132
test/stack_line_reader_test.cc
Normal file
132
test/stack_line_reader_test.cc
Normal file
@ -0,0 +1,132 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 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
|
138
test/string_view_test.cc
Normal file
138
test/string_view_test.cc
Normal file
@ -0,0 +1,138 @@
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// 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 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, IndexOfChar) {
|
||||
// Found.
|
||||
EXPECT_EQ(IndexOfChar(str("test"), 'e'), 1);
|
||||
// Not found.
|
||||
EXPECT_EQ(IndexOfChar(str("test"), 'z'), -1);
|
||||
// Empty.
|
||||
EXPECT_EQ(IndexOfChar(kEmptyStringView, 'z'), -1);
|
||||
}
|
||||
|
||||
TEST(StringViewTest, IndexOf) {
|
||||
// Found.
|
||||
EXPECT_EQ(IndexOf(str("test"), str("es")), 1);
|
||||
// Not found.
|
||||
EXPECT_EQ(IndexOf(str("test"), str("aa")), -1);
|
||||
// Empty.
|
||||
EXPECT_EQ(IndexOf(kEmptyStringView, str("aa")), -1);
|
||||
EXPECT_EQ(IndexOf(str("aa"), kEmptyStringView), -1);
|
||||
}
|
||||
|
||||
TEST(StringViewTest, StartsWith) {
|
||||
EXPECT_TRUE(StartsWith(str("test"), str("te")));
|
||||
EXPECT_FALSE(StartsWith(str("test"), str("")));
|
||||
EXPECT_FALSE(StartsWith(str("test"), kEmptyStringView));
|
||||
EXPECT_FALSE(StartsWith(kEmptyStringView, str("test")));
|
||||
}
|
||||
|
||||
TEST(StringViewTest, IsEquals) {
|
||||
EXPECT_TRUE(IsEquals(kEmptyStringView, kEmptyStringView));
|
||||
EXPECT_TRUE(IsEquals(kEmptyStringView, str("")));
|
||||
EXPECT_TRUE(IsEquals(str(""), kEmptyStringView));
|
||||
EXPECT_TRUE(IsEquals(str("a"), str("a")));
|
||||
EXPECT_FALSE(IsEquals(str("a"), str("b")));
|
||||
EXPECT_FALSE(IsEquals(str("a"), kEmptyStringView));
|
||||
EXPECT_FALSE(IsEquals(kEmptyStringView, str("a")));
|
||||
}
|
||||
|
||||
TEST(StringViewTest, PopFront) {
|
||||
EXPECT_EQ(PopFront(str("test"), 2), str("st"));
|
||||
EXPECT_EQ(PopFront(str("test"), 0), str("test"));
|
||||
EXPECT_EQ(PopFront(str("test"), 4), str(""));
|
||||
EXPECT_EQ(PopFront(str("test"), 100), str(""));
|
||||
}
|
||||
|
||||
TEST(StringViewTest, ParsePositiveNumber) {
|
||||
EXPECT_EQ(ParsePositiveNumber(str("42")), 42);
|
||||
EXPECT_EQ(ParsePositiveNumber(str("0x2a")), 42);
|
||||
EXPECT_EQ(ParsePositiveNumber(str("0x2A")), 42);
|
||||
|
||||
EXPECT_EQ(ParsePositiveNumber(str("-0x2A")), -1);
|
||||
EXPECT_EQ(ParsePositiveNumber(str("abc")), -1);
|
||||
EXPECT_EQ(ParsePositiveNumber(str("")), -1);
|
||||
}
|
||||
|
||||
TEST(StringViewTest, CopyString) {
|
||||
char buf[4];
|
||||
buf[0] = 'X';
|
||||
|
||||
// Empty
|
||||
CopyString(str(""), buf, sizeof(buf));
|
||||
EXPECT_STREQ(buf, "");
|
||||
|
||||
// Less
|
||||
CopyString(str("a"), buf, sizeof(buf));
|
||||
EXPECT_STREQ(buf, "a");
|
||||
|
||||
// exact
|
||||
CopyString(str("abc"), buf, sizeof(buf));
|
||||
EXPECT_STREQ(buf, "abc");
|
||||
|
||||
// More
|
||||
CopyString(str("abcd"), buf, sizeof(buf));
|
||||
EXPECT_STREQ(buf, "abc");
|
||||
}
|
||||
|
||||
TEST(StringViewTest, HasWord) {
|
||||
// Find flags at beginning, middle and end.
|
||||
EXPECT_TRUE(HasWord(str("first middle last"), "first"));
|
||||
EXPECT_TRUE(HasWord(str("first middle last"), "middle"));
|
||||
EXPECT_TRUE(HasWord(str("first middle last"), "last"));
|
||||
// Do not match partial flags
|
||||
EXPECT_FALSE(HasWord(str("first middle last"), "irst"));
|
||||
EXPECT_FALSE(HasWord(str("first middle last"), "mid"));
|
||||
EXPECT_FALSE(HasWord(str("first middle last"), "las"));
|
||||
}
|
||||
|
||||
TEST(StringViewTest, GetAttributeKeyValue) {
|
||||
const StringView line = str(" key : first middle last ");
|
||||
StringView key, value;
|
||||
EXPECT_TRUE(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(GetAttributeKeyValue(line, &key, &value));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpu_features
|
Reference in New Issue
Block a user