aboutsummaryrefslogtreecommitdiff
path: root/unittests/Support
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:01:22 +0000
commit71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch)
tree5343938942df402b49ec7300a1c25a2d4ccd5821 /unittests/Support
parent31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff)
Diffstat (limited to 'unittests/Support')
-rw-r--r--unittests/Support/ARMAttributeParser.cpp385
-rw-r--r--unittests/Support/AllocatorTest.cpp6
-rw-r--r--unittests/Support/BinaryStreamTest.cpp711
-rw-r--r--unittests/Support/CMakeLists.txt5
-rw-r--r--unittests/Support/CachePruningTest.cpp71
-rw-r--r--unittests/Support/Casting.cpp75
-rw-r--r--unittests/Support/Chrono.cpp31
-rw-r--r--unittests/Support/CommandLineTest.cpp76
-rw-r--r--unittests/Support/CompressionTest.cpp17
-rw-r--r--unittests/Support/ErrorTest.cpp28
-rw-r--r--unittests/Support/FormatVariadicTest.cpp2
-rw-r--r--unittests/Support/Host.cpp92
-rw-r--r--unittests/Support/LEB128Test.cpp47
-rw-r--r--unittests/Support/MD5Test.cpp4
-rw-r--r--unittests/Support/Path.cpp570
-rw-r--r--unittests/Support/ProgramTest.cpp1
-rw-r--r--unittests/Support/TargetParserTest.cpp73
-rw-r--r--unittests/Support/ThreadPool.cpp4
-rw-r--r--unittests/Support/TrailingObjectsTest.cpp21
-rw-r--r--unittests/Support/YAMLIOTest.cpp16
-rw-r--r--unittests/Support/raw_ostream_test.cpp8
21 files changed, 2072 insertions, 171 deletions
diff --git a/unittests/Support/ARMAttributeParser.cpp b/unittests/Support/ARMAttributeParser.cpp
new file mode 100644
index 000000000000..c2df6537ff63
--- /dev/null
+++ b/unittests/Support/ARMAttributeParser.cpp
@@ -0,0 +1,385 @@
+#include "llvm/Support/ARMBuildAttributes.h"
+#include "llvm/Support/ARMAttributeParser.h"
+#include "llvm/Support/LEB128.h"
+#include "gtest/gtest.h"
+#include <string>
+
+using namespace llvm;
+
+struct AttributeSection {
+ unsigned Tag;
+ unsigned Value;
+
+ AttributeSection(unsigned tag, unsigned value) : Tag(tag), Value(value) { }
+
+ void write(raw_ostream &OS) {
+ OS.flush();
+ // length = length + "aeabi\0" + TagFile + ByteSize + Tag + Value;
+ // length = 17 bytes
+
+ OS << 'A' << (uint8_t)17 << (uint8_t)0 << (uint8_t)0 << (uint8_t)0;
+ OS << "aeabi" << '\0';
+ OS << (uint8_t)1 << (uint8_t)7 << (uint8_t)0 << (uint8_t)0 << (uint8_t)0;
+ OS << (uint8_t)Tag << (uint8_t)Value;
+
+ }
+};
+
+bool testBuildAttr(unsigned Tag, unsigned Value,
+ unsigned ExpectedTag, unsigned ExpectedValue) {
+ std::string buffer;
+ raw_string_ostream OS(buffer);
+ AttributeSection Section(Tag, Value);
+ Section.write(OS);
+ ArrayRef<uint8_t> Bytes(
+ reinterpret_cast<const uint8_t*>(OS.str().c_str()), OS.str().size());
+
+ ARMAttributeParser Parser;
+ Parser.Parse(Bytes, true);
+
+ return (Parser.hasAttribute(ExpectedTag) &&
+ Parser.getAttributeValue(ExpectedTag) == ExpectedValue);
+}
+
+bool testTagString(unsigned Tag, const char *name) {
+ return ARMBuildAttrs::AttrTypeAsString(Tag).str() == name;
+}
+
+TEST(CPUArchBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(6, "Tag_CPU_arch"));
+
+ EXPECT_TRUE(testBuildAttr(6, 0, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::Pre_v4));
+ EXPECT_TRUE(testBuildAttr(6, 1, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v4));
+ EXPECT_TRUE(testBuildAttr(6, 2, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v4T));
+ EXPECT_TRUE(testBuildAttr(6, 3, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v5T));
+ EXPECT_TRUE(testBuildAttr(6, 4, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v5TE));
+ EXPECT_TRUE(testBuildAttr(6, 5, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v5TEJ));
+ EXPECT_TRUE(testBuildAttr(6, 6, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v6));
+ EXPECT_TRUE(testBuildAttr(6, 7, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v6KZ));
+ EXPECT_TRUE(testBuildAttr(6, 8, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v6T2));
+ EXPECT_TRUE(testBuildAttr(6, 9, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v6K));
+ EXPECT_TRUE(testBuildAttr(6, 10, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v7));
+ EXPECT_TRUE(testBuildAttr(6, 11, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v6_M));
+ EXPECT_TRUE(testBuildAttr(6, 12, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v6S_M));
+ EXPECT_TRUE(testBuildAttr(6, 13, ARMBuildAttrs::CPU_arch,
+ ARMBuildAttrs::v7E_M));
+}
+
+TEST(CPUArchProfileBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(7, "Tag_CPU_arch_profile"));
+ EXPECT_TRUE(testBuildAttr(7, 'A', ARMBuildAttrs::CPU_arch_profile,
+ ARMBuildAttrs::ApplicationProfile));
+ EXPECT_TRUE(testBuildAttr(7, 'R', ARMBuildAttrs::CPU_arch_profile,
+ ARMBuildAttrs::RealTimeProfile));
+ EXPECT_TRUE(testBuildAttr(7, 'M', ARMBuildAttrs::CPU_arch_profile,
+ ARMBuildAttrs::MicroControllerProfile));
+ EXPECT_TRUE(testBuildAttr(7, 'S', ARMBuildAttrs::CPU_arch_profile,
+ ARMBuildAttrs::SystemProfile));
+}
+
+TEST(ARMISABuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(8, "Tag_ARM_ISA_use"));
+ EXPECT_TRUE(testBuildAttr(8, 0, ARMBuildAttrs::ARM_ISA_use,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(8, 1, ARMBuildAttrs::ARM_ISA_use,
+ ARMBuildAttrs::Allowed));
+}
+
+TEST(ThumbISABuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(9, "Tag_THUMB_ISA_use"));
+ EXPECT_TRUE(testBuildAttr(9, 0, ARMBuildAttrs::THUMB_ISA_use,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(9, 1, ARMBuildAttrs::THUMB_ISA_use,
+ ARMBuildAttrs::Allowed));
+}
+
+TEST(FPArchBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(10, "Tag_FP_arch"));
+ EXPECT_TRUE(testBuildAttr(10, 0, ARMBuildAttrs::FP_arch,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(10, 1, ARMBuildAttrs::FP_arch,
+ ARMBuildAttrs::Allowed));
+ EXPECT_TRUE(testBuildAttr(10, 2, ARMBuildAttrs::FP_arch,
+ ARMBuildAttrs::AllowFPv2));
+ EXPECT_TRUE(testBuildAttr(10, 3, ARMBuildAttrs::FP_arch,
+ ARMBuildAttrs::AllowFPv3A));
+ EXPECT_TRUE(testBuildAttr(10, 4, ARMBuildAttrs::FP_arch,
+ ARMBuildAttrs::AllowFPv3B));
+ EXPECT_TRUE(testBuildAttr(10, 5, ARMBuildAttrs::FP_arch,
+ ARMBuildAttrs::AllowFPv4A));
+ EXPECT_TRUE(testBuildAttr(10, 6, ARMBuildAttrs::FP_arch,
+ ARMBuildAttrs::AllowFPv4B));
+ EXPECT_TRUE(testBuildAttr(10, 7, ARMBuildAttrs::FP_arch,
+ ARMBuildAttrs::AllowFPARMv8A));
+ EXPECT_TRUE(testBuildAttr(10, 8, ARMBuildAttrs::FP_arch,
+ ARMBuildAttrs::AllowFPARMv8B));
+}
+
+TEST(WMMXBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(11, "Tag_WMMX_arch"));
+ EXPECT_TRUE(testBuildAttr(11, 0, ARMBuildAttrs::WMMX_arch,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(11, 1, ARMBuildAttrs::WMMX_arch,
+ ARMBuildAttrs::AllowWMMXv1));
+ EXPECT_TRUE(testBuildAttr(11, 2, ARMBuildAttrs::WMMX_arch,
+ ARMBuildAttrs::AllowWMMXv2));
+}
+
+TEST(SIMDBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(12, "Tag_Advanced_SIMD_arch"));
+ EXPECT_TRUE(testBuildAttr(12, 0, ARMBuildAttrs::Advanced_SIMD_arch,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(12, 1, ARMBuildAttrs::Advanced_SIMD_arch,
+ ARMBuildAttrs::AllowNeon));
+ EXPECT_TRUE(testBuildAttr(12, 2, ARMBuildAttrs::Advanced_SIMD_arch,
+ ARMBuildAttrs::AllowNeon2));
+ EXPECT_TRUE(testBuildAttr(12, 3, ARMBuildAttrs::Advanced_SIMD_arch,
+ ARMBuildAttrs::AllowNeonARMv8));
+ EXPECT_TRUE(testBuildAttr(12, 4, ARMBuildAttrs::Advanced_SIMD_arch,
+ ARMBuildAttrs::AllowNeonARMv8_1a));
+}
+
+TEST(FPHPBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(36, "Tag_FP_HP_extension"));
+ EXPECT_TRUE(testBuildAttr(36, 0, ARMBuildAttrs::FP_HP_extension,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(36, 1, ARMBuildAttrs::FP_HP_extension,
+ ARMBuildAttrs::AllowHPFP));
+}
+
+TEST(CPUAlignBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(34, "Tag_CPU_unaligned_access"));
+ EXPECT_TRUE(testBuildAttr(34, 0, ARMBuildAttrs::CPU_unaligned_access,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(34, 1, ARMBuildAttrs::CPU_unaligned_access,
+ ARMBuildAttrs::Allowed));
+}
+
+TEST(T2EEBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(66, "Tag_T2EE_use"));
+ EXPECT_TRUE(testBuildAttr(66, 0, ARMBuildAttrs::T2EE_use,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(66, 1, ARMBuildAttrs::T2EE_use,
+ ARMBuildAttrs::Allowed));
+}
+
+TEST(VirtualizationBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(68, "Tag_Virtualization_use"));
+ EXPECT_TRUE(testBuildAttr(68, 0, ARMBuildAttrs::Virtualization_use,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(68, 1, ARMBuildAttrs::Virtualization_use,
+ ARMBuildAttrs::AllowTZ));
+ EXPECT_TRUE(testBuildAttr(68, 2, ARMBuildAttrs::Virtualization_use,
+ ARMBuildAttrs::AllowVirtualization));
+ EXPECT_TRUE(testBuildAttr(68, 3, ARMBuildAttrs::Virtualization_use,
+ ARMBuildAttrs::AllowTZVirtualization));
+}
+
+TEST(MPBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(42, "Tag_MPextension_use"));
+ EXPECT_TRUE(testBuildAttr(42, 0, ARMBuildAttrs::MPextension_use,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(42, 1, ARMBuildAttrs::MPextension_use,
+ ARMBuildAttrs::AllowMP));
+}
+
+TEST(DivBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(44, "Tag_DIV_use"));
+ EXPECT_TRUE(testBuildAttr(44, 0, ARMBuildAttrs::DIV_use,
+ ARMBuildAttrs::AllowDIVIfExists));
+ EXPECT_TRUE(testBuildAttr(44, 1, ARMBuildAttrs::DIV_use,
+ ARMBuildAttrs::DisallowDIV));
+ EXPECT_TRUE(testBuildAttr(44, 2, ARMBuildAttrs::DIV_use,
+ ARMBuildAttrs::AllowDIVExt));
+}
+
+TEST(PCS_ConfigBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(13, "Tag_PCS_config"));
+ EXPECT_TRUE(testBuildAttr(13, 0, ARMBuildAttrs::PCS_config, 0));
+ EXPECT_TRUE(testBuildAttr(13, 1, ARMBuildAttrs::PCS_config, 1));
+ EXPECT_TRUE(testBuildAttr(13, 2, ARMBuildAttrs::PCS_config, 2));
+ EXPECT_TRUE(testBuildAttr(13, 3, ARMBuildAttrs::PCS_config, 3));
+ EXPECT_TRUE(testBuildAttr(13, 4, ARMBuildAttrs::PCS_config, 4));
+ EXPECT_TRUE(testBuildAttr(13, 5, ARMBuildAttrs::PCS_config, 5));
+ EXPECT_TRUE(testBuildAttr(13, 6, ARMBuildAttrs::PCS_config, 6));
+ EXPECT_TRUE(testBuildAttr(13, 7, ARMBuildAttrs::PCS_config, 7));
+}
+
+TEST(PCS_R9BuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(14, "Tag_ABI_PCS_R9_use"));
+ EXPECT_TRUE(testBuildAttr(14, 0, ARMBuildAttrs::ABI_PCS_R9_use,
+ ARMBuildAttrs::R9IsGPR));
+ EXPECT_TRUE(testBuildAttr(14, 1, ARMBuildAttrs::ABI_PCS_R9_use,
+ ARMBuildAttrs::R9IsSB));
+ EXPECT_TRUE(testBuildAttr(14, 2, ARMBuildAttrs::ABI_PCS_R9_use,
+ ARMBuildAttrs::R9IsTLSPointer));
+ EXPECT_TRUE(testBuildAttr(14, 3, ARMBuildAttrs::ABI_PCS_R9_use,
+ ARMBuildAttrs::R9Reserved));
+}
+
+TEST(PCS_RWBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(15, "Tag_ABI_PCS_RW_data"));
+ EXPECT_TRUE(testBuildAttr(15, 0, ARMBuildAttrs::ABI_PCS_RW_data,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(15, 1, ARMBuildAttrs::ABI_PCS_RW_data,
+ ARMBuildAttrs::AddressRWPCRel));
+ EXPECT_TRUE(testBuildAttr(15, 2, ARMBuildAttrs::ABI_PCS_RW_data,
+ ARMBuildAttrs::AddressRWSBRel));
+ EXPECT_TRUE(testBuildAttr(15, 3, ARMBuildAttrs::ABI_PCS_RW_data,
+ ARMBuildAttrs::AddressRWNone));
+}
+
+TEST(PCS_ROBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(16, "Tag_ABI_PCS_RO_data"));
+ EXPECT_TRUE(testBuildAttr(16, 0, ARMBuildAttrs::ABI_PCS_RO_data,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(16, 1, ARMBuildAttrs::ABI_PCS_RO_data,
+ ARMBuildAttrs::AddressROPCRel));
+ EXPECT_TRUE(testBuildAttr(16, 2, ARMBuildAttrs::ABI_PCS_RO_data,
+ ARMBuildAttrs::AddressRONone));
+}
+
+TEST(PCS_GOTBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(17, "Tag_ABI_PCS_GOT_use"));
+ EXPECT_TRUE(testBuildAttr(17, 0, ARMBuildAttrs::ABI_PCS_GOT_use,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(17, 1, ARMBuildAttrs::ABI_PCS_GOT_use,
+ ARMBuildAttrs::AddressDirect));
+ EXPECT_TRUE(testBuildAttr(17, 2, ARMBuildAttrs::ABI_PCS_GOT_use,
+ ARMBuildAttrs::AddressGOT));
+}
+
+TEST(PCS_WCharBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(18, "Tag_ABI_PCS_wchar_t"));
+ EXPECT_TRUE(testBuildAttr(18, 0, ARMBuildAttrs::ABI_PCS_wchar_t,
+ ARMBuildAttrs::WCharProhibited));
+ EXPECT_TRUE(testBuildAttr(18, 2, ARMBuildAttrs::ABI_PCS_wchar_t,
+ ARMBuildAttrs::WCharWidth2Bytes));
+ EXPECT_TRUE(testBuildAttr(18, 4, ARMBuildAttrs::ABI_PCS_wchar_t,
+ ARMBuildAttrs::WCharWidth4Bytes));
+}
+
+TEST(EnumSizeBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(26, "Tag_ABI_enum_size"));
+ EXPECT_TRUE(testBuildAttr(26, 0, ARMBuildAttrs::ABI_enum_size,
+ ARMBuildAttrs::EnumProhibited));
+ EXPECT_TRUE(testBuildAttr(26, 1, ARMBuildAttrs::ABI_enum_size,
+ ARMBuildAttrs::EnumSmallest));
+ EXPECT_TRUE(testBuildAttr(26, 2, ARMBuildAttrs::ABI_enum_size,
+ ARMBuildAttrs::Enum32Bit));
+ EXPECT_TRUE(testBuildAttr(26, 3, ARMBuildAttrs::ABI_enum_size,
+ ARMBuildAttrs::Enum32BitABI));
+}
+
+TEST(AlignNeededBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(24, "Tag_ABI_align_needed"));
+ EXPECT_TRUE(testBuildAttr(24, 0, ARMBuildAttrs::ABI_align_needed,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(24, 1, ARMBuildAttrs::ABI_align_needed,
+ ARMBuildAttrs::Align8Byte));
+ EXPECT_TRUE(testBuildAttr(24, 2, ARMBuildAttrs::ABI_align_needed,
+ ARMBuildAttrs::Align4Byte));
+ EXPECT_TRUE(testBuildAttr(24, 3, ARMBuildAttrs::ABI_align_needed,
+ ARMBuildAttrs::AlignReserved));
+}
+
+TEST(AlignPreservedBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(25, "Tag_ABI_align_preserved"));
+ EXPECT_TRUE(testBuildAttr(25, 0, ARMBuildAttrs::ABI_align_preserved,
+ ARMBuildAttrs::AlignNotPreserved));
+ EXPECT_TRUE(testBuildAttr(25, 1, ARMBuildAttrs::ABI_align_preserved,
+ ARMBuildAttrs::AlignPreserve8Byte));
+ EXPECT_TRUE(testBuildAttr(25, 2, ARMBuildAttrs::ABI_align_preserved,
+ ARMBuildAttrs::AlignPreserveAll));
+ EXPECT_TRUE(testBuildAttr(25, 3, ARMBuildAttrs::ABI_align_preserved,
+ ARMBuildAttrs::AlignReserved));
+}
+
+TEST(FPRoundingBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(19, "Tag_ABI_FP_rounding"));
+ EXPECT_TRUE(testBuildAttr(19, 0, ARMBuildAttrs::ABI_FP_rounding, 0));
+ EXPECT_TRUE(testBuildAttr(19, 1, ARMBuildAttrs::ABI_FP_rounding, 1));
+}
+
+TEST(FPDenormalBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(20, "Tag_ABI_FP_denormal"));
+ EXPECT_TRUE(testBuildAttr(20, 0, ARMBuildAttrs::ABI_FP_denormal,
+ ARMBuildAttrs::PositiveZero));
+ EXPECT_TRUE(testBuildAttr(20, 1, ARMBuildAttrs::ABI_FP_denormal,
+ ARMBuildAttrs::IEEEDenormals));
+ EXPECT_TRUE(testBuildAttr(20, 2, ARMBuildAttrs::ABI_FP_denormal,
+ ARMBuildAttrs::PreserveFPSign));
+}
+
+TEST(FPExceptionsBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(21, "Tag_ABI_FP_exceptions"));
+ EXPECT_TRUE(testBuildAttr(21, 0, ARMBuildAttrs::ABI_FP_exceptions, 0));
+ EXPECT_TRUE(testBuildAttr(21, 1, ARMBuildAttrs::ABI_FP_exceptions, 1));
+}
+
+TEST(FPUserExceptionsBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(22, "Tag_ABI_FP_user_exceptions"));
+ EXPECT_TRUE(testBuildAttr(22, 0, ARMBuildAttrs::ABI_FP_user_exceptions, 0));
+ EXPECT_TRUE(testBuildAttr(22, 1, ARMBuildAttrs::ABI_FP_user_exceptions, 1));
+}
+
+TEST(FPNumberModelBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(23, "Tag_ABI_FP_number_model"));
+ EXPECT_TRUE(testBuildAttr(23, 0, ARMBuildAttrs::ABI_FP_number_model,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(23, 1, ARMBuildAttrs::ABI_FP_number_model,
+ ARMBuildAttrs::AllowIEEENormal));
+ EXPECT_TRUE(testBuildAttr(23, 2, ARMBuildAttrs::ABI_FP_number_model,
+ ARMBuildAttrs::AllowRTABI));
+ EXPECT_TRUE(testBuildAttr(23, 3, ARMBuildAttrs::ABI_FP_number_model,
+ ARMBuildAttrs::AllowIEEE754));
+}
+
+TEST(FP16BuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(38, "Tag_ABI_FP_16bit_format"));
+ EXPECT_TRUE(testBuildAttr(38, 0, ARMBuildAttrs::ABI_FP_16bit_format,
+ ARMBuildAttrs::Not_Allowed));
+ EXPECT_TRUE(testBuildAttr(38, 1, ARMBuildAttrs::ABI_FP_16bit_format,
+ ARMBuildAttrs::FP16FormatIEEE));
+ EXPECT_TRUE(testBuildAttr(38, 2, ARMBuildAttrs::ABI_FP_16bit_format,
+ ARMBuildAttrs::FP16VFP3));
+}
+
+TEST(HardFPBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(27, "Tag_ABI_HardFP_use"));
+ EXPECT_TRUE(testBuildAttr(27, 0, ARMBuildAttrs::ABI_HardFP_use,
+ ARMBuildAttrs::HardFPImplied));
+ EXPECT_TRUE(testBuildAttr(27, 1, ARMBuildAttrs::ABI_HardFP_use,
+ ARMBuildAttrs::HardFPSinglePrecision));
+ EXPECT_TRUE(testBuildAttr(27, 2, ARMBuildAttrs::ABI_HardFP_use, 2));
+}
+
+TEST(VFPArgsBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(28, "Tag_ABI_VFP_args"));
+ EXPECT_TRUE(testBuildAttr(28, 0, ARMBuildAttrs::ABI_VFP_args,
+ ARMBuildAttrs::BaseAAPCS));
+ EXPECT_TRUE(testBuildAttr(28, 1, ARMBuildAttrs::ABI_VFP_args,
+ ARMBuildAttrs::HardFPAAPCS));
+ EXPECT_TRUE(testBuildAttr(28, 2, ARMBuildAttrs::ABI_VFP_args, 2));
+ EXPECT_TRUE(testBuildAttr(28, 3, ARMBuildAttrs::ABI_VFP_args, 3));
+}
+
+TEST(WMMXArgsBuildAttr, testBuildAttr) {
+ EXPECT_TRUE(testTagString(29, "Tag_ABI_WMMX_args"));
+ EXPECT_TRUE(testBuildAttr(29, 0, ARMBuildAttrs::ABI_WMMX_args, 0));
+ EXPECT_TRUE(testBuildAttr(29, 1, ARMBuildAttrs::ABI_WMMX_args, 1));
+ EXPECT_TRUE(testBuildAttr(29, 2, ARMBuildAttrs::ABI_WMMX_args, 2));
+}
diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp
index 4b544641e9bf..4897c47eb28b 100644
--- a/unittests/Support/AllocatorTest.cpp
+++ b/unittests/Support/AllocatorTest.cpp
@@ -17,9 +17,9 @@ namespace {
TEST(AllocatorTest, Basics) {
BumpPtrAllocator Alloc;
- int *a = (int*)Alloc.Allocate(sizeof(int), 1);
- int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 1);
- int *c = (int*)Alloc.Allocate(sizeof(int), 1);
+ int *a = (int*)Alloc.Allocate(sizeof(int), alignof(int));
+ int *b = (int*)Alloc.Allocate(sizeof(int) * 10, alignof(int));
+ int *c = (int*)Alloc.Allocate(sizeof(int), alignof(int));
*a = 1;
b[0] = 2;
b[9] = 2;
diff --git a/unittests/Support/BinaryStreamTest.cpp b/unittests/Support/BinaryStreamTest.cpp
new file mode 100644
index 000000000000..1e646a6cf900
--- /dev/null
+++ b/unittests/Support/BinaryStreamTest.cpp
@@ -0,0 +1,711 @@
+//===- llvm/unittest/Support/BinaryStreamTest.cpp -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryItemStream.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "gtest/gtest.h"
+
+#include <unordered_map>
+
+using namespace llvm;
+using namespace llvm::support;
+
+#define EXPECT_NO_ERROR(Err) \
+ { \
+ auto E = Err; \
+ EXPECT_FALSE(static_cast<bool>(E)); \
+ if (E) \
+ consumeError(std::move(E)); \
+ }
+
+#define ASSERT_NO_ERROR(Err) \
+ { \
+ auto E = Err; \
+ ASSERT_FALSE(static_cast<bool>(E)); \
+ if (E) \
+ consumeError(std::move(E)); \
+ }
+
+#define EXPECT_ERROR(Err) \
+ { \
+ auto E = Err; \
+ EXPECT_TRUE(static_cast<bool>(E)); \
+ if (E) \
+ consumeError(std::move(E)); \
+ }
+
+namespace {
+
+class BrokenStream : public WritableBinaryStream {
+public:
+ BrokenStream(MutableArrayRef<uint8_t> Data, endianness Endian,
+ uint32_t Align)
+ : Data(Data), PartitionIndex(alignDown(Data.size() / 2, Align)),
+ Endian(Endian) {}
+
+ endianness getEndian() const override { return Endian; }
+
+ Error readBytes(uint32_t Offset, uint32_t Size,
+ ArrayRef<uint8_t> &Buffer) override {
+ if (auto EC = checkOffset(Offset, Size))
+ return EC;
+ uint32_t S = startIndex(Offset);
+ auto Ref = Data.drop_front(S);
+ if (Ref.size() >= Size) {
+ Buffer = Ref.take_front(Size);
+ return Error::success();
+ }
+
+ uint32_t BytesLeft = Size - Ref.size();
+ uint8_t *Ptr = Allocator.Allocate<uint8_t>(Size);
+ ::memcpy(Ptr, Ref.data(), Ref.size());
+ ::memcpy(Ptr + Ref.size(), Data.data(), BytesLeft);
+ Buffer = makeArrayRef<uint8_t>(Ptr, Size);
+ return Error::success();
+ }
+
+ Error readLongestContiguousChunk(uint32_t Offset,
+ ArrayRef<uint8_t> &Buffer) override {
+ if (auto EC = checkOffset(Offset, 1))
+ return EC;
+ uint32_t S = startIndex(Offset);
+ Buffer = Data.drop_front(S);
+ return Error::success();
+ }
+
+ uint32_t getLength() override { return Data.size(); }
+
+ Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> SrcData) override {
+ if (auto EC = checkOffset(Offset, SrcData.size()))
+ return EC;
+ if (SrcData.empty())
+ return Error::success();
+
+ uint32_t S = startIndex(Offset);
+ MutableArrayRef<uint8_t> Ref(Data);
+ Ref = Ref.drop_front(S);
+ if (Ref.size() >= SrcData.size()) {
+ ::memcpy(Ref.data(), SrcData.data(), SrcData.size());
+ return Error::success();
+ }
+
+ uint32_t BytesLeft = SrcData.size() - Ref.size();
+ ::memcpy(Ref.data(), SrcData.data(), Ref.size());
+ ::memcpy(&Data[0], SrcData.data() + Ref.size(), BytesLeft);
+ return Error::success();
+ }
+ Error commit() override { return Error::success(); }
+
+private:
+ uint32_t startIndex(uint32_t Offset) const {
+ return (Offset + PartitionIndex) % Data.size();
+ }
+
+ uint32_t endIndex(uint32_t Offset, uint32_t Size) const {
+ return (startIndex(Offset) + Size - 1) % Data.size();
+ }
+
+ // Buffer is organized like this:
+ // -------------------------------------------------
+ // | N/2 | N/2+1 | ... | N-1 | 0 | 1 | ... | N-2-1 |
+ // -------------------------------------------------
+ // So reads from the beginning actually come from the middle.
+ MutableArrayRef<uint8_t> Data;
+ uint32_t PartitionIndex = 0;
+ endianness Endian;
+ BumpPtrAllocator Allocator;
+};
+
+constexpr endianness Endians[] = {big, little, native};
+constexpr uint32_t NumEndians = llvm::array_lengthof(Endians);
+constexpr uint32_t NumStreams = 2 * NumEndians;
+
+class BinaryStreamTest : public testing::Test {
+
+public:
+ BinaryStreamTest() {}
+
+ void SetUp() override {
+ Streams.clear();
+ Streams.resize(NumStreams);
+ for (uint32_t I = 0; I < NumStreams; ++I)
+ Streams[I].IsContiguous = (I % 2 == 0);
+
+ InputData.clear();
+ OutputData.clear();
+ }
+
+protected:
+ struct StreamPair {
+ bool IsContiguous;
+ std::unique_ptr<BinaryStream> Input;
+ std::unique_ptr<WritableBinaryStream> Output;
+ };
+
+ void initializeInput(ArrayRef<uint8_t> Input, uint32_t Align) {
+ InputData = Input;
+
+ BrokenInputData.resize(InputData.size());
+ if (!Input.empty()) {
+ uint32_t PartitionIndex = alignDown(InputData.size() / 2, Align);
+ uint32_t RightBytes = InputData.size() - PartitionIndex;
+ uint32_t LeftBytes = PartitionIndex;
+ if (RightBytes > 0)
+ ::memcpy(&BrokenInputData[PartitionIndex], Input.data(), RightBytes);
+ if (LeftBytes > 0)
+ ::memcpy(&BrokenInputData[0], Input.data() + RightBytes, LeftBytes);
+ }
+
+ for (uint32_t I = 0; I < NumEndians; ++I) {
+ auto InByteStream =
+ llvm::make_unique<BinaryByteStream>(InputData, Endians[I]);
+ auto InBrokenStream = llvm::make_unique<BrokenStream>(
+ BrokenInputData, Endians[I], Align);
+
+ Streams[I * 2].Input = std::move(InByteStream);
+ Streams[I * 2 + 1].Input = std::move(InBrokenStream);
+ }
+ }
+
+ void initializeOutput(uint32_t Size, uint32_t Align) {
+ OutputData.resize(Size);
+ BrokenOutputData.resize(Size);
+
+ for (uint32_t I = 0; I < NumEndians; ++I) {
+ Streams[I * 2].Output =
+ llvm::make_unique<MutableBinaryByteStream>(OutputData, Endians[I]);
+ Streams[I * 2 + 1].Output = llvm::make_unique<BrokenStream>(
+ BrokenOutputData, Endians[I], Align);
+ }
+ }
+
+ void initializeOutputFromInput(uint32_t Align) {
+ for (uint32_t I = 0; I < NumEndians; ++I) {
+ Streams[I * 2].Output =
+ llvm::make_unique<MutableBinaryByteStream>(InputData, Endians[I]);
+ Streams[I * 2 + 1].Output = llvm::make_unique<BrokenStream>(
+ BrokenInputData, Endians[I], Align);
+ }
+ }
+
+ void initializeInputFromOutput(uint32_t Align) {
+ for (uint32_t I = 0; I < NumEndians; ++I) {
+ Streams[I * 2].Input =
+ llvm::make_unique<BinaryByteStream>(OutputData, Endians[I]);
+ Streams[I * 2 + 1].Input = llvm::make_unique<BrokenStream>(
+ BrokenOutputData, Endians[I], Align);
+ }
+ }
+
+ std::vector<uint8_t> InputData;
+ std::vector<uint8_t> BrokenInputData;
+
+ std::vector<uint8_t> OutputData;
+ std::vector<uint8_t> BrokenOutputData;
+
+ std::vector<StreamPair> Streams;
+};
+
+// Tests that a we can read from a BinaryByteStream without a StreamReader.
+TEST_F(BinaryStreamTest, BinaryByteStreamBounds) {
+ std::vector<uint8_t> InputData = {1, 2, 3, 4, 5};
+ initializeInput(InputData, 1);
+
+ for (auto &Stream : Streams) {
+ ArrayRef<uint8_t> Buffer;
+
+ // 1. If the read fits it should work.
+ ASSERT_EQ(InputData.size(), Stream.Input->getLength());
+ ASSERT_NO_ERROR(Stream.Input->readBytes(2, 1, Buffer));
+ EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer);
+ ASSERT_NO_ERROR(Stream.Input->readBytes(0, 4, Buffer));
+ EXPECT_EQ(makeArrayRef(InputData).slice(0, 4), Buffer);
+
+ // 2. Reading past the bounds of the input should fail.
+ EXPECT_ERROR(Stream.Input->readBytes(4, 2, Buffer));
+ }
+}
+
+TEST_F(BinaryStreamTest, StreamRefBounds) {
+ std::vector<uint8_t> InputData = {1, 2, 3, 4, 5};
+ initializeInput(InputData, 1);
+
+ for (const auto &Stream : Streams) {
+ ArrayRef<uint8_t> Buffer;
+ BinaryStreamRef Ref(*Stream.Input);
+
+ // Read 1 byte from offset 2 should work
+ ASSERT_EQ(InputData.size(), Ref.getLength());
+ ASSERT_NO_ERROR(Ref.readBytes(2, 1, Buffer));
+ EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer);
+
+ // Reading everything from offset 2 on.
+ ASSERT_NO_ERROR(Ref.readLongestContiguousChunk(2, Buffer));
+ if (Stream.IsContiguous)
+ EXPECT_EQ(makeArrayRef(InputData).slice(2), Buffer);
+ else
+ EXPECT_FALSE(Buffer.empty());
+
+ // Reading 6 bytes from offset 0 is too big.
+ EXPECT_ERROR(Ref.readBytes(0, 6, Buffer));
+ EXPECT_ERROR(Ref.readLongestContiguousChunk(6, Buffer));
+
+ // Reading 1 byte from offset 2 after dropping 1 byte is the same as reading
+ // 1 byte from offset 3.
+ Ref = Ref.drop_front(1);
+ ASSERT_NO_ERROR(Ref.readBytes(2, 1, Buffer));
+ if (Stream.IsContiguous)
+ EXPECT_EQ(makeArrayRef(InputData).slice(3, 1), Buffer);
+ else
+ EXPECT_FALSE(Buffer.empty());
+
+ // Reading everything from offset 2 on after dropping 1 byte.
+ ASSERT_NO_ERROR(Ref.readLongestContiguousChunk(2, Buffer));
+ if (Stream.IsContiguous)
+ EXPECT_EQ(makeArrayRef(InputData).slice(3), Buffer);
+ else
+ EXPECT_FALSE(Buffer.empty());
+
+ // Reading 2 bytes from offset 2 after dropping 2 bytes is the same as
+ // reading 2 bytes from offset 4, and should fail.
+ Ref = Ref.drop_front(1);
+ EXPECT_ERROR(Ref.readBytes(2, 2, Buffer));
+
+ // But if we read the longest contiguous chunk instead, we should still
+ // get the 1 byte at the end.
+ ASSERT_NO_ERROR(Ref.readLongestContiguousChunk(2, Buffer));
+ EXPECT_EQ(makeArrayRef(InputData).take_back(), Buffer);
+ }
+}
+
+// Test that we can write to a BinaryStream without a StreamWriter.
+TEST_F(BinaryStreamTest, MutableBinaryByteStreamBounds) {
+ std::vector<uint8_t> InputData = {'T', 'e', 's', 't', '\0'};
+ initializeInput(InputData, 1);
+ initializeOutput(InputData.size(), 1);
+
+ // For every combination of input stream and output stream.
+ for (auto &Stream : Streams) {
+ MutableArrayRef<uint8_t> Buffer;
+ ASSERT_EQ(InputData.size(), Stream.Input->getLength());
+
+ // 1. Try two reads that are supposed to work. One from offset 0, and one
+ // from the middle.
+ uint32_t Offsets[] = {0, 3};
+ for (auto Offset : Offsets) {
+ uint32_t ExpectedSize = Stream.Input->getLength() - Offset;
+
+ // Read everything from Offset until the end of the input data.
+ ArrayRef<uint8_t> Data;
+ ASSERT_NO_ERROR(Stream.Input->readBytes(Offset, ExpectedSize, Data));
+ ASSERT_EQ(ExpectedSize, Data.size());
+
+ // Then write it to the destination.
+ ASSERT_NO_ERROR(Stream.Output->writeBytes(0, Data));
+
+ // Then we read back what we wrote, it should match the corresponding
+ // slice of the original input data.
+ ArrayRef<uint8_t> Data2;
+ ASSERT_NO_ERROR(Stream.Output->readBytes(Offset, ExpectedSize, Data2));
+ EXPECT_EQ(makeArrayRef(InputData).drop_front(Offset), Data2);
+ }
+
+ std::vector<uint8_t> BigData = {0, 1, 2, 3, 4};
+ // 2. If the write is too big, it should fail.
+ EXPECT_ERROR(Stream.Output->writeBytes(3, BigData));
+ }
+}
+
+// Test that FixedStreamArray works correctly.
+TEST_F(BinaryStreamTest, FixedStreamArray) {
+ std::vector<uint32_t> Ints = {90823, 12908, 109823, 209823};
+ ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(Ints.data()),
+ Ints.size() * sizeof(uint32_t));
+
+ initializeInput(IntBytes, alignof(uint32_t));
+
+ for (auto &Stream : Streams) {
+ MutableArrayRef<uint8_t> Buffer;
+ ASSERT_EQ(InputData.size(), Stream.Input->getLength());
+
+ FixedStreamArray<uint32_t> Array(*Stream.Input);
+ auto Iter = Array.begin();
+ ASSERT_EQ(Ints[0], *Iter++);
+ ASSERT_EQ(Ints[1], *Iter++);
+ ASSERT_EQ(Ints[2], *Iter++);
+ ASSERT_EQ(Ints[3], *Iter++);
+ ASSERT_EQ(Array.end(), Iter);
+ }
+}
+
+// Test that VarStreamArray works correctly.
+TEST_F(BinaryStreamTest, VarStreamArray) {
+ StringLiteral Strings("1. Test2. Longer Test3. Really Long Test4. Super "
+ "Extra Longest Test Of All");
+ ArrayRef<uint8_t> StringBytes(
+ reinterpret_cast<const uint8_t *>(Strings.data()), Strings.size());
+ initializeInput(StringBytes, 1);
+
+ struct StringExtractor {
+ public:
+ Error operator()(BinaryStreamRef Stream, uint32_t &Len, StringRef &Item) {
+ if (Index == 0)
+ Len = strlen("1. Test");
+ else if (Index == 1)
+ Len = strlen("2. Longer Test");
+ else if (Index == 2)
+ Len = strlen("3. Really Long Test");
+ else
+ Len = strlen("4. Super Extra Longest Test Of All");
+ ArrayRef<uint8_t> Bytes;
+ if (auto EC = Stream.readBytes(0, Len, Bytes))
+ return EC;
+ Item =
+ StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
+ ++Index;
+ return Error::success();
+ }
+
+ private:
+ uint32_t Index = 0;
+ };
+
+ for (auto &Stream : Streams) {
+ VarStreamArray<StringRef, StringExtractor> Array(*Stream.Input);
+ auto Iter = Array.begin();
+ ASSERT_EQ("1. Test", *Iter++);
+ ASSERT_EQ("2. Longer Test", *Iter++);
+ ASSERT_EQ("3. Really Long Test", *Iter++);
+ ASSERT_EQ("4. Super Extra Longest Test Of All", *Iter++);
+ ASSERT_EQ(Array.end(), Iter);
+ }
+}
+
+TEST_F(BinaryStreamTest, StreamReaderBounds) {
+ std::vector<uint8_t> Bytes;
+
+ initializeInput(Bytes, 1);
+ for (auto &Stream : Streams) {
+ StringRef S;
+ BinaryStreamReader Reader(*Stream.Input);
+ EXPECT_EQ(0U, Reader.bytesRemaining());
+ EXPECT_ERROR(Reader.readFixedString(S, 1));
+ }
+
+ Bytes.resize(5);
+ initializeInput(Bytes, 1);
+ for (auto &Stream : Streams) {
+ StringRef S;
+ BinaryStreamReader Reader(*Stream.Input);
+ EXPECT_EQ(Bytes.size(), Reader.bytesRemaining());
+ EXPECT_NO_ERROR(Reader.readFixedString(S, 5));
+ EXPECT_ERROR(Reader.readFixedString(S, 6));
+ }
+}
+
+TEST_F(BinaryStreamTest, StreamReaderIntegers) {
+ support::ulittle64_t Little{908234};
+ support::ubig32_t Big{28907823};
+ short NS = 2897;
+ int NI = -89723;
+ unsigned long NUL = 902309023UL;
+ constexpr uint32_t Size =
+ sizeof(Little) + sizeof(Big) + sizeof(NS) + sizeof(NI) + sizeof(NUL);
+
+ initializeOutput(Size, alignof(support::ulittle64_t));
+ initializeInputFromOutput(alignof(support::ulittle64_t));
+
+ for (auto &Stream : Streams) {
+ BinaryStreamWriter Writer(*Stream.Output);
+ ASSERT_NO_ERROR(Writer.writeObject(Little));
+ ASSERT_NO_ERROR(Writer.writeObject(Big));
+ ASSERT_NO_ERROR(Writer.writeInteger(NS));
+ ASSERT_NO_ERROR(Writer.writeInteger(NI));
+ ASSERT_NO_ERROR(Writer.writeInteger(NUL));
+
+ const support::ulittle64_t *Little2;
+ const support::ubig32_t *Big2;
+ short NS2;
+ int NI2;
+ unsigned long NUL2;
+
+ // 1. Reading fields individually.
+ BinaryStreamReader Reader(*Stream.Input);
+ ASSERT_NO_ERROR(Reader.readObject(Little2));
+ ASSERT_NO_ERROR(Reader.readObject(Big2));
+ ASSERT_NO_ERROR(Reader.readInteger(NS2));
+ ASSERT_NO_ERROR(Reader.readInteger(NI2));
+ ASSERT_NO_ERROR(Reader.readInteger(NUL2));
+ ASSERT_EQ(0U, Reader.bytesRemaining());
+
+ EXPECT_EQ(Little, *Little2);
+ EXPECT_EQ(Big, *Big2);
+ EXPECT_EQ(NS, NS2);
+ EXPECT_EQ(NI, NI2);
+ EXPECT_EQ(NUL, NUL2);
+ }
+}
+
+TEST_F(BinaryStreamTest, StreamReaderIntegerArray) {
+ // 1. Arrays of integers
+ std::vector<int> Ints = {1, 2, 3, 4, 5};
+ ArrayRef<uint8_t> IntBytes(reinterpret_cast<uint8_t *>(&Ints[0]),
+ Ints.size() * sizeof(int));
+
+ initializeInput(IntBytes, alignof(int));
+ for (auto &Stream : Streams) {
+ BinaryStreamReader Reader(*Stream.Input);
+ ArrayRef<int> IntsRef;
+ ASSERT_NO_ERROR(Reader.readArray(IntsRef, Ints.size()));
+ ASSERT_EQ(0U, Reader.bytesRemaining());
+ EXPECT_EQ(makeArrayRef(Ints), IntsRef);
+
+ Reader.setOffset(0);
+ FixedStreamArray<int> FixedIntsRef;
+ ASSERT_NO_ERROR(Reader.readArray(FixedIntsRef, Ints.size()));
+ ASSERT_EQ(0U, Reader.bytesRemaining());
+ ASSERT_EQ(Ints, std::vector<int>(FixedIntsRef.begin(), FixedIntsRef.end()));
+ }
+}
+
+TEST_F(BinaryStreamTest, StreamReaderEnum) {
+ enum class MyEnum : int64_t { Foo = -10, Bar = 0, Baz = 10 };
+
+ std::vector<MyEnum> Enums = {MyEnum::Bar, MyEnum::Baz, MyEnum::Foo};
+
+ initializeOutput(Enums.size() * sizeof(MyEnum), alignof(MyEnum));
+ initializeInputFromOutput(alignof(MyEnum));
+ for (auto &Stream : Streams) {
+ BinaryStreamWriter Writer(*Stream.Output);
+ for (auto Value : Enums)
+ ASSERT_NO_ERROR(Writer.writeEnum(Value));
+
+ BinaryStreamReader Reader(*Stream.Input);
+
+ ArrayRef<MyEnum> Array;
+ FixedStreamArray<MyEnum> FSA;
+
+ for (size_t I = 0; I < Enums.size(); ++I) {
+ MyEnum Value;
+ ASSERT_NO_ERROR(Reader.readEnum(Value));
+ EXPECT_EQ(Enums[I], Value);
+ }
+ ASSERT_EQ(0U, Reader.bytesRemaining());
+ }
+}
+
+TEST_F(BinaryStreamTest, StreamReaderObject) {
+ struct Foo {
+ int X;
+ double Y;
+ char Z;
+
+ bool operator==(const Foo &Other) const {
+ return X == Other.X && Y == Other.Y && Z == Other.Z;
+ }
+ };
+
+ std::vector<Foo> Foos;
+ Foos.push_back({-42, 42.42, 42});
+ Foos.push_back({100, 3.1415, static_cast<char>(-89)});
+ Foos.push_back({200, 2.718, static_cast<char>(-12) });
+
+ const uint8_t *Bytes = reinterpret_cast<const uint8_t *>(&Foos[0]);
+
+ initializeInput(makeArrayRef(Bytes, 3 * sizeof(Foo)), alignof(Foo));
+
+ for (auto &Stream : Streams) {
+ // 1. Reading object pointers.
+ BinaryStreamReader Reader(*Stream.Input);
+ const Foo *FPtrOut = nullptr;
+ const Foo *GPtrOut = nullptr;
+ const Foo *HPtrOut = nullptr;
+ ASSERT_NO_ERROR(Reader.readObject(FPtrOut));
+ ASSERT_NO_ERROR(Reader.readObject(GPtrOut));
+ ASSERT_NO_ERROR(Reader.readObject(HPtrOut));
+ EXPECT_EQ(0U, Reader.bytesRemaining());
+ EXPECT_EQ(Foos[0], *FPtrOut);
+ EXPECT_EQ(Foos[1], *GPtrOut);
+ EXPECT_EQ(Foos[2], *HPtrOut);
+ }
+}
+
+TEST_F(BinaryStreamTest, StreamReaderStrings) {
+ std::vector<uint8_t> Bytes = {'O', 'n', 'e', '\0', 'T', 'w', 'o',
+ '\0', 'T', 'h', 'r', 'e', 'e', '\0',
+ 'F', 'o', 'u', 'r', '\0'};
+ initializeInput(Bytes, 1);
+
+ for (auto &Stream : Streams) {
+ BinaryStreamReader Reader(*Stream.Input);
+
+ StringRef S1;
+ StringRef S2;
+ StringRef S3;
+ StringRef S4;
+ ASSERT_NO_ERROR(Reader.readCString(S1));
+ ASSERT_NO_ERROR(Reader.readCString(S2));
+ ASSERT_NO_ERROR(Reader.readCString(S3));
+ ASSERT_NO_ERROR(Reader.readCString(S4));
+ ASSERT_EQ(0U, Reader.bytesRemaining());
+
+ EXPECT_EQ("One", S1);
+ EXPECT_EQ("Two", S2);
+ EXPECT_EQ("Three", S3);
+ EXPECT_EQ("Four", S4);
+
+ S1 = S2 = S3 = S4 = "";
+ Reader.setOffset(0);
+ ASSERT_NO_ERROR(Reader.readFixedString(S1, 3));
+ ASSERT_NO_ERROR(Reader.skip(1));
+ ASSERT_NO_ERROR(Reader.readFixedString(S2, 3));
+ ASSERT_NO_ERROR(Reader.skip(1));
+ ASSERT_NO_ERROR(Reader.readFixedString(S3, 5));
+ ASSERT_NO_ERROR(Reader.skip(1));
+ ASSERT_NO_ERROR(Reader.readFixedString(S4, 4));
+ ASSERT_NO_ERROR(Reader.skip(1));
+ ASSERT_EQ(0U, Reader.bytesRemaining());
+
+ EXPECT_EQ("One", S1);
+ EXPECT_EQ("Two", S2);
+ EXPECT_EQ("Three", S3);
+ EXPECT_EQ("Four", S4);
+ }
+}
+
+TEST_F(BinaryStreamTest, StreamWriterBounds) {
+ initializeOutput(5, 1);
+
+ for (auto &Stream : Streams) {
+ BinaryStreamWriter Writer(*Stream.Output);
+
+ // 1. Can write a string that exactly fills the buffer.
+ EXPECT_EQ(5U, Writer.bytesRemaining());
+ EXPECT_NO_ERROR(Writer.writeFixedString("abcde"));
+ EXPECT_EQ(0U, Writer.bytesRemaining());
+
+ // 2. Can write an empty string even when you're full
+ EXPECT_NO_ERROR(Writer.writeFixedString(""));
+ EXPECT_ERROR(Writer.writeFixedString("a"));
+
+ // 3. Can't write a string that is one character too long.
+ Writer.setOffset(0);
+ EXPECT_ERROR(Writer.writeFixedString("abcdef"));
+ }
+}
+
+TEST_F(BinaryStreamTest, StreamWriterIntegerArrays) {
+ // 3. Arrays of integers
+ std::vector<int> SourceInts = {1, 2, 3, 4, 5};
+ ArrayRef<uint8_t> SourceBytes(reinterpret_cast<uint8_t *>(&SourceInts[0]),
+ SourceInts.size() * sizeof(int));
+
+ initializeInput(SourceBytes, alignof(int));
+ initializeOutputFromInput(alignof(int));
+
+ for (auto &Stream : Streams) {
+ BinaryStreamReader Reader(*Stream.Input);
+ BinaryStreamWriter Writer(*Stream.Output);
+ ArrayRef<int> Ints;
+ ArrayRef<int> Ints2;
+ // First read them, then write them, then read them back.
+ ASSERT_NO_ERROR(Reader.readArray(Ints, SourceInts.size()));
+ ASSERT_NO_ERROR(Writer.writeArray(Ints));
+
+ BinaryStreamReader ReaderBacker(*Stream.Output);
+ ASSERT_NO_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()));
+
+ EXPECT_EQ(makeArrayRef(SourceInts), Ints2);
+ }
+}
+
+TEST_F(BinaryStreamTest, StringWriterStrings) {
+ StringRef Strings[] = {"First", "Second", "Third", "Fourth"};
+
+ size_t Length = 0;
+ for (auto S : Strings)
+ Length += S.size() + 1;
+ initializeOutput(Length, 1);
+ initializeInputFromOutput(1);
+
+ for (auto &Stream : Streams) {
+ BinaryStreamWriter Writer(*Stream.Output);
+ for (auto S : Strings)
+ ASSERT_NO_ERROR(Writer.writeCString(S));
+ std::vector<StringRef> InStrings;
+ BinaryStreamReader Reader(*Stream.Input);
+ while (!Reader.empty()) {
+ StringRef S;
+ ASSERT_NO_ERROR(Reader.readCString(S));
+ InStrings.push_back(S);
+ }
+ EXPECT_EQ(makeArrayRef(Strings), makeArrayRef(InStrings));
+ }
+}
+}
+
+namespace {
+struct BinaryItemStreamObject {
+ explicit BinaryItemStreamObject(ArrayRef<uint8_t> Bytes) : Bytes(Bytes) {}
+
+ ArrayRef<uint8_t> Bytes;
+};
+}
+
+namespace llvm {
+template <> struct BinaryItemTraits<BinaryItemStreamObject> {
+ static size_t length(const BinaryItemStreamObject &Item) {
+ return Item.Bytes.size();
+ }
+
+ static ArrayRef<uint8_t> bytes(const BinaryItemStreamObject &Item) {
+ return Item.Bytes;
+ }
+};
+}
+
+namespace {
+
+TEST_F(BinaryStreamTest, BinaryItemStream) {
+ std::vector<BinaryItemStreamObject> Objects;
+
+ struct Foo {
+ int X;
+ double Y;
+ };
+ std::vector<Foo> Foos = {{1, 1.0}, {2, 2.0}, {3, 3.0}};
+ BumpPtrAllocator Allocator;
+ for (const auto &F : Foos) {
+ uint8_t *Ptr = static_cast<uint8_t *>(Allocator.Allocate(sizeof(Foo),
+ alignof(Foo)));
+ MutableArrayRef<uint8_t> Buffer(Ptr, sizeof(Foo));
+ MutableBinaryByteStream Stream(Buffer, llvm::support::big);
+ BinaryStreamWriter Writer(Stream);
+ ASSERT_NO_ERROR(Writer.writeObject(F));
+ Objects.push_back(BinaryItemStreamObject(Buffer));
+ }
+
+ BinaryItemStream<BinaryItemStreamObject> ItemStream(big);
+ ItemStream.setItems(Objects);
+ BinaryStreamReader Reader(ItemStream);
+
+ for (const auto &F : Foos) {
+ const Foo *F2;
+ ASSERT_NO_ERROR(Reader.readObject(F2));
+
+ EXPECT_EQ(F.X, F2->X);
+ EXPECT_DOUBLE_EQ(F.Y, F2->Y);
+ }
+}
+
+} // end anonymous namespace
diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt
index 6068de5514c7..a7be18b6a3c5 100644
--- a/unittests/Support/CMakeLists.txt
+++ b/unittests/Support/CMakeLists.txt
@@ -5,9 +5,12 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(SupportTests
AlignOfTest.cpp
AllocatorTest.cpp
+ ARMAttributeParser.cpp
ArrayRecyclerTest.cpp
+ BinaryStreamTest.cpp
BlockFrequencyTest.cpp
BranchProbabilityTest.cpp
+ CachePruningTest.cpp
Casting.cpp
Chrono.cpp
CommandLineTest.cpp
@@ -63,4 +66,4 @@ add_llvm_unittest(SupportTests
)
# ManagedStatic.cpp uses <pthread>.
-target_link_libraries(SupportTests ${PTHREAD_LIB})
+target_link_libraries(SupportTests ${LLVM_PTHREAD_LIB})
diff --git a/unittests/Support/CachePruningTest.cpp b/unittests/Support/CachePruningTest.cpp
new file mode 100644
index 000000000000..04ac0d09b493
--- /dev/null
+++ b/unittests/Support/CachePruningTest.cpp
@@ -0,0 +1,71 @@
+//===- CachePruningTest.cpp -----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/CachePruning.h"
+#include "llvm/Support/Error.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+TEST(CachePruningPolicyParser, Empty) {
+ auto P = parseCachePruningPolicy("");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(std::chrono::seconds(1200), P->Interval);
+ EXPECT_EQ(std::chrono::hours(7 * 24), P->Expiration);
+ EXPECT_EQ(75u, P->PercentageOfAvailableSpace);
+}
+
+TEST(CachePruningPolicyParser, Interval) {
+ auto P = parseCachePruningPolicy("prune_interval=1s");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(std::chrono::seconds(1), P->Interval);
+ P = parseCachePruningPolicy("prune_interval=2m");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(std::chrono::minutes(2), P->Interval);
+ P = parseCachePruningPolicy("prune_interval=3h");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(std::chrono::hours(3), P->Interval);
+}
+
+TEST(CachePruningPolicyParser, Expiration) {
+ auto P = parseCachePruningPolicy("prune_after=1s");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(std::chrono::seconds(1), P->Expiration);
+}
+
+TEST(CachePruningPolicyParser, PercentageOfAvailableSpace) {
+ auto P = parseCachePruningPolicy("cache_size=100%");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(100u, P->PercentageOfAvailableSpace);
+}
+
+TEST(CachePruningPolicyParser, Multiple) {
+ auto P = parseCachePruningPolicy("prune_after=1s:cache_size=50%");
+ ASSERT_TRUE(bool(P));
+ EXPECT_EQ(std::chrono::seconds(1200), P->Interval);
+ EXPECT_EQ(std::chrono::seconds(1), P->Expiration);
+ EXPECT_EQ(50u, P->PercentageOfAvailableSpace);
+}
+
+TEST(CachePruningPolicyParser, Errors) {
+ EXPECT_EQ("Duration must not be empty",
+ toString(parseCachePruningPolicy("prune_interval=").takeError()));
+ EXPECT_EQ("'foo' not an integer",
+ toString(parseCachePruningPolicy("prune_interval=foos").takeError()));
+ EXPECT_EQ("'24x' must end with one of 's', 'm' or 'h'",
+ toString(parseCachePruningPolicy("prune_interval=24x").takeError()));
+ EXPECT_EQ("'foo' must be a percentage",
+ toString(parseCachePruningPolicy("cache_size=foo").takeError()));
+ EXPECT_EQ("'foo' not an integer",
+ toString(parseCachePruningPolicy("cache_size=foo%").takeError()));
+ EXPECT_EQ("'101' must be between 0 and 100",
+ toString(parseCachePruningPolicy("cache_size=101%").takeError()));
+ EXPECT_EQ("Unknown key: 'foo'",
+ toString(parseCachePruningPolicy("foo=bar").takeError()));
+}
diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp
index e6c35fc21eb7..9a818f6bdebd 100644
--- a/unittests/Support/Casting.cpp
+++ b/unittests/Support/Casting.cpp
@@ -40,6 +40,14 @@ struct foo {
}*/
};
+struct base {
+ virtual ~base() {}
+};
+
+struct derived : public base {
+ static bool classof(const base *B) { return true; }
+};
+
template <> struct isa_impl<foo, bar> {
static inline bool doit(const bar &Val) {
dbgs() << "Classof: " << &Val << "\n";
@@ -47,6 +55,10 @@ template <> struct isa_impl<foo, bar> {
}
};
+template <typename T> struct isa_impl<foo, T> {
+ static inline bool doit(const T &Val) { return false; }
+};
+
foo *bar::baz() {
return cast<foo>(this);
}
@@ -123,6 +135,13 @@ TEST(CastingTest, cast) {
// EXPECT_EQ(F7, null_foo);
foo *F8 = B1.baz();
EXPECT_NE(F8, null_foo);
+
+ std::unique_ptr<const bar> BP(B2);
+ auto FP = cast<foo>(std::move(BP));
+ static_assert(std::is_same<std::unique_ptr<const foo>, decltype(FP)>::value,
+ "Incorrect deduced return type!");
+ EXPECT_NE(FP.get(), null_foo);
+ FP.release();
}
TEST(CastingTest, cast_or_null) {
@@ -136,6 +155,10 @@ TEST(CastingTest, cast_or_null) {
EXPECT_EQ(F14, null_foo);
foo *F15 = B1.caz();
EXPECT_NE(F15, null_foo);
+
+ std::unique_ptr<const bar> BP(fub());
+ auto FP = cast_or_null<foo>(std::move(BP));
+ EXPECT_EQ(FP.get(), null_foo);
}
TEST(CastingTest, dyn_cast) {
@@ -165,6 +188,58 @@ TEST(CastingTest, dyn_cast_or_null) {
EXPECT_NE(F5, null_foo);
}
+std::unique_ptr<derived> newd() { return llvm::make_unique<derived>(); }
+std::unique_ptr<base> newb() { return llvm::make_unique<derived>(); }
+
+TEST(CastingTest, unique_dyn_cast) {
+ derived *OrigD = nullptr;
+ auto D = llvm::make_unique<derived>();
+ OrigD = D.get();
+
+ // Converting from D to itself is valid, it should return a new unique_ptr
+ // and the old one should become nullptr.
+ auto NewD = unique_dyn_cast<derived>(D);
+ ASSERT_EQ(OrigD, NewD.get());
+ ASSERT_EQ(nullptr, D);
+
+ // Converting from D to B is valid, B should have a value and D should be
+ // nullptr.
+ auto B = unique_dyn_cast<base>(NewD);
+ ASSERT_EQ(OrigD, B.get());
+ ASSERT_EQ(nullptr, NewD);
+
+ // Converting from B to itself is valid, it should return a new unique_ptr
+ // and the old one should become nullptr.
+ auto NewB = unique_dyn_cast<base>(B);
+ ASSERT_EQ(OrigD, NewB.get());
+ ASSERT_EQ(nullptr, B);
+
+ // Converting from B to D is valid, D should have a value and B should be
+ // nullptr;
+ D = unique_dyn_cast<derived>(NewB);
+ ASSERT_EQ(OrigD, D.get());
+ ASSERT_EQ(nullptr, NewB);
+
+ // Converting between unrelated types should fail. The original value should
+ // remain unchanged and it should return nullptr.
+ auto F = unique_dyn_cast<foo>(D);
+ ASSERT_EQ(nullptr, F);
+ ASSERT_EQ(OrigD, D.get());
+
+ // All of the above should also hold for temporaries.
+ auto D2 = unique_dyn_cast<derived>(newd());
+ EXPECT_NE(nullptr, D2);
+
+ auto B2 = unique_dyn_cast<derived>(newb());
+ EXPECT_NE(nullptr, B2);
+
+ auto B3 = unique_dyn_cast<base>(newb());
+ EXPECT_NE(nullptr, B3);
+
+ auto F2 = unique_dyn_cast<foo>(newb());
+ EXPECT_EQ(nullptr, F2);
+}
+
// These lines are errors...
//foo *F20 = cast<foo>(B2); // Yields const foo*
//foo &F21 = cast<foo>(B3); // Yields const foo&
diff --git a/unittests/Support/Chrono.cpp b/unittests/Support/Chrono.cpp
index 3d5787807563..1410baf848bb 100644
--- a/unittests/Support/Chrono.cpp
+++ b/unittests/Support/Chrono.cpp
@@ -9,6 +9,7 @@
#include "llvm/Support/Chrono.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/FormatVariadic.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -76,4 +77,34 @@ TEST(Chrono, ImplicitConversions) {
EXPECT_EQ(TimeT, toTimeT(Nano));
}
+TEST(Chrono, DurationFormat) {
+ EXPECT_EQ("1 h", formatv("{0}", hours(1)).str());
+ EXPECT_EQ("1 m", formatv("{0}", minutes(1)).str());
+ EXPECT_EQ("1 s", formatv("{0}", seconds(1)).str());
+ EXPECT_EQ("1 ms", formatv("{0}", milliseconds(1)).str());
+ EXPECT_EQ("1 us", formatv("{0}", microseconds(1)).str());
+ EXPECT_EQ("1 ns", formatv("{0}", nanoseconds(1)).str());
+
+ EXPECT_EQ("1 s", formatv("{0:+}", seconds(1)).str());
+ EXPECT_EQ("1", formatv("{0:-}", seconds(1)).str());
+
+ EXPECT_EQ("1000 ms", formatv("{0:ms}", seconds(1)).str());
+ EXPECT_EQ("1000000 us", formatv("{0:us}", seconds(1)).str());
+ EXPECT_EQ("1000", formatv("{0:ms-}", seconds(1)).str());
+
+ EXPECT_EQ("1,000 ms", formatv("{0:+n}", milliseconds(1000)).str());
+ EXPECT_EQ("0x3e8", formatv("{0:-x}", milliseconds(1000)).str());
+ EXPECT_EQ("010", formatv("{0:-3}", milliseconds(10)).str());
+ EXPECT_EQ("10,000", formatv("{0:ms-n}", seconds(10)).str());
+
+ EXPECT_EQ("1.00 s", formatv("{0}", duration<float>(1)).str());
+ EXPECT_EQ("0.123 s", formatv("{0:+3}", duration<float>(0.123f)).str());
+ EXPECT_EQ("1.230e-01 s", formatv("{0:+e3}", duration<float>(0.123f)).str());
+
+ typedef duration<float, std::ratio<60 * 60 * 24 * 14, 1000000>>
+ microfortnights;
+ EXPECT_EQ("1.00", formatv("{0:-}", microfortnights(1)).str());
+ EXPECT_EQ("1209.60 ms", formatv("{0:ms}", microfortnights(1)).str());
+}
+
} // anonymous namespace
diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp
index 945eb1d4e1cf..33573c4e6960 100644
--- a/unittests/Support/CommandLineTest.cpp
+++ b/unittests/Support/CommandLineTest.cpp
@@ -303,7 +303,8 @@ TEST(CommandLineTest, SetValueInSubcategories) {
EXPECT_FALSE(SC1Opt);
EXPECT_FALSE(SC2Opt);
const char *args[] = {"prog", "-top-level"};
- EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
EXPECT_TRUE(TopLevelOpt);
EXPECT_FALSE(SC1Opt);
EXPECT_FALSE(SC2Opt);
@@ -315,7 +316,8 @@ TEST(CommandLineTest, SetValueInSubcategories) {
EXPECT_FALSE(SC1Opt);
EXPECT_FALSE(SC2Opt);
const char *args2[] = {"prog", "sc1", "-sc1"};
- EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
EXPECT_FALSE(TopLevelOpt);
EXPECT_TRUE(SC1Opt);
EXPECT_FALSE(SC2Opt);
@@ -327,7 +329,8 @@ TEST(CommandLineTest, SetValueInSubcategories) {
EXPECT_FALSE(SC1Opt);
EXPECT_FALSE(SC2Opt);
const char *args3[] = {"prog", "sc2", "-sc2"};
- EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(3, args3, StringRef(), &llvm::nulls()));
EXPECT_FALSE(TopLevelOpt);
EXPECT_FALSE(SC1Opt);
EXPECT_TRUE(SC2Opt);
@@ -342,8 +345,13 @@ TEST(CommandLineTest, LookupFailsInWrongSubCommand) {
StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
+ std::string Errs;
+ raw_string_ostream OS(Errs);
+
const char *args[] = {"prog", "sc1", "-sc2"};
- EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), true));
+ EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
+ OS.flush();
+ EXPECT_FALSE(Errs.empty());
}
TEST(CommandLineTest, AddToAllSubCommands) {
@@ -358,23 +366,30 @@ TEST(CommandLineTest, AddToAllSubCommands) {
const char *args2[] = {"prog", "sc1", "-everywhere"};
const char *args3[] = {"prog", "sc2", "-everywhere"};
+ std::string Errs;
+ raw_string_ostream OS(Errs);
+
EXPECT_FALSE(AllOpt);
- EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
EXPECT_TRUE(AllOpt);
AllOpt = false;
cl::ResetAllOptionOccurrences();
EXPECT_FALSE(AllOpt);
- EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), true));
+ EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), &OS));
EXPECT_TRUE(AllOpt);
AllOpt = false;
cl::ResetAllOptionOccurrences();
EXPECT_FALSE(AllOpt);
- EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), true));
+ EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), &OS));
EXPECT_TRUE(AllOpt);
+
+ // Since all parsing succeeded, the error message should be empty.
+ OS.flush();
+ EXPECT_TRUE(Errs.empty());
}
TEST(CommandLineTest, ReparseCommandLineOptions) {
@@ -386,14 +401,16 @@ TEST(CommandLineTest, ReparseCommandLineOptions) {
const char *args[] = {"prog", "-top-level"};
EXPECT_FALSE(TopLevelOpt);
- EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
EXPECT_TRUE(TopLevelOpt);
TopLevelOpt = false;
cl::ResetAllOptionOccurrences();
EXPECT_FALSE(TopLevelOpt);
- EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
EXPECT_TRUE(TopLevelOpt);
}
@@ -406,14 +423,21 @@ TEST(CommandLineTest, RemoveFromRegularSubCommand) {
const char *args[] = {"prog", "sc", "-remove-option"};
+ std::string Errs;
+ raw_string_ostream OS(Errs);
+
EXPECT_FALSE(RemoveOption);
- EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, StringRef(), true));
+ EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
EXPECT_TRUE(RemoveOption);
+ OS.flush();
+ EXPECT_TRUE(Errs.empty());
RemoveOption.removeArgument();
cl::ResetAllOptionOccurrences();
- EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), true));
+ EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
+ OS.flush();
+ EXPECT_FALSE(Errs.empty());
}
TEST(CommandLineTest, RemoveFromTopLevelSubCommand) {
@@ -427,13 +451,15 @@ TEST(CommandLineTest, RemoveFromTopLevelSubCommand) {
const char *args[] = {"prog", "-top-level-remove"};
EXPECT_FALSE(TopLevelRemove);
- EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
EXPECT_TRUE(TopLevelRemove);
TopLevelRemove.removeArgument();
cl::ResetAllOptionOccurrences();
- EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
+ EXPECT_FALSE(
+ cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
}
TEST(CommandLineTest, RemoveFromAllSubCommands) {
@@ -452,32 +478,38 @@ TEST(CommandLineTest, RemoveFromAllSubCommands) {
// It should work for all subcommands including the top-level.
EXPECT_FALSE(RemoveOption);
- EXPECT_TRUE(cl::ParseCommandLineOptions(2, args0, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
EXPECT_TRUE(RemoveOption);
RemoveOption = false;
cl::ResetAllOptionOccurrences();
EXPECT_FALSE(RemoveOption);
- EXPECT_TRUE(cl::ParseCommandLineOptions(3, args1, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
EXPECT_TRUE(RemoveOption);
RemoveOption = false;
cl::ResetAllOptionOccurrences();
EXPECT_FALSE(RemoveOption);
- EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
EXPECT_TRUE(RemoveOption);
RemoveOption.removeArgument();
// It should not work for any subcommands including the top-level.
cl::ResetAllOptionOccurrences();
- EXPECT_FALSE(cl::ParseCommandLineOptions(2, args0, StringRef(), true));
+ EXPECT_FALSE(
+ cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
cl::ResetAllOptionOccurrences();
- EXPECT_FALSE(cl::ParseCommandLineOptions(3, args1, StringRef(), true));
+ EXPECT_FALSE(
+ cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
cl::ResetAllOptionOccurrences();
- EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, StringRef(), true));
+ EXPECT_FALSE(
+ cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
}
TEST(CommandLineTest, GetRegisteredSubcommands) {
@@ -491,7 +523,8 @@ TEST(CommandLineTest, GetRegisteredSubcommands) {
const char *args0[] = {"prog", "sc1"};
const char *args1[] = {"prog", "sc2"};
- EXPECT_TRUE(cl::ParseCommandLineOptions(2, args0, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
EXPECT_FALSE(Opt1);
EXPECT_FALSE(Opt2);
for (auto *S : cl::getRegisteredSubcommands()) {
@@ -500,7 +533,8 @@ TEST(CommandLineTest, GetRegisteredSubcommands) {
}
cl::ResetAllOptionOccurrences();
- EXPECT_TRUE(cl::ParseCommandLineOptions(2, args1, StringRef(), true));
+ EXPECT_TRUE(
+ cl::ParseCommandLineOptions(2, args1, StringRef(), &llvm::nulls()));
EXPECT_FALSE(Opt1);
EXPECT_FALSE(Opt2);
for (auto *S : cl::getRegisteredSubcommands()) {
diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp
index 36b84d85f22b..18a6175460d3 100644
--- a/unittests/Support/CompressionTest.cpp
+++ b/unittests/Support/CompressionTest.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Compression.h"
+#include "llvm/Support/Error.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/config.h"
@@ -26,15 +27,21 @@ namespace {
void TestZlibCompression(StringRef Input, zlib::CompressionLevel Level) {
SmallString<32> Compressed;
SmallString<32> Uncompressed;
- EXPECT_EQ(zlib::StatusOK, zlib::compress(Input, Compressed, Level));
+
+ Error E = zlib::compress(Input, Compressed, Level);
+ EXPECT_FALSE(E);
+ consumeError(std::move(E));
+
// Check that uncompressed buffer is the same as original.
- EXPECT_EQ(zlib::StatusOK,
- zlib::uncompress(Compressed, Uncompressed, Input.size()));
+ E = zlib::uncompress(Compressed, Uncompressed, Input.size());
+ EXPECT_FALSE(E);
+ consumeError(std::move(E));
+
EXPECT_EQ(Input, Uncompressed);
if (Input.size() > 0) {
// Uncompression fails if expected length is too short.
- EXPECT_EQ(zlib::StatusBufferTooShort,
- zlib::uncompress(Compressed, Uncompressed, Input.size() - 1));
+ E = zlib::uncompress(Compressed, Uncompressed, Input.size() - 1);
+ EXPECT_EQ("zlib error: Z_BUF_ERROR", llvm::toString(std::move(E)));
}
}
diff --git a/unittests/Support/ErrorTest.cpp b/unittests/Support/ErrorTest.cpp
index 29a173a058b6..382346cd231a 100644
--- a/unittests/Support/ErrorTest.cpp
+++ b/unittests/Support/ErrorTest.cpp
@@ -469,6 +469,34 @@ TEST(Error, ExitOnError) {
<< "exitOnError returned an unexpected error result";
}
+// Test that the ExitOnError utility works as expected.
+TEST(Error, CantFailSuccess) {
+ cantFail(Error::success());
+
+ int X = cantFail(Expected<int>(42));
+ EXPECT_EQ(X, 42) << "Expected value modified by cantFail";
+}
+
+// Test that cantFail results in a crash if you pass it a failure value.
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+TEST(Error, CantFailDeath) {
+ EXPECT_DEATH(
+ cantFail(make_error<StringError>("foo", inconvertibleErrorCode())),
+ "Failure value returned from cantFail wrapped call")
+ << "cantFail(Error) did not cause an abort for failure value";
+
+ EXPECT_DEATH(
+ {
+ auto IEC = inconvertibleErrorCode();
+ int X = cantFail(Expected<int>(make_error<StringError>("foo", IEC)));
+ (void)X;
+ },
+ "Failure value returned from cantFail wrapped call")
+ << "cantFail(Expected<int>) did not cause an abort for failure value";
+}
+#endif
+
+
// Test Checked Expected<T> in success mode.
TEST(Error, CheckedExpectedInSuccessMode) {
Expected<int> A = 7;
diff --git a/unittests/Support/FormatVariadicTest.cpp b/unittests/Support/FormatVariadicTest.cpp
index 9307c6d8e09b..b0c843870afc 100644
--- a/unittests/Support/FormatVariadicTest.cpp
+++ b/unittests/Support/FormatVariadicTest.cpp
@@ -324,11 +324,13 @@ TEST(FormatVariadicTest, StringFormatting) {
const char FooArray[] = "FooArray";
const char *FooPtr = "FooPtr";
llvm::StringRef FooRef("FooRef");
+ constexpr StringLiteral FooLiteral("FooLiteral");
std::string FooString("FooString");
// 1. Test that we can print various types of strings.
EXPECT_EQ(FooArray, formatv("{0}", FooArray).str());
EXPECT_EQ(FooPtr, formatv("{0}", FooPtr).str());
EXPECT_EQ(FooRef, formatv("{0}", FooRef).str());
+ EXPECT_EQ(FooLiteral, formatv("{0}", FooLiteral).str());
EXPECT_EQ(FooString, formatv("{0}", FooString).str());
// 2. Test that the precision specifier prints the correct number of
diff --git a/unittests/Support/Host.cpp b/unittests/Support/Host.cpp
index 934a60495427..fd53697793c7 100644
--- a/unittests/Support/Host.cpp
+++ b/unittests/Support/Host.cpp
@@ -17,25 +17,17 @@ using namespace llvm;
class HostTest : public testing::Test {
Triple Host;
- SmallVector<std::pair<Triple::ArchType, Triple::OSType>, 4> SupportedArchAndOSs;
protected:
bool isSupportedArchAndOS() {
- if (is_contained(SupportedArchAndOSs, std::make_pair(Host.getArch(), Host.getOS())))
- return true;
-
- return false;
- }
-
- HostTest() {
- Host.setTriple(Triple::normalize(sys::getProcessTriple()));
-
// Initially this is only testing detection of the number of
// physical cores, which is currently only supported/tested for
// x86_64 Linux and Darwin.
- SupportedArchAndOSs.push_back(std::make_pair(Triple::x86_64, Triple::Linux));
- SupportedArchAndOSs.push_back(std::make_pair(Triple::x86_64, Triple::Darwin));
+ return (Host.getArch() == Triple::x86_64 &&
+ (Host.isOSDarwin() || Host.getOS() == Triple::Linux));
}
+
+ HostTest() : Host(Triple::normalize(sys::getProcessTriple())) {}
};
TEST_F(HostTest, NumPhysicalCores) {
@@ -46,3 +38,79 @@ TEST_F(HostTest, NumPhysicalCores) {
else
ASSERT_EQ(Num, -1);
}
+
+TEST(getLinuxHostCPUName, ARM) {
+ StringRef CortexA9ProcCpuinfo = R"(
+processor : 0
+model name : ARMv7 Processor rev 10 (v7l)
+BogoMIPS : 1393.66
+Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
+CPU implementer : 0x41
+CPU architecture: 7
+CPU variant : 0x2
+CPU part : 0xc09
+CPU revision : 10
+
+processor : 1
+model name : ARMv7 Processor rev 10 (v7l)
+BogoMIPS : 1393.66
+Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
+CPU implementer : 0x41
+CPU architecture: 7
+CPU variant : 0x2
+CPU part : 0xc09
+CPU revision : 10
+
+Hardware : Generic OMAP4 (Flattened Device Tree)
+Revision : 0000
+Serial : 0000000000000000
+)";
+
+ EXPECT_EQ(sys::detail::getHostCPUNameForARM(CortexA9ProcCpuinfo),
+ "cortex-a9");
+ EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
+ "CPU part : 0xc0f"),
+ "cortex-a15");
+ // Verify that both CPU implementer and CPU part are checked:
+ EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
+ "CPU part : 0xc0f"),
+ "generic");
+ EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
+ "CPU part : 0x06f"),
+ "krait");
+}
+
+TEST(getLinuxHostCPUName, AArch64) {
+ EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
+ "CPU part : 0xd03"),
+ "cortex-a53");
+ // Verify that both CPU implementer and CPU part are checked:
+ EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
+ "CPU part : 0xd03"),
+ "generic");
+ EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
+ "CPU part : 0x201"),
+ "kryo");
+
+ // MSM8992/4 weirdness
+ StringRef MSM8992ProcCpuInfo = R"(
+Processor : AArch64 Processor rev 3 (aarch64)
+processor : 0
+processor : 1
+processor : 2
+processor : 3
+processor : 4
+processor : 5
+Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
+CPU implementer : 0x41
+CPU architecture: 8
+CPU variant : 0x0
+CPU part : 0xd03
+CPU revision : 3
+
+Hardware : Qualcomm Technologies, Inc MSM8992
+)";
+
+ EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo),
+ "cortex-a53");
+}
diff --git a/unittests/Support/LEB128Test.cpp b/unittests/Support/LEB128Test.cpp
index 76b63e5a8381..061936df1d19 100644
--- a/unittests/Support/LEB128Test.cpp
+++ b/unittests/Support/LEB128Test.cpp
@@ -17,26 +17,45 @@ using namespace llvm;
namespace {
TEST(LEB128Test, EncodeSLEB128) {
-#define EXPECT_SLEB128_EQ(EXPECTED, VALUE) \
+#define EXPECT_SLEB128_EQ(EXPECTED, VALUE, PAD) \
do { \
- /* encodeSLEB128(uint64_t, raw_ostream &) */ \
std::string Expected(EXPECTED, sizeof(EXPECTED) - 1); \
- std::string Actual; \
- raw_string_ostream Stream(Actual); \
- encodeSLEB128(VALUE, Stream); \
+ \
+ /* encodeSLEB128(uint64_t, raw_ostream &, unsigned) */ \
+ std::string Actual1; \
+ raw_string_ostream Stream(Actual1); \
+ encodeSLEB128(VALUE, Stream, PAD); \
Stream.flush(); \
- EXPECT_EQ(Expected, Actual); \
+ EXPECT_EQ(Expected, Actual1); \
+ \
+ /* encodeSLEB128(uint64_t, uint8_t *, unsigned) */ \
+ uint8_t Buffer[32]; \
+ unsigned Size = encodeSLEB128(VALUE, Buffer, PAD); \
+ std::string Actual2(reinterpret_cast<const char *>(Buffer), Size); \
+ EXPECT_EQ(Expected, Actual2); \
} while (0)
// Encode SLEB128
- EXPECT_SLEB128_EQ("\x00", 0);
- EXPECT_SLEB128_EQ("\x01", 1);
- EXPECT_SLEB128_EQ("\x7f", -1);
- EXPECT_SLEB128_EQ("\x3f", 63);
- EXPECT_SLEB128_EQ("\x41", -63);
- EXPECT_SLEB128_EQ("\x40", -64);
- EXPECT_SLEB128_EQ("\xbf\x7f", -65);
- EXPECT_SLEB128_EQ("\xc0\x00", 64);
+ EXPECT_SLEB128_EQ("\x00", 0, 0);
+ EXPECT_SLEB128_EQ("\x01", 1, 0);
+ EXPECT_SLEB128_EQ("\x7f", -1, 0);
+ EXPECT_SLEB128_EQ("\x3f", 63, 0);
+ EXPECT_SLEB128_EQ("\x41", -63, 0);
+ EXPECT_SLEB128_EQ("\x40", -64, 0);
+ EXPECT_SLEB128_EQ("\xbf\x7f", -65, 0);
+ EXPECT_SLEB128_EQ("\xc0\x00", 64, 0);
+
+ // Encode SLEB128 with some extra padding bytes
+ EXPECT_SLEB128_EQ("\x80\x00", 0, 1);
+ EXPECT_SLEB128_EQ("\x80\x80\x00", 0, 2);
+ EXPECT_SLEB128_EQ("\xff\x80\x00", 0x7f, 1);
+ EXPECT_SLEB128_EQ("\xff\x80\x80\x00", 0x7f, 2);
+ EXPECT_SLEB128_EQ("\x80\x81\x00", 0x80, 1);
+ EXPECT_SLEB128_EQ("\x80\x81\x80\x00", 0x80, 2);
+ EXPECT_SLEB128_EQ("\xc0\x7f", -0x40, 1);
+ EXPECT_SLEB128_EQ("\xc0\xff\x7f", -0x40, 2);
+ EXPECT_SLEB128_EQ("\x80\xff\x7f", -0x80, 1);
+ EXPECT_SLEB128_EQ("\x80\xff\xff\x7f", -0x80, 2);
#undef EXPECT_SLEB128_EQ
}
diff --git a/unittests/Support/MD5Test.cpp b/unittests/Support/MD5Test.cpp
index 4d790254503e..fa9372fde33f 100644
--- a/unittests/Support/MD5Test.cpp
+++ b/unittests/Support/MD5Test.cpp
@@ -63,8 +63,10 @@ TEST(MD5HashTest, MD5) {
std::array<uint8_t, 16> Vec = MD5::hash(Input);
MD5::MD5Result MD5Res;
SmallString<32> Res;
- memcpy(MD5Res, Vec.data(), Vec.size());
+ memcpy(MD5Res.Bytes.data(), Vec.data(), Vec.size());
MD5::stringifyResult(MD5Res, Res);
EXPECT_EQ(Res, "c3fcd3d76192e4007dfb496cca67e13b");
+ EXPECT_EQ(0x3be167ca6c49fb7dULL, MD5Res.high());
+ EXPECT_EQ(0x00e49261d7d3fcc3ULL, MD5Res.low());
}
}
diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp
index 30eaa8b278ab..86ad57f3f3ff 100644
--- a/unittests/Support/Path.cpp
+++ b/unittests/Support/Path.cpp
@@ -8,12 +8,15 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Path.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
@@ -25,6 +28,7 @@
#endif
#ifdef LLVM_ON_UNIX
+#include <pwd.h>
#include <sys/stat.h>
#endif
@@ -50,6 +54,9 @@ TEST(is_separator, Works) {
EXPECT_FALSE(path::is_separator('-'));
EXPECT_FALSE(path::is_separator(' '));
+ EXPECT_TRUE(path::is_separator('\\', path::Style::windows));
+ EXPECT_FALSE(path::is_separator('\\', path::Style::posix));
+
#ifdef LLVM_ON_WIN32
EXPECT_TRUE(path::is_separator('\\'));
#else
@@ -249,7 +256,6 @@ TEST(Support, AbsolutePathDotIterator) {
}
}
-#ifdef LLVM_ON_WIN32
TEST(Support, AbsolutePathIteratorWin32) {
SmallString<64> Path(StringRef("c:\\c\\e\\foo.txt"));
typedef SmallVector<StringRef, 4> PathComponents;
@@ -262,8 +268,9 @@ TEST(Support, AbsolutePathIteratorWin32) {
// when iterating.
ExpectedPathComponents.insert(ExpectedPathComponents.begin()+1, "\\");
- for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
- ++I) {
+ for (path::const_iterator I = path::begin(Path, path::Style::windows),
+ E = path::end(Path);
+ I != E; ++I) {
ActualPathComponents.push_back(*I);
}
@@ -273,34 +280,29 @@ TEST(Support, AbsolutePathIteratorWin32) {
EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
}
}
-#endif // LLVM_ON_WIN32
TEST(Support, AbsolutePathIteratorEnd) {
// Trailing slashes are converted to '.' unless they are part of the root path.
- SmallVector<StringRef, 4> Paths;
- Paths.push_back("/foo/");
- Paths.push_back("/foo//");
- Paths.push_back("//net//");
-#ifdef LLVM_ON_WIN32
- Paths.push_back("c:\\\\");
-#endif
-
- for (StringRef Path : Paths) {
- StringRef LastComponent = *path::rbegin(Path);
+ SmallVector<std::pair<StringRef, path::Style>, 4> Paths;
+ Paths.emplace_back("/foo/", path::Style::native);
+ Paths.emplace_back("/foo//", path::Style::native);
+ Paths.emplace_back("//net//", path::Style::native);
+ Paths.emplace_back("c:\\\\", path::Style::windows);
+
+ for (auto &Path : Paths) {
+ StringRef LastComponent = *path::rbegin(Path.first, Path.second);
EXPECT_EQ(".", LastComponent);
}
- SmallVector<StringRef, 3> RootPaths;
- RootPaths.push_back("/");
- RootPaths.push_back("//net/");
-#ifdef LLVM_ON_WIN32
- RootPaths.push_back("c:\\");
-#endif
+ SmallVector<std::pair<StringRef, path::Style>, 3> RootPaths;
+ RootPaths.emplace_back("/", path::Style::native);
+ RootPaths.emplace_back("//net/", path::Style::native);
+ RootPaths.emplace_back("c:\\", path::Style::windows);
- for (StringRef Path : RootPaths) {
- StringRef LastComponent = *path::rbegin(Path);
+ for (auto &Path : RootPaths) {
+ StringRef LastComponent = *path::rbegin(Path.first, Path.second);
EXPECT_EQ(1u, LastComponent.size());
- EXPECT_TRUE(path::is_separator(LastComponent[0]));
+ EXPECT_TRUE(path::is_separator(LastComponent[0], Path.second));
}
}
@@ -327,6 +329,36 @@ TEST(Support, HomeDirectory) {
}
}
+#ifdef LLVM_ON_UNIX
+TEST(Support, HomeDirectoryWithNoEnv) {
+ std::string OriginalStorage;
+ char const *OriginalEnv = ::getenv("HOME");
+ if (OriginalEnv) {
+ // We're going to unset it, so make a copy and save a pointer to the copy
+ // so that we can reset it at the end of the test.
+ OriginalStorage = OriginalEnv;
+ OriginalEnv = OriginalStorage.c_str();
+ }
+
+ // Don't run the test if we have nothing to compare against.
+ struct passwd *pw = getpwuid(getuid());
+ if (!pw || !pw->pw_dir) return;
+
+ ::unsetenv("HOME");
+ EXPECT_EQ(nullptr, ::getenv("HOME"));
+ std::string PwDir = pw->pw_dir;
+
+ SmallString<128> HomeDir;
+ auto status = path::home_directory(HomeDir);
+ EXPECT_TRUE(status);
+ EXPECT_EQ(PwDir, HomeDir);
+
+ // Now put the environment back to its original state (meaning that if it was
+ // unset before, we don't reset it).
+ if (OriginalEnv) ::setenv("HOME", OriginalEnv, 1);
+}
+#endif
+
TEST(Support, UserCacheDirectory) {
SmallString<13> CacheDir;
SmallString<20> CacheDir2;
@@ -496,6 +528,41 @@ TEST_F(FileSystemTest, Unique) {
ASSERT_NO_ERROR(fs::remove(TempPath));
}
+TEST_F(FileSystemTest, RealPath) {
+ ASSERT_NO_ERROR(
+ fs::create_directories(Twine(TestDirectory) + "/test1/test2/test3"));
+ ASSERT_TRUE(fs::exists(Twine(TestDirectory) + "/test1/test2/test3"));
+
+ SmallString<64> RealBase;
+ SmallString<64> Expected;
+ SmallString<64> Actual;
+
+ // TestDirectory itself might be under a symlink or have been specified with
+ // a different case than the existing temp directory. In such cases real_path
+ // on the concatenated path will differ in the TestDirectory portion from
+ // how we specified it. Make sure to compare against the real_path of the
+ // TestDirectory, and not just the value of TestDirectory.
+ ASSERT_NO_ERROR(fs::real_path(TestDirectory, RealBase));
+ path::native(Twine(RealBase) + "/test1/test2", Expected);
+
+ ASSERT_NO_ERROR(fs::real_path(
+ Twine(TestDirectory) + "/././test1/../test1/test2/./test3/..", Actual));
+
+ EXPECT_EQ(Expected, Actual);
+
+ SmallString<64> HomeDir;
+ bool Result = llvm::sys::path::home_directory(HomeDir);
+ if (Result) {
+ ASSERT_NO_ERROR(fs::real_path(HomeDir, Expected));
+ ASSERT_NO_ERROR(fs::real_path("~", Actual, true));
+ EXPECT_EQ(Expected, Actual);
+ ASSERT_NO_ERROR(fs::real_path("~/", Actual, true));
+ EXPECT_EQ(Expected, Actual);
+ }
+
+ ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/test1"));
+}
+
TEST_F(FileSystemTest, TempFiles) {
// Create a temp file.
int FileDescriptor;
@@ -740,6 +807,118 @@ TEST_F(FileSystemTest, DirectoryIteration) {
ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel"));
}
+#ifdef LLVM_ON_UNIX
+TEST_F(FileSystemTest, BrokenSymlinkDirectoryIteration) {
+ // Create a known hierarchy to recurse over.
+ ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) + "/symlink"));
+ ASSERT_NO_ERROR(
+ fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/a"));
+ ASSERT_NO_ERROR(
+ fs::create_directories(Twine(TestDirectory) + "/symlink/b/bb"));
+ ASSERT_NO_ERROR(
+ fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/b/ba"));
+ ASSERT_NO_ERROR(
+ fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/b/bc"));
+ ASSERT_NO_ERROR(
+ fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/c"));
+ ASSERT_NO_ERROR(
+ fs::create_directories(Twine(TestDirectory) + "/symlink/d/dd/ddd"));
+ ASSERT_NO_ERROR(fs::create_link(Twine(TestDirectory) + "/symlink/d/dd",
+ Twine(TestDirectory) + "/symlink/d/da"));
+ ASSERT_NO_ERROR(
+ fs::create_link("no_such_file", Twine(TestDirectory) + "/symlink/e"));
+
+ typedef std::vector<std::string> v_t;
+ v_t visited;
+
+ // The directory iterator doesn't stat the file, so we should be able to
+ // iterate over the whole directory.
+ std::error_code ec;
+ for (fs::directory_iterator i(Twine(TestDirectory) + "/symlink", ec), e;
+ i != e; i.increment(ec)) {
+ ASSERT_NO_ERROR(ec);
+ visited.push_back(path::filename(i->path()));
+ }
+ std::sort(visited.begin(), visited.end());
+ v_t expected = {"a", "b", "c", "d", "e"};
+ ASSERT_TRUE(visited.size() == expected.size());
+ ASSERT_TRUE(std::equal(visited.begin(), visited.end(), expected.begin()));
+ visited.clear();
+
+ // The recursive directory iterator has to stat the file, so we need to skip
+ // the broken symlinks.
+ for (fs::recursive_directory_iterator
+ i(Twine(TestDirectory) + "/symlink", ec),
+ e;
+ i != e; i.increment(ec)) {
+ ASSERT_NO_ERROR(ec);
+
+ fs::file_status status;
+ if (i->status(status) ==
+ std::make_error_code(std::errc::no_such_file_or_directory)) {
+ i.no_push();
+ continue;
+ }
+
+ visited.push_back(path::filename(i->path()));
+ }
+ std::sort(visited.begin(), visited.end());
+ expected = {"b", "bb", "d", "da", "dd", "ddd", "ddd"};
+ ASSERT_TRUE(visited.size() == expected.size());
+ ASSERT_TRUE(std::equal(visited.begin(), visited.end(), expected.begin()));
+ visited.clear();
+
+ // This recursive directory iterator doesn't follow symlinks, so we don't need
+ // to skip them.
+ for (fs::recursive_directory_iterator
+ i(Twine(TestDirectory) + "/symlink", ec, /*follow_symlinks=*/false),
+ e;
+ i != e; i.increment(ec)) {
+ ASSERT_NO_ERROR(ec);
+ visited.push_back(path::filename(i->path()));
+ }
+ std::sort(visited.begin(), visited.end());
+ expected = {"a", "b", "ba", "bb", "bc", "c", "d", "da", "dd", "ddd", "e"};
+ ASSERT_TRUE(visited.size() == expected.size());
+ ASSERT_TRUE(std::equal(visited.begin(), visited.end(), expected.begin()));
+
+ ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/symlink"));
+}
+#endif
+
+TEST_F(FileSystemTest, Remove) {
+ SmallString<64> BaseDir;
+ SmallString<64> Paths[4];
+ int fds[4];
+ ASSERT_NO_ERROR(fs::createUniqueDirectory("fs_remove", BaseDir));
+
+ ASSERT_NO_ERROR(fs::create_directories(Twine(BaseDir) + "/foo/bar/baz"));
+ ASSERT_NO_ERROR(fs::create_directories(Twine(BaseDir) + "/foo/bar/buzz"));
+ ASSERT_NO_ERROR(fs::createUniqueFile(
+ Twine(BaseDir) + "/foo/bar/baz/%%%%%%.tmp", fds[0], Paths[0]));
+ ASSERT_NO_ERROR(fs::createUniqueFile(
+ Twine(BaseDir) + "/foo/bar/baz/%%%%%%.tmp", fds[1], Paths[1]));
+ ASSERT_NO_ERROR(fs::createUniqueFile(
+ Twine(BaseDir) + "/foo/bar/buzz/%%%%%%.tmp", fds[2], Paths[2]));
+ ASSERT_NO_ERROR(fs::createUniqueFile(
+ Twine(BaseDir) + "/foo/bar/buzz/%%%%%%.tmp", fds[3], Paths[3]));
+
+ for (int fd : fds)
+ ::close(fd);
+
+ EXPECT_TRUE(fs::exists(Twine(BaseDir) + "/foo/bar/baz"));
+ EXPECT_TRUE(fs::exists(Twine(BaseDir) + "/foo/bar/buzz"));
+ EXPECT_TRUE(fs::exists(Paths[0]));
+ EXPECT_TRUE(fs::exists(Paths[1]));
+ EXPECT_TRUE(fs::exists(Paths[2]));
+ EXPECT_TRUE(fs::exists(Paths[3]));
+
+ ASSERT_NO_ERROR(fs::remove_directories("D:/footest"));
+
+ ASSERT_NO_ERROR(fs::remove_directories(BaseDir));
+ ASSERT_FALSE(fs::exists(BaseDir));
+}
+
const char archive[] = "!<arch>\x0A";
const char bitcode[] = "\xde\xc0\x17\x0b";
const char coff_object[] = "\x00\x00......";
@@ -863,6 +1042,20 @@ TEST_F(FileSystemTest, Resize) {
ASSERT_NO_ERROR(fs::remove(TempPath));
}
+TEST_F(FileSystemTest, MD5) {
+ int FD;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath));
+ StringRef Data("abcdefghijklmnopqrstuvwxyz");
+ write(FD, Data.data(), Data.size());
+ lseek(FD, 0, SEEK_SET);
+ auto Hash = fs::md5_contents(FD);
+ ::close(FD);
+ ASSERT_NO_ERROR(Hash.getError());
+
+ EXPECT_STREQ("c3fcd3d76192e4007dfb496cca67e13b", Hash->digest().c_str());
+}
+
TEST_F(FileSystemTest, FileMapping) {
// Create a temp file.
int FileDescriptor;
@@ -906,40 +1099,50 @@ TEST_F(FileSystemTest, FileMapping) {
}
TEST(Support, NormalizePath) {
+ using TestTuple = std::tuple<const char *, const char *, const char *>;
+ std::vector<TestTuple> Tests;
+ Tests.emplace_back("a", "a", "a");
+ Tests.emplace_back("a/b", "a\\b", "a/b");
+ Tests.emplace_back("a\\b", "a\\b", "a/b");
+ Tests.emplace_back("a\\\\b", "a\\\\b", "a\\\\b");
+ Tests.emplace_back("\\a", "\\a", "/a");
+ Tests.emplace_back("a\\", "a\\", "a/");
+
+ for (auto &T : Tests) {
+ SmallString<64> Win(std::get<0>(T));
+ SmallString<64> Posix(Win);
+ path::native(Win, path::Style::windows);
+ path::native(Posix, path::Style::posix);
+ EXPECT_EQ(std::get<1>(T), Win);
+ EXPECT_EQ(std::get<2>(T), Posix);
+ }
+
#if defined(LLVM_ON_WIN32)
-#define EXPECT_PATH_IS(path__, windows__, not_windows__) \
- EXPECT_EQ(path__, windows__);
-#else
-#define EXPECT_PATH_IS(path__, windows__, not_windows__) \
- EXPECT_EQ(path__, not_windows__);
+ SmallString<64> PathHome;
+ path::home_directory(PathHome);
+
+ const char *Path7a = "~/aaa";
+ SmallString<64> Path7(Path7a);
+ path::native(Path7);
+ EXPECT_TRUE(Path7.endswith("\\aaa"));
+ EXPECT_TRUE(Path7.startswith(PathHome));
+ EXPECT_EQ(Path7.size(), PathHome.size() + strlen(Path7a + 1));
+
+ const char *Path8a = "~";
+ SmallString<64> Path8(Path8a);
+ path::native(Path8);
+ EXPECT_EQ(Path8, PathHome);
+
+ const char *Path9a = "~aaa";
+ SmallString<64> Path9(Path9a);
+ path::native(Path9);
+ EXPECT_EQ(Path9, "~aaa");
+
+ const char *Path10a = "aaa/~/b";
+ SmallString<64> Path10(Path10a);
+ path::native(Path10);
+ EXPECT_EQ(Path10, "aaa\\~\\b");
#endif
-
- SmallString<64> Path1("a");
- SmallString<64> Path2("a/b");
- SmallString<64> Path3("a\\b");
- SmallString<64> Path4("a\\\\b");
- SmallString<64> Path5("\\a");
- SmallString<64> Path6("a\\");
-
- path::native(Path1);
- EXPECT_PATH_IS(Path1, "a", "a");
-
- path::native(Path2);
- EXPECT_PATH_IS(Path2, "a\\b", "a/b");
-
- path::native(Path3);
- EXPECT_PATH_IS(Path3, "a\\b", "a/b");
-
- path::native(Path4);
- EXPECT_PATH_IS(Path4, "a\\\\b", "a\\\\b");
-
- path::native(Path5);
- EXPECT_PATH_IS(Path5, "\\a", "/a");
-
- path::native(Path6);
- EXPECT_PATH_IS(Path6, "a\\", "a/");
-
-#undef EXPECT_PATH_IS
}
TEST(Support, RemoveLeadingDotSlash) {
@@ -952,43 +1155,48 @@ TEST(Support, RemoveLeadingDotSlash) {
EXPECT_EQ(Path2, "");
}
-static std::string remove_dots(StringRef path,
- bool remove_dot_dot) {
+static std::string remove_dots(StringRef path, bool remove_dot_dot,
+ path::Style style) {
SmallString<256> buffer(path);
- path::remove_dots(buffer, remove_dot_dot);
+ path::remove_dots(buffer, remove_dot_dot, style);
return buffer.str();
}
TEST(Support, RemoveDots) {
-#if defined(LLVM_ON_WIN32)
- EXPECT_EQ("foolz\\wat", remove_dots(".\\.\\\\foolz\\wat", false));
- EXPECT_EQ("", remove_dots(".\\\\\\\\\\", false));
-
- EXPECT_EQ("a\\..\\b\\c", remove_dots(".\\a\\..\\b\\c", false));
- EXPECT_EQ("b\\c", remove_dots(".\\a\\..\\b\\c", true));
- EXPECT_EQ("c", remove_dots(".\\.\\c", true));
- EXPECT_EQ("..\\a\\c", remove_dots("..\\a\\b\\..\\c", true));
- EXPECT_EQ("..\\..\\a\\c", remove_dots("..\\..\\a\\b\\..\\c", true));
+ EXPECT_EQ("foolz\\wat",
+ remove_dots(".\\.\\\\foolz\\wat", false, path::Style::windows));
+ EXPECT_EQ("", remove_dots(".\\\\\\\\\\", false, path::Style::windows));
+
+ EXPECT_EQ("a\\..\\b\\c",
+ remove_dots(".\\a\\..\\b\\c", false, path::Style::windows));
+ EXPECT_EQ("b\\c", remove_dots(".\\a\\..\\b\\c", true, path::Style::windows));
+ EXPECT_EQ("c", remove_dots(".\\.\\c", true, path::Style::windows));
+ EXPECT_EQ("..\\a\\c",
+ remove_dots("..\\a\\b\\..\\c", true, path::Style::windows));
+ EXPECT_EQ("..\\..\\a\\c",
+ remove_dots("..\\..\\a\\b\\..\\c", true, path::Style::windows));
SmallString<64> Path1(".\\.\\c");
- EXPECT_TRUE(path::remove_dots(Path1, true));
- EXPECT_EQ("c", Path1);
-#else
- EXPECT_EQ("foolz/wat", remove_dots("././/foolz/wat", false));
- EXPECT_EQ("", remove_dots("./////", false));
-
- EXPECT_EQ("a/../b/c", remove_dots("./a/../b/c", false));
- EXPECT_EQ("b/c", remove_dots("./a/../b/c", true));
- EXPECT_EQ("c", remove_dots("././c", true));
- EXPECT_EQ("../a/c", remove_dots("../a/b/../c", true));
- EXPECT_EQ("../../a/c", remove_dots("../../a/b/../c", true));
- EXPECT_EQ("/a/c", remove_dots("/../../a/c", true));
- EXPECT_EQ("/a/c", remove_dots("/../a/b//../././/c", true));
-
- SmallString<64> Path1("././c");
- EXPECT_TRUE(path::remove_dots(Path1, true));
+ EXPECT_TRUE(path::remove_dots(Path1, true, path::Style::windows));
EXPECT_EQ("c", Path1);
-#endif
+
+ EXPECT_EQ("foolz/wat",
+ remove_dots("././/foolz/wat", false, path::Style::posix));
+ EXPECT_EQ("", remove_dots("./////", false, path::Style::posix));
+
+ EXPECT_EQ("a/../b/c", remove_dots("./a/../b/c", false, path::Style::posix));
+ EXPECT_EQ("b/c", remove_dots("./a/../b/c", true, path::Style::posix));
+ EXPECT_EQ("c", remove_dots("././c", true, path::Style::posix));
+ EXPECT_EQ("../a/c", remove_dots("../a/b/../c", true, path::Style::posix));
+ EXPECT_EQ("../../a/c",
+ remove_dots("../../a/b/../c", true, path::Style::posix));
+ EXPECT_EQ("/a/c", remove_dots("/../../a/c", true, path::Style::posix));
+ EXPECT_EQ("/a/c",
+ remove_dots("/../a/b//../././/c", true, path::Style::posix));
+
+ SmallString<64> Path2("././c");
+ EXPECT_TRUE(path::remove_dots(Path2, true, path::Style::posix));
+ EXPECT_EQ("c", Path2);
}
TEST(Support, ReplacePathPrefix) {
@@ -1135,4 +1343,198 @@ TEST_F(FileSystemTest, OpenFileForRead) {
::close(FileDescriptor);
}
+
+TEST_F(FileSystemTest, set_current_path) {
+ SmallString<128> path;
+
+ ASSERT_NO_ERROR(fs::current_path(path));
+ ASSERT_NE(TestDirectory, path);
+
+ struct RestorePath {
+ SmallString<128> path;
+ RestorePath(const SmallString<128> &path) : path(path) {}
+ ~RestorePath() { fs::set_current_path(path); }
+ } restore_path(path);
+
+ ASSERT_NO_ERROR(fs::set_current_path(TestDirectory));
+
+ ASSERT_NO_ERROR(fs::current_path(path));
+
+ fs::UniqueID D1, D2;
+ ASSERT_NO_ERROR(fs::getUniqueID(TestDirectory, D1));
+ ASSERT_NO_ERROR(fs::getUniqueID(path, D2));
+ ASSERT_EQ(D1, D2) << "D1: " << TestDirectory << "\nD2: " << path;
+}
+
+TEST_F(FileSystemTest, permissions) {
+ int FD;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath));
+ FileRemover Cleanup(TempPath);
+
+ // Make sure it exists.
+ ASSERT_TRUE(fs::exists(Twine(TempPath)));
+
+ auto CheckPermissions = [&](fs::perms Expected) {
+ ErrorOr<fs::perms> Actual = fs::getPermissions(TempPath);
+ return Actual && *Actual == Expected;
+ };
+
+ std::error_code NoError;
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_all), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read | fs::all_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_read | fs::all_exe));
+
+#if defined(LLVM_ON_WIN32)
+ fs::perms ReadOnly = fs::all_read | fs::all_exe;
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::no_perms), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_read), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_write), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_all), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_read), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_write), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_all), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_read), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_write), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_all), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_write), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_gid_on_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::sticky_bit), NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe |
+ fs::set_gid_on_exe |
+ fs::sticky_bit),
+ NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, ReadOnly | fs::set_uid_on_exe |
+ fs::set_gid_on_exe |
+ fs::sticky_bit),
+ NoError);
+ EXPECT_TRUE(CheckPermissions(ReadOnly));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_perms), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_all));
+#else
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::no_perms), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::no_perms));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_read), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::owner_read));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_write), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::owner_write));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::owner_exe));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::owner_all), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::owner_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_read), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::group_read));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_write), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::group_write));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::group_exe));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::group_all), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::group_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_read), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::others_read));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_write), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::others_write));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::others_exe));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::others_all), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::others_all));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_read));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_write), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_write));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_exe));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::set_uid_on_exe));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_gid_on_exe), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::set_gid_on_exe));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::sticky_bit), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::sticky_bit));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::set_uid_on_exe |
+ fs::set_gid_on_exe |
+ fs::sticky_bit),
+ NoError);
+ EXPECT_TRUE(CheckPermissions(fs::set_uid_on_exe | fs::set_gid_on_exe |
+ fs::sticky_bit));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_read | fs::set_uid_on_exe |
+ fs::set_gid_on_exe |
+ fs::sticky_bit),
+ NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_read | fs::set_uid_on_exe |
+ fs::set_gid_on_exe | fs::sticky_bit));
+
+ EXPECT_EQ(fs::setPermissions(TempPath, fs::all_perms), NoError);
+ EXPECT_TRUE(CheckPermissions(fs::all_perms));
+#endif
+}
+
} // anonymous namespace
diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp
index 886ead8305bc..3926ceb92b3e 100644
--- a/unittests/Support/ProgramTest.cpp
+++ b/unittests/Support/ProgramTest.cpp
@@ -87,6 +87,7 @@ protected:
EXPECT_TRUE(convStatus);
return EnvStorage.back().c_str();
#else
+ (void)this;
return Var;
#endif
};
diff --git a/unittests/Support/TargetParserTest.cpp b/unittests/Support/TargetParserTest.cpp
index a3d806f76fb5..f0bfe7dbde96 100644
--- a/unittests/Support/TargetParserTest.cpp
+++ b/unittests/Support/TargetParserTest.cpp
@@ -17,17 +17,17 @@ using namespace llvm;
namespace {
const char *ARMArch[] = {
- "armv2", "armv2a", "armv3", "armv3m", "armv4",
- "armv4t", "armv5", "armv5t", "armv5e", "armv5te",
- "armv5tej", "armv6", "armv6j", "armv6k", "armv6hl",
- "armv6t2", "armv6kz", "armv6z", "armv6zk", "armv6-m",
- "armv6m", "armv6sm", "armv6s-m", "armv7-a", "armv7",
- "armv7a", "armv7hl", "armv7l", "armv7-r", "armv7r",
- "armv7-m", "armv7m", "armv7k", "armv7s", "armv7e-m",
- "armv7em", "armv8-a", "armv8", "armv8a", "armv8.1-a",
- "armv8.1a", "armv8.2-a", "armv8.2a", "armv8-r", "armv8r",
- "armv8-m.base", "armv8m.base", "armv8-m.main", "armv8m.main", "iwmmxt",
- "iwmmxt2", "xscale"};
+ "armv2", "armv2a", "armv3", "armv3m", "armv4",
+ "armv4t", "armv5", "armv5t", "armv5e", "armv5te",
+ "armv5tej", "armv6", "armv6j", "armv6k", "armv6hl",
+ "armv6t2", "armv6kz", "armv6z", "armv6zk", "armv6-m",
+ "armv6m", "armv6sm", "armv6s-m", "armv7-a", "armv7",
+ "armv7a", "armv7ve", "armv7hl", "armv7l", "armv7-r",
+ "armv7r", "armv7-m", "armv7m", "armv7k", "armv7s",
+ "armv7e-m", "armv7em", "armv8-a", "armv8", "armv8a",
+ "armv8.1-a", "armv8.1a", "armv8.2-a", "armv8.2a", "armv8-r",
+ "armv8r", "armv8-m.base", "armv8m.base", "armv8-m.main", "armv8m.main",
+ "iwmmxt", "iwmmxt2", "xscale"};
bool testARMCPU(StringRef CPUName, StringRef ExpectedArch,
StringRef ExpectedFPU, unsigned ExpectedFlags,
@@ -246,6 +246,10 @@ TEST(TargetParserTest, testARMCPU) {
ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIV | ARM::AEK_DSP,
"8-A"));
+ EXPECT_TRUE(testARMCPU("cortex-m23", "armv8-m.base", "none",
+ ARM::AEK_HWDIV, "8-M.Baseline"));
+ EXPECT_TRUE(testARMCPU("cortex-m33", "armv8-m.main", "fpv5-sp-d16",
+ ARM::AEK_HWDIV | ARM::AEK_DSP, "8-M.Mainline"));
EXPECT_TRUE(testARMCPU("iwmmxt", "iwmmxt", "none",
ARM::AEK_NONE, "iwmmxt"));
EXPECT_TRUE(testARMCPU("xscale", "xscale", "none",
@@ -311,6 +315,9 @@ TEST(TargetParserTest, testARMArch) {
testARMArch("armv7-a", "cortex-a8", "v7",
ARMBuildAttrs::CPUArch::v7));
EXPECT_TRUE(
+ testARMArch("armv7ve", "generic", "v7ve",
+ ARMBuildAttrs::CPUArch::v7));
+ EXPECT_TRUE(
testARMArch("armv7-r", "cortex-r4", "v7r",
ARMBuildAttrs::CPUArch::v7));
EXPECT_TRUE(
@@ -498,12 +505,12 @@ TEST(TargetParserTest, ARMparseHWDiv) {
TEST(TargetParserTest, ARMparseArchEndianAndISA) {
const char *Arch[] = {
- "v2", "v2a", "v3", "v3m", "v4", "v4t", "v5", "v5t",
- "v5e", "v5te", "v5tej", "v6", "v6j", "v6k", "v6hl", "v6t2",
- "v6kz", "v6z", "v6zk", "v6-m", "v6m", "v6sm", "v6s-m", "v7-a",
- "v7", "v7a", "v7hl", "v7l", "v7-r", "v7r", "v7-m", "v7m",
- "v7k", "v7s", "v7e-m", "v7em", "v8-a", "v8", "v8a", "v8.1-a",
- "v8.1a", "v8.2-a", "v8.2a", "v8-r"};
+ "v2", "v2a", "v3", "v3m", "v4", "v4t", "v5", "v5t",
+ "v5e", "v5te", "v5tej", "v6", "v6j", "v6k", "v6hl", "v6t2",
+ "v6kz", "v6z", "v6zk", "v6-m", "v6m", "v6sm", "v6s-m", "v7-a",
+ "v7", "v7a", "v7ve", "v7hl", "v7l", "v7-r", "v7r", "v7-m",
+ "v7m", "v7k", "v7s", "v7e-m", "v7em", "v8-a", "v8", "v8a",
+ "v8.1-a", "v8.1a", "v8.2-a", "v8.2a", "v8-r"};
for (unsigned i = 0; i < array_lengthof(Arch); i++) {
std::string arm_1 = "armeb" + (std::string)(Arch[i]);
@@ -555,6 +562,7 @@ TEST(TargetParserTest, ARMparseArchProfile) {
EXPECT_EQ(ARM::PK_R, ARM::parseArchProfile(ARMArch[i]));
continue;
case ARM::AK_ARMV7A:
+ case ARM::AK_ARMV7VE:
case ARM::AK_ARMV7K:
case ARM::AK_ARMV8A:
case ARM::AK_ARMV8_1A:
@@ -635,8 +643,29 @@ TEST(TargetParserTest, testAArch64CPU) {
"kryo", "armv8-a", "crypto-neon-fp-armv8",
AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_SIMD, "8-A"));
EXPECT_TRUE(testAArch64CPU(
- "vulcan", "armv8.1-a", "crypto-neon-fp-armv8",
- AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_SIMD, "8.1-A"));
+ "thunderx2t99", "armv8.1-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_LSE |
+ AArch64::AEK_SIMD, "8.1-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "thunderx", "armv8-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_SIMD |
+ AArch64::AEK_FP | AArch64::AEK_PROFILE,
+ "8-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "thunderxt81", "armv8-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_SIMD |
+ AArch64::AEK_FP | AArch64::AEK_PROFILE,
+ "8-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "thunderxt83", "armv8-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_SIMD |
+ AArch64::AEK_FP | AArch64::AEK_PROFILE,
+ "8-A"));
+ EXPECT_TRUE(testAArch64CPU(
+ "thunderxt88", "armv8-a", "crypto-neon-fp-armv8",
+ AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_SIMD |
+ AArch64::AEK_FP | AArch64::AEK_PROFILE,
+ "8-A"));
}
bool testAArch64Arch(StringRef Arch, StringRef DefaultCPU, StringRef SubArch,
@@ -672,7 +701,11 @@ TEST(TargetParserTest, testAArch64Extension) {
EXPECT_FALSE(testAArch64Extension("cyclone", 0, "ras"));
EXPECT_FALSE(testAArch64Extension("exynos-m1", 0, "ras"));
EXPECT_FALSE(testAArch64Extension("kryo", 0, "ras"));
- EXPECT_FALSE(testAArch64Extension("vulcan", 0, "ras"));
+ EXPECT_FALSE(testAArch64Extension("thunderx2t99", 0, "ras"));
+ EXPECT_FALSE(testAArch64Extension("thunderx", 0, "lse"));
+ EXPECT_FALSE(testAArch64Extension("thunderxt81", 0, "lse"));
+ EXPECT_FALSE(testAArch64Extension("thunderxt83", 0, "lse"));
+ EXPECT_FALSE(testAArch64Extension("thunderxt88", 0, "lse"));
EXPECT_FALSE(testAArch64Extension(
"generic", static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8A), "ras"));
diff --git a/unittests/Support/ThreadPool.cpp b/unittests/Support/ThreadPool.cpp
index 8e03aacfb1e0..0da33ad50c07 100644
--- a/unittests/Support/ThreadPool.cpp
+++ b/unittests/Support/ThreadPool.cpp
@@ -90,7 +90,7 @@ TEST_F(ThreadPoolTest, AsyncBarrier) {
ThreadPool Pool;
for (size_t i = 0; i < 5; ++i) {
- Pool.async([this, &checked_in, i] {
+ Pool.async([this, &checked_in] {
waitForMainThread();
++checked_in;
});
@@ -154,7 +154,7 @@ TEST_F(ThreadPoolTest, PoolDestruction) {
{
ThreadPool Pool;
for (size_t i = 0; i < 5; ++i) {
- Pool.async([this, &checked_in, i] {
+ Pool.async([this, &checked_in] {
waitForMainThread();
++checked_in;
});
diff --git a/unittests/Support/TrailingObjectsTest.cpp b/unittests/Support/TrailingObjectsTest.cpp
index cb5c47d1b25b..23acc54d2376 100644
--- a/unittests/Support/TrailingObjectsTest.cpp
+++ b/unittests/Support/TrailingObjectsTest.cpp
@@ -236,3 +236,24 @@ TEST(TrailingObjects, Realignment) {
reinterpret_cast<char *>(C + 1) + 1, alignof(long))));
}
}
+
+// Test the use of TrailingObjects with a template class. This
+// previously failed to compile due to a bug in MSVC's member access
+// control/lookup handling for OverloadToken.
+template <typename Derived>
+class Class5Tmpl : private llvm::TrailingObjects<Derived, float, int> {
+ using TrailingObjects = typename llvm::TrailingObjects<Derived, float>;
+ friend TrailingObjects;
+
+ size_t numTrailingObjects(
+ typename TrailingObjects::template OverloadToken<float>) const {
+ return 1;
+ }
+
+ size_t numTrailingObjects(
+ typename TrailingObjects::template OverloadToken<int>) const {
+ return 2;
+ }
+};
+
+class Class5 : public Class5Tmpl<Class5> {};
diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp
index dc7c5d47cba9..5a0280c8ca5b 100644
--- a/unittests/Support/YAMLIOTest.cpp
+++ b/unittests/Support/YAMLIOTest.cpp
@@ -1740,7 +1740,7 @@ TEST(YAMLIO, TestFlagsReadError) {
//
// Test error handling reading built-in uint8_t type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint8_t)
TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
std::vector<uint8_t> seq;
Input yin("---\n"
@@ -1759,7 +1759,7 @@ TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
//
// Test error handling reading built-in uint16_t type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint16_t)
TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
std::vector<uint16_t> seq;
Input yin("---\n"
@@ -1778,7 +1778,7 @@ TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
//
// Test error handling reading built-in uint32_t type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
std::vector<uint32_t> seq;
Input yin("---\n"
@@ -1797,7 +1797,7 @@ TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
//
// Test error handling reading built-in uint64_t type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint64_t)
TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
std::vector<uint64_t> seq;
Input yin("---\n"
@@ -1816,7 +1816,7 @@ TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
//
// Test error handling reading built-in int8_t type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(int8_t)
TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
std::vector<int8_t> seq;
Input yin("---\n"
@@ -1854,7 +1854,7 @@ TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
//
// Test error handling reading built-in int16_t type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(int16_t)
TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
std::vector<int16_t> seq;
Input yin("---\n"
@@ -1893,7 +1893,7 @@ TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
//
// Test error handling reading built-in int32_t type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(int32_t)
TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
std::vector<int32_t> seq;
Input yin("---\n"
@@ -1931,7 +1931,7 @@ TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
//
// Test error handling reading built-in int64_t type
//
-LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(int64_t)
TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
std::vector<int64_t> seq;
Input yin("---\n"
diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp
index f87d2f60d169..777e555949ee 100644
--- a/unittests/Support/raw_ostream_test.cpp
+++ b/unittests/Support/raw_ostream_test.cpp
@@ -9,6 +9,7 @@
#include "gtest/gtest.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -330,4 +331,11 @@ TEST(raw_ostreamTest, FormattedHexBytes) {
"0007: 68 69 6a 6b 6c |hijkl|",
format_bytes_with_ascii_str(B.take_front(12), 0, 7, 1));
}
+
+TEST(raw_fd_ostreamTest, multiple_raw_fd_ostream_to_stdout) {
+ std::error_code EC;
+
+ { raw_fd_ostream("-", EC, sys::fs::OpenFlags::F_None); }
+ { raw_fd_ostream("-", EC, sys::fs::OpenFlags::F_None); }
+}
}