summaryrefslogtreecommitdiff
path: root/unittests/Support
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/Support')
-rw-r--r--unittests/Support/BlockFrequencyTest.cpp156
-rw-r--r--unittests/Support/CMakeLists.txt9
-rw-r--r--unittests/Support/Casting.cpp25
-rw-r--r--unittests/Support/CommandLineTest.cpp43
-rw-r--r--unittests/Support/CompressionTest.cpp6
-rw-r--r--unittests/Support/ConstantRangeTest.cpp3
-rw-r--r--unittests/Support/ConvertUTFTest.cpp65
-rw-r--r--unittests/Support/ErrorOrTest.cpp38
-rw-r--r--unittests/Support/FileOutputBufferTest.cpp8
-rw-r--r--unittests/Support/IntegersSubsetTest.cpp326
-rw-r--r--unittests/Support/LockFileManagerTest.cpp48
-rw-r--r--unittests/Support/MD5Test.cpp60
-rw-r--r--unittests/Support/Makefile2
-rw-r--r--unittests/Support/ManagedStatic.cpp3
-rw-r--r--unittests/Support/MathExtrasTest.cpp119
-rw-r--r--unittests/Support/MemoryBufferTest.cpp77
-rw-r--r--unittests/Support/Path.cpp259
-rw-r--r--unittests/Support/ProcessTest.cpp30
-rw-r--r--unittests/Support/ProgramTest.cpp121
-rw-r--r--unittests/Support/RegexTest.cpp23
-rw-r--r--unittests/Support/SourceMgrTest.cpp174
-rw-r--r--unittests/Support/ThreadLocalTest.cpp38
-rw-r--r--unittests/Support/TimeValue.cpp23
-rw-r--r--unittests/Support/TimeValueTest.cpp39
-rw-r--r--unittests/Support/UnicodeTest.cpp93
-rw-r--r--unittests/Support/YAMLIOTest.cpp441
26 files changed, 1704 insertions, 525 deletions
diff --git a/unittests/Support/BlockFrequencyTest.cpp b/unittests/Support/BlockFrequencyTest.cpp
index ff66bc4e45aae..ffdea2c1790fc 100644
--- a/unittests/Support/BlockFrequencyTest.cpp
+++ b/unittests/Support/BlockFrequencyTest.cpp
@@ -13,6 +13,11 @@ TEST(BlockFrequencyTest, OneToZero) {
BranchProbability Prob(UINT32_MAX - 1, UINT32_MAX);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 0u);
+
+ Freq = BlockFrequency(1);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), 0u);
+ EXPECT_EQ(Remainder, UINT32_MAX - 1);
}
TEST(BlockFrequencyTest, OneToOne) {
@@ -20,6 +25,11 @@ TEST(BlockFrequencyTest, OneToOne) {
BranchProbability Prob(UINT32_MAX, UINT32_MAX);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 1u);
+
+ Freq = BlockFrequency(1);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), 1u);
+ EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, ThreeToOne) {
@@ -27,6 +37,11 @@ TEST(BlockFrequencyTest, ThreeToOne) {
BranchProbability Prob(3000000, 9000000);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 1u);
+
+ Freq = BlockFrequency(3);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), 1u);
+ EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, MaxToHalfMax) {
@@ -34,6 +49,11 @@ TEST(BlockFrequencyTest, MaxToHalfMax) {
BranchProbability Prob(UINT32_MAX / 2, UINT32_MAX);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 9223372034707292159ULL);
+
+ Freq = BlockFrequency(UINT64_MAX);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), 9223372034707292159ULL);
+ EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, BigToBig) {
@@ -43,6 +63,11 @@ TEST(BlockFrequencyTest, BigToBig) {
BranchProbability Prob(P, P);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), Big);
+
+ Freq = BlockFrequency(Big);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), Big);
+ EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, MaxToMax) {
@@ -50,6 +75,137 @@ TEST(BlockFrequencyTest, MaxToMax) {
BranchProbability Prob(UINT32_MAX, UINT32_MAX);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+
+ // This additionally makes sure if we have a value equal to our saturating
+ // value, we do not signal saturation if the result equals said value, but
+ // saturating does not occur.
+ Freq = BlockFrequency(UINT64_MAX);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+ EXPECT_EQ(Remainder, 0u);
+}
+
+TEST(BlockFrequencyTest, ScaleResultRemainderTest) {
+ struct {
+ uint64_t Freq;
+ uint32_t Prob[2];
+ uint64_t ExpectedFreq;
+ uint32_t ExpectedRemainder;
+ } Tests[80] = {
+ // Data for scaling that results in <= 64 bit division.
+ { 0x1423e2a50ULL, { 0x64819521, 0x7765dd13 }, 0x10f418889ULL, 0x92b9d25 },
+ { 0x35ef14ceULL, { 0x28ade3c7, 0x304532ae }, 0x2d73c33aULL, 0x2c0fd0b6 },
+ { 0xd03dbfbe24ULL, { 0x790079, 0xe419f3 }, 0x6e776fc1fdULL, 0x4a06dd },
+ { 0x21d67410bULL, { 0x302a9dc2, 0x3ddb4442 }, 0x1a5948fd6ULL, 0x265d1c2a },
+ { 0x8664aeadULL, { 0x3d523513, 0x403523b1 }, 0x805a04cfULL, 0x324c27b8 },
+ { 0x201db0cf4ULL, { 0x35112a7b, 0x79fc0c74 }, 0xdf8b07f6ULL, 0x490c1dc4 },
+ { 0x13f1e4430aULL, { 0x21c92bf, 0x21e63aae }, 0x13e0cba15ULL, 0x1df47c30 },
+ { 0x16c83229ULL, { 0x3793f66f, 0x53180dea }, 0xf3ce7b6ULL, 0x1d0c1b6b },
+ { 0xc62415be8ULL, { 0x9cc4a63, 0x4327ae9b }, 0x1ce8b71caULL, 0x3f2c696a },
+ { 0x6fac5e434ULL, { 0xe5f9170, 0x1115e10b }, 0x5df23dd4cULL, 0x4dafc7c },
+ { 0x1929375f2ULL, { 0x3a851375, 0x76c08456 }, 0xc662b082ULL, 0x343589ee },
+ { 0x243c89db6ULL, { 0x354ebfc0, 0x450ef197 }, 0x1bf8c1661ULL, 0x4948e49 },
+ { 0x310e9b31aULL, { 0x1b1b8acf, 0x2d3629f0 }, 0x1d69c93f9ULL, 0x73e3b96 },
+ { 0xa1fae921dULL, { 0xa7a098c, 0x10469f44 }, 0x684413d6cULL, 0x86a882c },
+ { 0xc1582d957ULL, { 0x498e061, 0x59856bc }, 0x9edc5f4e7ULL, 0x29b0653 },
+ { 0x57cfee75ULL, { 0x1d061dc3, 0x7c8bfc17 }, 0x1476a220ULL, 0x2383d33f },
+ { 0x139220080ULL, { 0x294a6c71, 0x2a2b07c9 }, 0x1329e1c76ULL, 0x7aa5da },
+ { 0x1665d353cULL, { 0x7080db5, 0xde0d75c }, 0xb590d9fbULL, 0x7ba8c38 },
+ { 0xe8f14541ULL, { 0x5188e8b2, 0x736527ef }, 0xa4971be5ULL, 0x6b612167 },
+ { 0x2f4775f29ULL, { 0x254ef0fe, 0x435fcf50 }, 0x1a2e449c1ULL, 0x28bbf5e },
+ { 0x27b85d8d7ULL, { 0x304c8220, 0x5de678f2 }, 0x146e3bef9ULL, 0x4b27097e },
+ { 0x1d362e36bULL, { 0x36c85b12, 0x37a66f55 }, 0x1cc19b8e6ULL, 0x688e828 },
+ { 0x155fd48c7ULL, { 0xf5894d, 0x1256108 }, 0x11e383602ULL, 0x111f0cb },
+ { 0xb5db2d15ULL, { 0x39bb26c5, 0x5bdcda3e }, 0x72499259ULL, 0x59c4939b },
+ { 0x153990298ULL, { 0x48921c09, 0x706eb817 }, 0xdb3268e8ULL, 0x66bb8a80 },
+ { 0x28a7c3ed7ULL, { 0x1f776fd7, 0x349f7a70 }, 0x184f73ae1ULL, 0x28910321 },
+ { 0x724dbeabULL, { 0x1bd149f5, 0x253a085e }, 0x5569c0b3ULL, 0xff8e2ed },
+ { 0xd8f0c513ULL, { 0x18c8cc4c, 0x1b72bad0 }, 0xc3e30643ULL, 0xd85e134 },
+ { 0x17ce3dcbULL, { 0x1e4c6260, 0x233b359e }, 0x1478f4afULL, 0x49ea31e },
+ { 0x1ce036ce0ULL, { 0x29e3c8af, 0x5318dd4a }, 0xe8e76196ULL, 0x11d5b9c4 },
+ { 0x1473ae2aULL, { 0x29b897ba, 0x2be29378 }, 0x13718185ULL, 0x6f93b2c },
+ { 0x1dd41aa68ULL, { 0x3d0a4441, 0x5a0e8f12 }, 0x1437b6bbfULL, 0x54b09ffa },
+ { 0x1b49e4a53ULL, { 0x3430c1fe, 0x5a204aed }, 0xfcd6852fULL, 0x15ad6ed7 },
+ { 0x217941b19ULL, { 0x12ced2bd, 0x21b68310 }, 0x12aca65b1ULL, 0x1b2a9565 },
+ { 0xac6a4dc8ULL, { 0x3ed68da8, 0x6fdca34c }, 0x60da926dULL, 0x22ff53e4 },
+ { 0x1c503a4e7ULL, { 0xfcbbd32, 0x11e48d17 }, 0x18fec7d38ULL, 0xa8aa816 },
+ { 0x1c885855ULL, { 0x213e919d, 0x25941897 }, 0x193de743ULL, 0x4ea09c },
+ { 0x29b9c168eULL, { 0x2b644aea, 0x45725ee7 }, 0x1a122e5d5ULL, 0xbee1099 },
+ { 0x806a33f2ULL, { 0x30a80a23, 0x5063733a }, 0x4db9a264ULL, 0x1eaed76e },
+ { 0x282afc96bULL, { 0x143ae554, 0x1a9863ff }, 0x1e8de5204ULL, 0x158d9020 },
+ // Data for scaling that results in > 64 bit division.
+ { 0x23ca5f2f672ca41cULL, { 0xecbc641, 0x111373f7 }, 0x1f0301e5e8295ab5ULL, 0xf627f79 },
+ { 0x5e4f2468142265e3ULL, { 0x1ddf5837, 0x32189233 }, 0x383ca7ba9fdd2c8cULL, 0x1c8f33e1 },
+ { 0x277a1a6f6b266bf6ULL, { 0x415d81a8, 0x61eb5e1e }, 0x1a5a3e1d41b30c0fULL, 0x29cde3ae },
+ { 0x1bdbb49a237035cbULL, { 0xea5bf17, 0x1d25ffb3 }, 0xdffc51c53d44b93ULL, 0x5170574 },
+ { 0x2bce6d29b64fb8ULL, { 0x3bfd5631, 0x7525c9bb }, 0x166ebedda7ac57ULL, 0x3026dfab },
+ { 0x3a02116103df5013ULL, { 0x2ee18a83, 0x3299aea8 }, 0x35be8922ab1e2a84ULL, 0x298d9919 },
+ { 0x7b5762390799b18cULL, { 0x12f8e5b9, 0x2563bcd4 }, 0x3e960077aca01209ULL, 0x93afeb8 },
+ { 0x69cfd72537021579ULL, { 0x4c35f468, 0x6a40feee }, 0x4be4cb3848be98a3ULL, 0x4ff96b9e },
+ { 0x49dfdf835120f1c1ULL, { 0x8cb3759, 0x559eb891 }, 0x79663f7120edadeULL, 0x51b1fb5b },
+ { 0x74b5be5c27676381ULL, { 0x47e4c5e0, 0x7c7b19ff }, 0x4367d2dff36a1028ULL, 0x7a7b5608 },
+ { 0x4f50f97075e7f431ULL, { 0x9a50a17, 0x11cd1185 }, 0x2af952b34c032df4ULL, 0xfddc6a3 },
+ { 0x2f8b0d712e393be4ULL, { 0x1487e386, 0x15aa356e }, 0x2d0df36478a776aaULL, 0x14e2564c },
+ { 0x224c1c75999d3deULL, { 0x3b2df0ea, 0x4523b100 }, 0x1d5b481d145f08aULL, 0x15145eec },
+ { 0x2bcbcea22a399a76ULL, { 0x28b58212, 0x48dd013e }, 0x187814d084c47cabULL, 0x3a38ebe2 },
+ { 0x1dbfca91257cb2d1ULL, { 0x1a8c04d9, 0x5e92502c }, 0x859cf7d00f77545ULL, 0x7431f4d },
+ { 0x7f20039b57cda935ULL, { 0xeccf651, 0x323f476e }, 0x25720cd976461a77ULL, 0x202817a3 },
+ { 0x40512c6a586aa087ULL, { 0x113b0423, 0x398c9eab }, 0x1341c03de8696a7eULL, 0x1e27284b },
+ { 0x63d802693f050a11ULL, { 0xf50cdd6, 0xfce2a44 }, 0x60c0177bb5e46846ULL, 0xf7ad89e },
+ { 0x2d956b422838de77ULL, { 0xb2d345b, 0x1321e557 }, 0x1aa0ed16b6aa5319ULL, 0xfe1a5ce },
+ { 0x5a1cdf0c1657bc91ULL, { 0x1d77bb0c, 0x1f991ff1 }, 0x54097ee94ff87560ULL, 0x11c4a26c },
+ { 0x3801b26d7e00176bULL, { 0xeed25da, 0x1a819d8b }, 0x1f89e96a3a639526ULL, 0xcd51e7c },
+ { 0x37655e74338e1e45ULL, { 0x300e170a, 0x5a1595fe }, 0x1d8cfb55fddc0441ULL, 0x3df05434 },
+ { 0x7b38703f2a84e6ULL, { 0x66d9053, 0xc79b6b9 }, 0x3f7d4c91774094ULL, 0x26d939e },
+ { 0x2245063c0acb3215ULL, { 0x30ce2f5b, 0x610e7271 }, 0x113b916468389235ULL, 0x1b588512 },
+ { 0x6bc195877b7b8a7eULL, { 0x392004aa, 0x4a24e60c }, 0x530594fb17db6ba5ULL, 0x35c0a5f0 },
+ { 0x40a3fde23c7b43dbULL, { 0x4e712195, 0x6553e56e }, 0x320a799bc76a466aULL, 0x5e23a5eb },
+ { 0x1d3dfc2866fbccbaULL, { 0x5075b517, 0x5fc42245 }, 0x18917f0061595bc3ULL, 0x3fcf4527 },
+ { 0x19aeb14045a61121ULL, { 0x1bf6edec, 0x707e2f4b }, 0x6626672a070bcc7ULL, 0x3607801f },
+ { 0x44ff90486c531e9fULL, { 0x66598a, 0x8a90dc }, 0x32f6f2b0525199b0ULL, 0x5ab576 },
+ { 0x3f3e7121092c5bcbULL, { 0x1c754df7, 0x5951a1b9 }, 0x14267f50b7ef375dULL, 0x221220a8 },
+ { 0x60e2dafb7e50a67eULL, { 0x4d96c66e, 0x65bd878d }, 0x49e31715ac393f8bULL, 0x4e97b195 },
+ { 0x656286667e0e6e29ULL, { 0x9d971a2, 0xacda23b }, 0x5c6ee315ead6cb4fULL, 0x516f5bd },
+ { 0x1114e0974255d507ULL, { 0x1c693, 0x2d6ff }, 0xaae42e4b35f6e60ULL, 0x8b65 },
+ { 0x508c8baf3a70ff5aULL, { 0x3b26b779, 0x6ad78745 }, 0x2c98387636c4b365ULL, 0x11dc6a51 },
+ { 0x5b47bc666bf1f9cfULL, { 0x10a87ed6, 0x187d358a }, 0x3e1767155848368bULL, 0xfb871c },
+ { 0x50954e3744460395ULL, { 0x7a42263, 0xcdaa048 }, 0x2fe739f0aee1fee1ULL, 0xb8add57 },
+ { 0x20020b406550dd8fULL, { 0x3318539, 0x42eead0 }, 0x186f326325fa346bULL, 0x10d3ae7 },
+ { 0x5bcb0b872439ffd5ULL, { 0x6f61fb2, 0x9af7344 }, 0x41fa1e3bec3c1b30ULL, 0x4fee45a },
+ { 0x7a670f365db87a53ULL, { 0x417e102, 0x3bb54c67 }, 0x8642a558304fd9eULL, 0x3b65f514 },
+ { 0x1ef0db1e7bab1cd0ULL, { 0x2b60cf38, 0x4188f78f }, 0x147ae0d6226b2ee6ULL, 0x336b6106 }
+ };
+
+ for (unsigned i = 0; i < 80; i++) {
+ BlockFrequency Freq(Tests[i].Freq);
+ uint32_t Remainder = Freq.scale(BranchProbability(Tests[i].Prob[0],
+ Tests[i].Prob[1]));
+ EXPECT_EQ(Tests[i].ExpectedFreq, Freq.getFrequency());
+ EXPECT_EQ(Tests[i].ExpectedRemainder, Remainder);
+ }
+}
+
+TEST(BlockFrequency, Divide) {
+ BlockFrequency Freq(0x3333333333333333ULL);
+ Freq /= BranchProbability(1, 2);
+ EXPECT_EQ(Freq.getFrequency(), 0x6666666666666666ULL);
+}
+
+TEST(BlockFrequencyTest, Saturate) {
+ BlockFrequency Freq(0x3333333333333333ULL);
+ Freq /= BranchProbability(100, 300);
+ EXPECT_EQ(Freq.getFrequency(), 0x9999999999999999ULL);
+ Freq /= BranchProbability(1, 2);
+ EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+
+ Freq = 0x1000000000000000ULL;
+ Freq /= BranchProbability(10000, 160000);
+ EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+
+ // Try to cheat the multiplication overflow check.
+ Freq = 0x00000001f0000001ull;
+ Freq /= BranchProbability(1000, 0xf000000f);
+ EXPECT_EQ(33506781356485509ULL, Freq.getFrequency());
}
TEST(BlockFrequencyTest, ProbabilityCompare) {
diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt
index e6cafbcaf158b..0abc2ffe1d9c8 100644
--- a/unittests/Support/CMakeLists.txt
+++ b/unittests/Support/CMakeLists.txt
@@ -12,22 +12,27 @@ add_llvm_unittest(SupportTests
CommandLineTest.cpp
CompressionTest.cpp
ConstantRangeTest.cpp
+ ConvertUTFTest.cpp
DataExtractorTest.cpp
EndianTest.cpp
ErrorOrTest.cpp
FileOutputBufferTest.cpp
- IntegersSubsetTest.cpp
LeakDetectorTest.cpp
+ LockFileManagerTest.cpp
ManagedStatic.cpp
MathExtrasTest.cpp
+ MD5Test.cpp
MemoryBufferTest.cpp
MemoryTest.cpp
Path.cpp
ProcessTest.cpp
ProgramTest.cpp
RegexTest.cpp
+ SourceMgrTest.cpp
SwapByteOrderTest.cpp
- TimeValue.cpp
+ ThreadLocalTest.cpp
+ TimeValueTest.cpp
+ UnicodeTest.cpp
ValueHandleTest.cpp
YAMLIOTest.cpp
YAMLParserTest.cpp
diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp
index 01583e43e29b4..362abeecd07ad 100644
--- a/unittests/Support/Casting.cpp
+++ b/unittests/Support/Casting.cpp
@@ -10,10 +10,15 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/User.h"
#include "gtest/gtest.h"
#include <cstdlib>
namespace llvm {
+// Used to test illegal cast. If a cast doesn't match any of the "real" ones,
+// it will match this one.
+struct IllegalCast;
+template <typename T> IllegalCast *cast(...) { return 0; }
// set up two example classes
// with conversion facility
@@ -60,10 +65,25 @@ foo *bar::naz() {
bar *fub();
+
+template <> struct simplify_type<foo> {
+ typedef int SimpleType;
+ static SimpleType getSimplifiedValue(foo &Val) { return 0; }
+};
+
} // End llvm namespace
using namespace llvm;
+
+// Test the peculiar behavior of Use in simplify_type.
+int Check1[is_same<simplify_type<Use>::SimpleType, Value *>::value ? 1 : -1];
+int Check2[is_same<simplify_type<Use *>::SimpleType, Value *>::value ? 1 : -1];
+
+// Test that a regular class behaves as expected.
+int Check3[is_same<simplify_type<foo>::SimpleType, int>::value ? 1 : -1];
+int Check4[is_same<simplify_type<foo *>::SimpleType, foo *>::value ? 1 : -1];
+
namespace {
const foo *null_foo = NULL;
@@ -203,3 +223,8 @@ TEST(CastingTest, InferredUpcastTakesPrecedence) {
} // end namespace inferred_upcasting
} // end anonymous namespace
+// Test that we reject casts of temporaries (and so the illegal cast gets used).
+namespace TemporaryCast {
+struct pod {};
+IllegalCast *testIllegalCast() { return cast<foo>(pod()); }
+}
diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp
index cd235d274e6c0..c54e1b9570f89 100644
--- a/unittests/Support/CommandLineTest.cpp
+++ b/unittests/Support/CommandLineTest.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Config/config.h"
#include "gtest/gtest.h"
@@ -118,4 +119,46 @@ TEST(CommandLineTest, UseOptionCategory) {
"Category.";
}
+class StrDupSaver : public cl::StringSaver {
+ const char *SaveString(const char *Str) LLVM_OVERRIDE {
+ return strdup(Str);
+ }
+};
+
+typedef void ParserFunction(StringRef Source, llvm::cl::StringSaver &Saver,
+ SmallVectorImpl<const char *> &NewArgv);
+
+
+void testCommandLineTokenizer(ParserFunction *parse, const char *Input,
+ const char *const Output[], size_t OutputSize) {
+ SmallVector<const char *, 0> Actual;
+ StrDupSaver Saver;
+ parse(Input, Saver, Actual);
+ EXPECT_EQ(OutputSize, Actual.size());
+ for (unsigned I = 0, E = Actual.size(); I != E; ++I) {
+ if (I < OutputSize)
+ EXPECT_STREQ(Output[I], Actual[I]);
+ free(const_cast<char *>(Actual[I]));
+ }
+}
+
+TEST(CommandLineTest, TokenizeGNUCommandLine) {
+ const char *Input = "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' "
+ "foo\"bar\"baz C:\\src\\foo.cpp \"C:\\src\\foo.cpp\"";
+ const char *const Output[] = { "foo bar", "foo bar", "foo bar", "foo\\bar",
+ "foobarbaz", "C:\\src\\foo.cpp",
+ "C:\\src\\foo.cpp" };
+ testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output,
+ array_lengthof(Output));
+}
+
+TEST(CommandLineTest, TokenizeWindowsCommandLine) {
+ const char *Input = "a\\b c\\\\d e\\\\\"f g\" h\\\"i j\\\\\\\"k \"lmn\" o pqr "
+ "\"st \\\"u\" \\v";
+ const char *const Output[] = { "a\\b", "c\\\\d", "e\\f g", "h\"i", "j\\\"k",
+ "lmn", "o", "pqr", "st \"u", "\\v" };
+ testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output,
+ array_lengthof(Output));
+}
+
} // anonymous namespace
diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp
index c8e2cd9f02b62..c0a9adadb7887 100644
--- a/unittests/Support/CompressionTest.cpp
+++ b/unittests/Support/CompressionTest.cpp
@@ -63,6 +63,12 @@ TEST(CompressionTest, Zlib) {
TestZlibCompression(BinaryDataStr, zlib::DefaultCompression);
}
+TEST(CompressionTest, ZlibCRC32) {
+ EXPECT_EQ(
+ 0x414FA339U,
+ zlib::crc32(StringRef("The quick brown fox jumps over the lazy dog")));
+}
+
#endif
}
diff --git a/unittests/Support/ConstantRangeTest.cpp b/unittests/Support/ConstantRangeTest.cpp
index 4d6bbf6f8402b..3e0a085ed1e7f 100644
--- a/unittests/Support/ConstantRangeTest.cpp
+++ b/unittests/Support/ConstantRangeTest.cpp
@@ -216,6 +216,9 @@ TEST_F(ConstantRangeTest, SExt) {
EXPECT_EQ(ConstantRange(APInt(8, 120), APInt(8, 140)).signExtend(16),
ConstantRange(APInt(16, -128), APInt(16, 128)));
+
+ EXPECT_EQ(ConstantRange(APInt(16, 0x0200), APInt(16, 0x8000)).signExtend(19),
+ ConstantRange(APInt(19, 0x0200), APInt(19, 0x8000)));
}
TEST_F(ConstantRangeTest, IntersectWith) {
diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp
new file mode 100644
index 0000000000000..13ea75b1573b5
--- /dev/null
+++ b/unittests/Support/ConvertUTFTest.cpp
@@ -0,0 +1,65 @@
+//===- llvm/unittest/Support/ConvertUTFTest.cpp - ConvertUTF tests --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ConvertUTF.h"
+#include "gtest/gtest.h"
+#include <string>
+
+using namespace llvm;
+
+TEST(ConvertUTFTest, ConvertUTF16LittleEndianToUTF8String) {
+ // Src is the look of disapproval.
+ static const char Src[] = "\xff\xfe\xa0\x0c_\x00\xa0\x0c";
+ ArrayRef<char> Ref(Src, sizeof(Src) - 1);
+ std::string Result;
+ bool Success = convertUTF16ToUTF8String(Ref, Result);
+ EXPECT_TRUE(Success);
+ std::string Expected("\xe0\xb2\xa0_\xe0\xb2\xa0");
+ EXPECT_EQ(Expected, Result);
+}
+
+TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) {
+ // Src is the look of disapproval.
+ static const char Src[] = "\xfe\xff\x0c\xa0\x00_\x0c\xa0";
+ ArrayRef<char> Ref(Src, sizeof(Src) - 1);
+ std::string Result;
+ bool Success = convertUTF16ToUTF8String(Ref, Result);
+ EXPECT_TRUE(Success);
+ std::string Expected("\xe0\xb2\xa0_\xe0\xb2\xa0");
+ EXPECT_EQ(Expected, Result);
+}
+
+TEST(ConvertUTFTest, OddLengthInput) {
+ std::string Result;
+ bool Success = convertUTF16ToUTF8String(ArrayRef<char>("xxxxx", 5), Result);
+ EXPECT_FALSE(Success);
+}
+
+TEST(ConvertUTFTest, Empty) {
+ std::string Result;
+ bool Success = convertUTF16ToUTF8String(ArrayRef<char>(), Result);
+ EXPECT_TRUE(Success);
+ EXPECT_TRUE(Result.empty());
+}
+
+TEST(ConvertUTFTest, HasUTF16BOM) {
+ bool HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xff\xfe", 2));
+ EXPECT_TRUE(HasBOM);
+ HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe\xff", 2));
+ EXPECT_TRUE(HasBOM);
+ HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe\xff ", 3));
+ EXPECT_TRUE(HasBOM); // Don't care about odd lengths.
+ HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe\xff\x00asdf", 6));
+ EXPECT_TRUE(HasBOM);
+
+ HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>());
+ EXPECT_FALSE(HasBOM);
+ HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe", 1));
+ EXPECT_FALSE(HasBOM);
+}
diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp
index 4853426c94706..feb6a086e1943 100644
--- a/unittests/Support/ErrorOrTest.cpp
+++ b/unittests/Support/ErrorOrTest.cpp
@@ -45,9 +45,6 @@ TEST(ErrorOr, Types) {
*a = 42;
EXPECT_EQ(42, x);
- EXPECT_FALSE(ErrorOr<void>(errc::broken_pipe));
- EXPECT_TRUE(ErrorOr<void>(errc::success));
-
#if LLVM_HAS_CXX11_STDLIB
// Move only types.
EXPECT_EQ(3, **t3());
@@ -67,38 +64,3 @@ TEST(ErrorOr, Covariant) {
#endif
}
} // end anon namespace
-
-struct InvalidArgError {
- InvalidArgError() {}
- InvalidArgError(std::string S) : ArgName(S) {}
- std::string ArgName;
-};
-
-namespace llvm {
-template<>
-struct ErrorOrUserDataTraits<InvalidArgError> : true_type {
- static error_code error() {
- return make_error_code(errc::invalid_argument);
- }
-};
-} // end namespace llvm
-
-ErrorOr<int> t4() {
- return InvalidArgError("adena");
-}
-
-ErrorOr<void> t5() {
- return InvalidArgError("pie");
-}
-
-namespace {
-TEST(ErrorOr, UserErrorData) {
- ErrorOr<int> a = t4();
- EXPECT_EQ(errc::invalid_argument, a);
- EXPECT_EQ("adena", t4().getError<InvalidArgError>().ArgName);
-
- ErrorOr<void> b = t5();
- EXPECT_EQ(errc::invalid_argument, b);
- EXPECT_EQ("pie", b.getError<InvalidArgError>().ArgName);
-}
-} // end anon namespace
diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp
index 80d724536821f..5e873193f2886 100644
--- a/unittests/Support/FileOutputBufferTest.cpp
+++ b/unittests/Support/FileOutputBufferTest.cpp
@@ -11,7 +11,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/PathV2.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
@@ -30,12 +30,8 @@ TEST(FileOutputBuffer, Test) {
// Create unique temporary directory for these tests
SmallString<128> TestDirectory;
{
- int fd;
ASSERT_NO_ERROR(
- fs::unique_file("FileOutputBuffer-test-%%-%%-%%-%%/dir", fd,
- TestDirectory));
- ::close(fd);
- TestDirectory = path::parent_path(TestDirectory);
+ fs::createUniqueDirectory("FileOutputBuffer-test", TestDirectory));
}
// TEST 1: Verify commit case.
diff --git a/unittests/Support/IntegersSubsetTest.cpp b/unittests/Support/IntegersSubsetTest.cpp
deleted file mode 100644
index f4298bf595aad..0000000000000
--- a/unittests/Support/IntegersSubsetTest.cpp
+++ /dev/null
@@ -1,326 +0,0 @@
-//===- llvm/unittest/Support/IntegersSubsetTest.cpp - IntegersSubset tests ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/IntegersSubset.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/Support/IntegersSubsetMapping.h"
-#include "gtest/gtest.h"
-#include <vector>
-
-using namespace llvm;
-
-namespace {
-
- class Int : public APInt {
- public:
- Int() {}
- Int(uint64_t V) : APInt(64, V) {}
- Int(const APInt& Src) : APInt(Src) {}
- bool operator < (const APInt& RHS) const { return ult(RHS); }
- bool operator > (const APInt& RHS) const { return ugt(RHS); }
- bool operator <= (const APInt& RHS) const { return ule(RHS); }
- bool operator >= (const APInt& RHS) const { return uge(RHS); }
- };
-
- typedef IntRange<Int> Range;
- typedef IntegersSubsetGeneric<Int> Subset;
- typedef IntegersSubsetMapping<unsigned,Subset,Int> Mapping;
-
- TEST(IntegersSubsetTest, GeneralTest) {
-
- // Test construction.
-
- std::vector<Range> Ranges;
- Ranges.reserve(3);
-
- // Initialize Subset as union of three pairs:
- // { {0, 8}, {10, 18}, {20, 28} }
- for (unsigned i = 0; i < 3; ++i)
- Ranges.push_back(Range(Int(i*10), Int(i*10 + 8)));
-
- Subset TheSubset(Ranges);
-
- for (unsigned i = 0; i < 3; ++i) {
- EXPECT_EQ(TheSubset.getItem(i).getLow(), Int(i*10));
- EXPECT_EQ(TheSubset.getItem(i).getHigh(), Int(i*10 + 8));
- }
-
- EXPECT_EQ(TheSubset.getNumItems(), 3ULL);
-
- // Test belonging to range.
-
- EXPECT_TRUE(TheSubset.isSatisfies(Int(5)));
- EXPECT_FALSE(TheSubset.isSatisfies(Int(9)));
-
- // Test when subset contains the only item.
-
- Ranges.clear();
- Ranges.push_back(Range(Int(10), Int(10)));
-
- Subset TheSingleNumber(Ranges);
-
- EXPECT_TRUE(TheSingleNumber.isSingleNumber());
-
- Ranges.push_back(Range(Int(12), Int(15)));
-
- Subset NotASingleNumber(Ranges);
-
- EXPECT_FALSE(NotASingleNumber.isSingleNumber());
-
- // Test when subset contains items that are not a ranges but
- // the single numbers.
-
- Ranges.clear();
- Ranges.push_back(Range(Int(10), Int(10)));
- Ranges.push_back(Range(Int(15), Int(19)));
-
- Subset WithSingleNumberItems(Ranges);
-
- EXPECT_TRUE(WithSingleNumberItems.isSingleNumber(0));
- EXPECT_FALSE(WithSingleNumberItems.isSingleNumber(1));
-
- // Test size of subset. Note subset itself may be not optimized (improper),
- // so it may contain duplicates, and the size of subset { {0, 9} {5, 9} }
- // will 15 instead of 10.
-
- Ranges.clear();
- Ranges.push_back(Range(Int(0), Int(9)));
- Ranges.push_back(Range(Int(5), Int(9)));
-
- Subset NotOptimizedSubset(Ranges);
-
- EXPECT_EQ(NotOptimizedSubset.getSize(), 15ULL);
-
- // Test access to a single value.
- // getSingleValue(idx) method represents subset as flat numbers collection,
- // so subset { {0, 3}, {8, 10} } will represented as array
- // { 0, 1, 2, 3, 8, 9, 10 }.
-
- Ranges.clear();
- Ranges.push_back(Range(Int(0), Int(3)));
- Ranges.push_back(Range(Int(8), Int(10)));
-
- Subset OneMoreSubset(Ranges);
-
- EXPECT_EQ(OneMoreSubset.getSingleValue(5), Int(9));
- }
-
- TEST(IntegersSubsetTest, MappingTest) {
-
- Mapping::Cases TheCases;
-
- unsigned Successors[3] = {0, 1, 2};
-
- // Test construction.
-
- Mapping TheMapping;
- for (unsigned i = 0; i < 3; ++i)
- TheMapping.add(Int(10*i), Int(10*i + 9), Successors + i);
- TheMapping.add(Int(111), Int(222), Successors);
- TheMapping.removeItem(--TheMapping.end());
-
- TheMapping.getCases(TheCases);
-
- EXPECT_EQ(TheCases.size(), 3ULL);
-
- for (unsigned i = 0; i < 3; ++i) {
- Mapping::Cases::iterator CaseIt = TheCases.begin();
- std::advance(CaseIt, i);
- EXPECT_EQ(CaseIt->first, Successors + i);
- EXPECT_EQ(CaseIt->second.getNumItems(), 1ULL);
- EXPECT_EQ(CaseIt->second.getItem(0), Range(Int(10*i), Int(10*i + 9)));
- }
-
- // Test verification.
-
- Mapping ImproperMapping;
- ImproperMapping.add(Int(10), Int(11), Successors + 0);
- ImproperMapping.add(Int(11), Int(12), Successors + 1);
-
- Mapping::RangeIterator ErrItem;
- EXPECT_FALSE(ImproperMapping.verify(ErrItem));
- EXPECT_EQ(ErrItem, --ImproperMapping.end());
-
- Mapping ProperMapping;
- ProperMapping.add(Int(10), Int(11), Successors + 0);
- ProperMapping.add(Int(12), Int(13), Successors + 1);
-
- EXPECT_TRUE(ProperMapping.verify(ErrItem));
-
- // Test optimization.
-
- Mapping ToBeOptimized;
-
- for (unsigned i = 0; i < 3; ++i) {
- ToBeOptimized.add(Int(i * 10), Int(i * 10 + 1), Successors + i);
- ToBeOptimized.add(Int(i * 10 + 2), Int(i * 10 + 9), Successors + i);
- }
-
- ToBeOptimized.optimize();
-
- TheCases.clear();
- ToBeOptimized.getCases(TheCases);
-
- EXPECT_EQ(TheCases.size(), 3ULL);
-
- for (unsigned i = 0; i < 3; ++i) {
- Mapping::Cases::iterator CaseIt = TheCases.begin();
- std::advance(CaseIt, i);
- EXPECT_EQ(CaseIt->first, Successors + i);
- EXPECT_EQ(CaseIt->second.getNumItems(), 1ULL);
- EXPECT_EQ(CaseIt->second.getItem(0), Range(Int(i * 10), Int(i * 10 + 9)));
- }
- }
-
- typedef unsigned unsigned_pair[2];
- typedef unsigned_pair unsigned_ranges[];
-
- void TestDiff(
- const unsigned_ranges LHS,
- unsigned LSize,
- const unsigned_ranges RHS,
- unsigned RSize,
- const unsigned_ranges ExcludeRes,
- unsigned ExcludeResSize,
- const unsigned_ranges IntersectRes,
- unsigned IntersectResSize
- ) {
-
- Mapping::RangesCollection Ranges;
-
- Mapping LHSMapping;
- for (unsigned i = 0; i < LSize; ++i)
- Ranges.push_back(Range(Int(LHS[i][0]), Int(LHS[i][1])));
- LHSMapping.add(Ranges);
-
- Ranges.clear();
-
- Mapping RHSMapping;
- for (unsigned i = 0; i < RSize; ++i)
- Ranges.push_back(Range(Int(RHS[i][0]), Int(RHS[i][1])));
- RHSMapping.add(Ranges);
-
- Mapping LExclude, Intersection;
-
- LHSMapping.diff(&LExclude, &Intersection, 0, RHSMapping);
-
- if (ExcludeResSize) {
- EXPECT_EQ(LExclude.size(), ExcludeResSize);
-
- unsigned i = 0;
- for (Mapping::RangeIterator rei = LExclude.begin(),
- e = LExclude.end(); rei != e; ++rei, ++i)
- EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1]));
- } else
- EXPECT_TRUE(LExclude.empty());
-
- if (IntersectResSize) {
- EXPECT_EQ(Intersection.size(), IntersectResSize);
-
- unsigned i = 0;
- for (Mapping::RangeIterator ii = Intersection.begin(),
- e = Intersection.end(); ii != e; ++ii, ++i)
- EXPECT_EQ(ii->first, Range(IntersectRes[i][0], IntersectRes[i][1]));
- } else
- EXPECT_TRUE(Intersection.empty());
-
- LExclude.clear();
- Intersection.clear();
- RHSMapping.diff(0, &Intersection, &LExclude, LHSMapping);
-
- // Check LExclude again.
- if (ExcludeResSize) {
- EXPECT_EQ(LExclude.size(), ExcludeResSize);
-
- unsigned i = 0;
- for (Mapping::RangeIterator rei = LExclude.begin(),
- e = LExclude.end(); rei != e; ++rei, ++i)
- EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1]));
- } else
- EXPECT_TRUE(LExclude.empty());
- }
-
- TEST(IntegersSubsetTest, DiffTest) {
-
- static const unsigned NOT_A_NUMBER = 0xffff;
-
- {
- unsigned_ranges LHS = { { 0, 4 }, { 7, 10 }, { 13, 17 } };
- unsigned_ranges RHS = { { 3, 14 } };
- unsigned_ranges ExcludeRes = { { 0, 2 }, { 15, 17 } };
- unsigned_ranges IntersectRes = { { 3, 4 }, { 7, 10 }, { 13, 14 } };
-
- TestDiff(LHS, 3, RHS, 1, ExcludeRes, 2, IntersectRes, 3);
- }
-
- {
- unsigned_ranges LHS = { { 0, 4 }, { 7, 10 }, { 13, 17 } };
- unsigned_ranges RHS = { { 0, 4 }, { 13, 17 } };
- unsigned_ranges ExcludeRes = { { 7, 10 } };
- unsigned_ranges IntersectRes = { { 0, 4 }, { 13, 17 } };
-
- TestDiff(LHS, 3, RHS, 2, ExcludeRes, 1, IntersectRes, 2);
- }
-
- {
- unsigned_ranges LHS = { { 0, 17 } };
- unsigned_ranges RHS = { { 1, 5 }, { 10, 12 }, { 15, 16 } };
- unsigned_ranges ExcludeRes =
- { { 0, 0 }, { 6, 9 }, { 13, 14 }, { 17, 17 } };
- unsigned_ranges IntersectRes = { { 1, 5 }, { 10, 12 }, { 15, 16 } };
-
- TestDiff(LHS, 1, RHS, 3, ExcludeRes, 4, IntersectRes, 3);
- }
-
- {
- unsigned_ranges LHS = { { 2, 4 } };
- unsigned_ranges RHS = { { 0, 5 } };
- unsigned_ranges ExcludeRes = { {NOT_A_NUMBER, NOT_A_NUMBER} };
- unsigned_ranges IntersectRes = { { 2, 4 } };
-
- TestDiff(LHS, 1, RHS, 1, ExcludeRes, 0, IntersectRes, 1);
- }
-
- {
- unsigned_ranges LHS = { { 2, 4 } };
- unsigned_ranges RHS = { { 7, 8 } };
- unsigned_ranges ExcludeRes = { { 2, 4 } };
- unsigned_ranges IntersectRes = { {NOT_A_NUMBER, NOT_A_NUMBER} };
-
- TestDiff(LHS, 1, RHS, 1, ExcludeRes, 1, IntersectRes, 0);
- }
-
- {
- unsigned_ranges LHS = { { 3, 7 } };
- unsigned_ranges RHS = { { 1, 4 } };
- unsigned_ranges ExcludeRes = { { 5, 7 } };
- unsigned_ranges IntersectRes = { { 3, 4 } };
-
- TestDiff(LHS, 1, RHS, 1, ExcludeRes, 1, IntersectRes, 1);
- }
-
- {
- unsigned_ranges LHS = { { 0, 7 } };
- unsigned_ranges RHS = { { 0, 5 }, { 6, 9 } };
- unsigned_ranges ExcludeRes = { {NOT_A_NUMBER, NOT_A_NUMBER} };
- unsigned_ranges IntersectRes = { { 0, 5 }, {6, 7} };
-
- TestDiff(LHS, 1, RHS, 2, ExcludeRes, 0, IntersectRes, 2);
- }
-
- {
- unsigned_ranges LHS = { { 17, 17 } };
- unsigned_ranges RHS = { { 4, 4 } };
- unsigned_ranges ExcludeRes = { {17, 17} };
- unsigned_ranges IntersectRes = { { NOT_A_NUMBER, NOT_A_NUMBER } };
-
- TestDiff(LHS, 1, RHS, 1, ExcludeRes, 1, IntersectRes, 0);
- }
- }
-}
diff --git a/unittests/Support/LockFileManagerTest.cpp b/unittests/Support/LockFileManagerTest.cpp
new file mode 100644
index 0000000000000..5c73b9f5e2352
--- /dev/null
+++ b/unittests/Support/LockFileManagerTest.cpp
@@ -0,0 +1,48 @@
+//===- unittests/LockFileManagerTest.cpp - LockFileManager tests ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LockFileManager.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+#include "gtest/gtest.h"
+
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+TEST(LockFileManagerTest, Basic) {
+ SmallString<64> TmpDir;
+ error_code EC;
+ EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir);
+ ASSERT_FALSE(EC);
+
+ SmallString<64> LockedFile(TmpDir);
+ sys::path::append(LockedFile, "file.lock");
+
+ {
+ // The lock file should not exist, so we should successfully acquire it.
+ LockFileManager Locked1(LockedFile);
+ EXPECT_EQ(LockFileManager::LFS_Owned, Locked1.getState());
+
+ // Attempting to reacquire the lock should fail. Waiting on it would cause
+ // deadlock, so don't try that.
+ LockFileManager Locked2(LockedFile);
+ EXPECT_NE(LockFileManager::LFS_Owned, Locked2.getState());
+ }
+
+ // Now that the lock is out of scope, the file should be gone.
+ EXPECT_FALSE(sys::fs::exists(StringRef(LockedFile)));
+
+ sys::fs::remove_all(StringRef(TmpDir));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Support/MD5Test.cpp b/unittests/Support/MD5Test.cpp
new file mode 100644
index 0000000000000..7c1331b6c5370
--- /dev/null
+++ b/unittests/Support/MD5Test.cpp
@@ -0,0 +1,60 @@
+//===- llvm/unittest/Support/MD5Test.cpp - MD5 tests ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements unit tests for the MD5 functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/MD5.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+/// \brief Tests an arbitrary set of bytes passed as \p Input.
+void TestMD5Sum(ArrayRef<uint8_t> Input, StringRef Final) {
+ MD5 Hash;
+ Hash.update(Input);
+ MD5::MD5Result MD5Res;
+ Hash.final(MD5Res);
+ SmallString<32> Res;
+ MD5::stringifyResult(MD5Res, Res);
+ EXPECT_EQ(Res, Final);
+}
+
+void TestMD5Sum(StringRef Input, StringRef Final) {
+ MD5 Hash;
+ Hash.update(Input);
+ MD5::MD5Result MD5Res;
+ Hash.final(MD5Res);
+ SmallString<32> Res;
+ MD5::stringifyResult(MD5Res, Res);
+ EXPECT_EQ(Res, Final);
+}
+
+TEST(MD5Test, MD5) {
+ TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"", (size_t) 0),
+ "d41d8cd98f00b204e9800998ecf8427e");
+ TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"a", (size_t) 1),
+ "0cc175b9c0f1b6a831c399e269772661");
+ TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"abcdefghijklmnopqrstuvwxyz",
+ (size_t) 26),
+ "c3fcd3d76192e4007dfb496cca67e13b");
+ TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"\0", (size_t) 1),
+ "93b885adfe0da089cdf634904fd59f71");
+ TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"a\0", (size_t) 2),
+ "4144e195f46de78a3623da7364d04f11");
+ TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"abcdefghijklmnopqrstuvwxyz\0",
+ (size_t) 27),
+ "81948d1f1554f58cd1a56ebb01f808cb");
+ TestMD5Sum("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b");
+}
+}
diff --git a/unittests/Support/Makefile b/unittests/Support/Makefile
index 815bdd269da56..9c0a7f94d7725 100644
--- a/unittests/Support/Makefile
+++ b/unittests/Support/Makefile
@@ -1,4 +1,4 @@
-##===- unittests/ADT/Makefile ------------------------------*- Makefile -*-===##
+##===- unittests/Support/Makefile --------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
diff --git a/unittests/Support/ManagedStatic.cpp b/unittests/Support/ManagedStatic.cpp
index 8ddad38ecf171..1497f4e34082d 100644
--- a/unittests/Support/ManagedStatic.cpp
+++ b/unittests/Support/ManagedStatic.cpp
@@ -19,7 +19,8 @@ using namespace llvm;
namespace {
-#if defined(HAVE_PTHREAD_H) && !__has_feature(memory_sanitizer)
+#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H) && \
+ !__has_feature(memory_sanitizer)
namespace test1 {
llvm::ManagedStatic<int> ms;
void *helper(void*) {
diff --git a/unittests/Support/MathExtrasTest.cpp b/unittests/Support/MathExtrasTest.cpp
index 0a6724c7e7080..93a38cb03fd93 100644
--- a/unittests/Support/MathExtrasTest.cpp
+++ b/unittests/Support/MathExtrasTest.cpp
@@ -14,6 +14,109 @@ using namespace llvm;
namespace {
+TEST(MathExtras, countTrailingZeros) {
+ uint8_t Z8 = 0;
+ uint16_t Z16 = 0;
+ uint32_t Z32 = 0;
+ uint64_t Z64 = 0;
+ EXPECT_EQ(8u, countTrailingZeros(Z8));
+ EXPECT_EQ(16u, countTrailingZeros(Z16));
+ EXPECT_EQ(32u, countTrailingZeros(Z32));
+ EXPECT_EQ(64u, countTrailingZeros(Z64));
+
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(1u, countTrailingZeros(NZ8));
+ EXPECT_EQ(1u, countTrailingZeros(NZ16));
+ EXPECT_EQ(1u, countTrailingZeros(NZ32));
+ EXPECT_EQ(1u, countTrailingZeros(NZ64));
+}
+
+TEST(MathExtras, countLeadingZeros) {
+ uint8_t Z8 = 0;
+ uint16_t Z16 = 0;
+ uint32_t Z32 = 0;
+ uint64_t Z64 = 0;
+ EXPECT_EQ(8u, countLeadingZeros(Z8));
+ EXPECT_EQ(16u, countLeadingZeros(Z16));
+ EXPECT_EQ(32u, countLeadingZeros(Z32));
+ EXPECT_EQ(64u, countLeadingZeros(Z64));
+
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(2u, countLeadingZeros(NZ8));
+ EXPECT_EQ(10u, countLeadingZeros(NZ16));
+ EXPECT_EQ(26u, countLeadingZeros(NZ32));
+ EXPECT_EQ(58u, countLeadingZeros(NZ64));
+
+ EXPECT_EQ(8u, countLeadingZeros(0x00F000FFu));
+ EXPECT_EQ(8u, countLeadingZeros(0x00F12345u));
+ for (unsigned i = 0; i <= 30; ++i) {
+ EXPECT_EQ(31 - i, countLeadingZeros(1u << i));
+ }
+
+ EXPECT_EQ(8u, countLeadingZeros(0x00F1234500F12345ULL));
+ EXPECT_EQ(1u, countLeadingZeros(1ULL << 62));
+ for (unsigned i = 0; i <= 62; ++i) {
+ EXPECT_EQ(63 - i, countLeadingZeros(1ULL << i));
+ }
+}
+
+TEST(MathExtras, findFirstSet) {
+ uint8_t Z8 = 0;
+ uint16_t Z16 = 0;
+ uint32_t Z32 = 0;
+ uint64_t Z64 = 0;
+ EXPECT_EQ(0xFFULL, findFirstSet(Z8));
+ EXPECT_EQ(0xFFFFULL, findFirstSet(Z16));
+ EXPECT_EQ(0xFFFFFFFFULL, findFirstSet(Z32));
+ EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, findFirstSet(Z64));
+
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(1u, findFirstSet(NZ8));
+ EXPECT_EQ(1u, findFirstSet(NZ16));
+ EXPECT_EQ(1u, findFirstSet(NZ32));
+ EXPECT_EQ(1u, findFirstSet(NZ64));
+}
+
+TEST(MathExtras, findLastSet) {
+ uint8_t Z8 = 0;
+ uint16_t Z16 = 0;
+ uint32_t Z32 = 0;
+ uint64_t Z64 = 0;
+ EXPECT_EQ(0xFFULL, findLastSet(Z8));
+ EXPECT_EQ(0xFFFFULL, findLastSet(Z16));
+ EXPECT_EQ(0xFFFFFFFFULL, findLastSet(Z32));
+ EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, findLastSet(Z64));
+
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(5u, findLastSet(NZ8));
+ EXPECT_EQ(5u, findLastSet(NZ16));
+ EXPECT_EQ(5u, findLastSet(NZ32));
+ EXPECT_EQ(5u, findLastSet(NZ64));
+}
+
+TEST(MathExtras, reverseBits) {
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(0x54ULL, reverseBits(NZ8));
+ EXPECT_EQ(0x5400ULL, reverseBits(NZ16));
+ EXPECT_EQ(0x54000000ULL, reverseBits(NZ32));
+ EXPECT_EQ(0x5400000000000000ULL, reverseBits(NZ64));
+}
+
TEST(MathExtras, isPowerOf2_32) {
EXPECT_TRUE(isPowerOf2_32(1 << 6));
EXPECT_TRUE(isPowerOf2_32(1 << 12));
@@ -38,22 +141,6 @@ TEST(MathExtras, ByteSwap_64) {
EXPECT_EQ(0x1100FFEEDDCCBBAAULL, ByteSwap_64(0xAABBCCDDEEFF0011LL));
}
-TEST(MathExtras, CountLeadingZeros_32) {
- EXPECT_EQ(8u, CountLeadingZeros_32(0x00F000FF));
- EXPECT_EQ(8u, CountLeadingZeros_32(0x00F12345));
- for (unsigned i = 0; i <= 30; ++i) {
- EXPECT_EQ(31 - i, CountLeadingZeros_32(1 << i));
- }
-}
-
-TEST(MathExtras, CountLeadingZeros_64) {
- EXPECT_EQ(8u, CountLeadingZeros_64(0x00F1234500F12345LL));
- EXPECT_EQ(1u, CountLeadingZeros_64(1LL << 62));
- for (unsigned i = 0; i <= 62; ++i) {
- EXPECT_EQ(63 - i, CountLeadingZeros_64(1LL << i));
- }
-}
-
TEST(MathExtras, CountLeadingOnes_32) {
for (int i = 30; i >= 0; --i) {
// Start with all ones and unset some bit.
diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp
index 1d9f482c519db..2b8806c394f34 100644
--- a/unittests/Support/MemoryBufferTest.cpp
+++ b/unittests/Support/MemoryBufferTest.cpp
@@ -11,12 +11,16 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/OwningPtr.h"
#include "gtest/gtest.h"
using namespace llvm;
+namespace {
+
class MemoryBufferTest : public testing::Test {
protected:
MemoryBufferTest()
@@ -25,13 +29,18 @@ protected:
virtual void SetUp() { }
+ /// Common testing for different modes of getOpenFileSlice.
+ /// Creates a temporary file with known contents, and uses
+ /// MemoryBuffer::getOpenFileSlice to map it.
+ /// If \p Reopen is true, the file is closed after creating and reopened
+ /// anew before using MemoryBuffer.
+ void testGetOpenFileSlice(bool Reopen);
+
typedef OwningPtr<MemoryBuffer> OwningBuffer;
std::string data;
};
-namespace {
-
TEST_F(MemoryBufferTest, get) {
// Default name and null-terminator flag
OwningBuffer MB1(MemoryBuffer::getMemBuffer(data));
@@ -56,6 +65,28 @@ TEST_F(MemoryBufferTest, get) {
EXPECT_EQ("this is some data", data);
}
+TEST_F(MemoryBufferTest, NullTerminator4K) {
+ // Test that a file with size that is a multiple of the page size can be null
+ // terminated correctly by MemoryBuffer.
+ int TestFD;
+ SmallString<64> TestPath;
+ sys::fs::createTemporaryFile("MemoryBufferTest_NullTerminator4K", "temp",
+ TestFD, TestPath);
+ raw_fd_ostream OF(TestFD, true, /*unbuffered=*/true);
+ for (unsigned i = 0; i < 4096 / 16; ++i) {
+ OF << "0123456789abcdef";
+ }
+ OF.close();
+
+ OwningPtr<MemoryBuffer> MB;
+ error_code EC = MemoryBuffer::getFile(TestPath.c_str(), MB);
+ ASSERT_FALSE(EC);
+
+ const char *BufData = MB->getBufferStart();
+ EXPECT_EQ('f', BufData[4095]);
+ EXPECT_EQ('\0', BufData[4096]);
+}
+
TEST_F(MemoryBufferTest, copy) {
// copy with no name
OwningBuffer MBC1(MemoryBuffer::getMemBufferCopy(data));
@@ -95,4 +126,46 @@ TEST_F(MemoryBufferTest, make_new) {
EXPECT_EQ(0, Four->getBufferStart()[0]);
}
+void MemoryBufferTest::testGetOpenFileSlice(bool Reopen) {
+ // Test that MemoryBuffer::getOpenFile works properly when no null
+ // terminator is requested and the size is large enough to trigger
+ // the usage of memory mapping.
+ int TestFD;
+ SmallString<64> TestPath;
+ // Create a temporary file and write data into it.
+ sys::fs::createTemporaryFile("prefix", "temp", TestFD, TestPath);
+ // OF is responsible for closing the file; If the file is not
+ // reopened, it will be unbuffered so that the results are
+ // immediately visible through the fd.
+ raw_fd_ostream OF(TestFD, true, !Reopen);
+ for (int i = 0; i < 60000; ++i) {
+ OF << "0123456789";
+ }
+
+ if (Reopen) {
+ OF.close();
+ EXPECT_FALSE(sys::fs::openFileForRead(TestPath.c_str(), TestFD));
+ }
+
+ OwningBuffer Buf;
+ error_code EC = MemoryBuffer::getOpenFileSlice(TestFD, TestPath.c_str(), Buf,
+ 40000, // Size
+ 80000 // Offset
+ );
+ EXPECT_FALSE(EC);
+
+ StringRef BufData = Buf->getBuffer();
+ EXPECT_EQ(BufData.size(), 40000U);
+ EXPECT_EQ(BufData[0], '0');
+ EXPECT_EQ(BufData[9], '9');
+}
+
+TEST_F(MemoryBufferTest, getOpenFileNoReopen) {
+ testGetOpenFileSlice(false);
+}
+
+TEST_F(MemoryBufferTest, getOpenFileReopened) {
+ testGetOpenFileSlice(true);
+}
+
}
diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp
index eec8c62d8c841..031624162d0f1 100644
--- a/unittests/Support/Path.cpp
+++ b/unittests/Support/Path.cpp
@@ -7,9 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/PathV2.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
@@ -140,6 +141,75 @@ TEST(Support, Path) {
}
}
+TEST(Support, RelativePathIterator) {
+ SmallString<64> Path(StringRef("c/d/e/foo.txt"));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, "/");
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+
+TEST(Support, AbsolutePathIterator) {
+ SmallString<64> Path(StringRef("/c/d/e/foo.txt"));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, "/");
+
+ // The root path will also be a component when iterating
+ ExpectedPathComponents[0] = "/";
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+
+#ifdef LLVM_ON_WIN32
+TEST(Support, AbsolutePathIteratorWin32) {
+ SmallString<64> Path(StringRef("c:\\c\\e\\foo.txt"));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, "\\");
+
+ // The root path (which comes after the drive name) will also be a component
+ // when iterating.
+ ExpectedPathComponents.insert(ExpectedPathComponents.begin()+1, "\\");
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+#endif // LLVM_ON_WIN32
+
class FileSystemTest : public testing::Test {
protected:
/// Unique temporary directory in which all created filesystem entities must
@@ -147,13 +217,9 @@ protected:
SmallString<128> TestDirectory;
virtual void SetUp() {
- int fd;
ASSERT_NO_ERROR(
- fs::unique_file("file-system-test-%%-%%-%%-%%/test-directory.anchor", fd,
- TestDirectory));
+ fs::createUniqueDirectory("file-system-test", TestDirectory));
// We don't care about this specific file.
- ::close(fd);
- TestDirectory = path::parent_path(TestDirectory);
errs() << "Test Directory: " << TestDirectory << '\n';
errs().flush();
}
@@ -164,12 +230,61 @@ protected:
}
};
+TEST_F(FileSystemTest, Unique) {
+ // Create a temp file.
+ int FileDescriptor;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(
+ fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath));
+
+ // The same file should return an identical unique id.
+ fs::UniqueID F1, F2;
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), F1));
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), F2));
+ ASSERT_EQ(F1, F2);
+
+ // Different files should return different unique ids.
+ int FileDescriptor2;
+ SmallString<64> TempPath2;
+ ASSERT_NO_ERROR(
+ fs::createTemporaryFile("prefix", "temp", FileDescriptor2, TempPath2));
+
+ fs::UniqueID D;
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2), D));
+ ASSERT_NE(D, F1);
+ ::close(FileDescriptor2);
+
+ ASSERT_NO_ERROR(fs::remove(Twine(TempPath2)));
+
+ // Two paths representing the same file on disk should still provide the
+ // same unique id. We can test this by making a hard link.
+ ASSERT_NO_ERROR(fs::create_hard_link(Twine(TempPath), Twine(TempPath2)));
+ fs::UniqueID D2;
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2), D2));
+ ASSERT_EQ(D2, F1);
+
+ ::close(FileDescriptor);
+
+ SmallString<128> Dir1;
+ ASSERT_NO_ERROR(
+ fs::createUniqueDirectory("dir1", Dir1));
+ ASSERT_NO_ERROR(fs::getUniqueID(Dir1.c_str(), F1));
+ ASSERT_NO_ERROR(fs::getUniqueID(Dir1.c_str(), F2));
+ ASSERT_EQ(F1, F2);
+
+ SmallString<128> Dir2;
+ ASSERT_NO_ERROR(
+ fs::createUniqueDirectory("dir2", Dir2));
+ ASSERT_NO_ERROR(fs::getUniqueID(Dir2.c_str(), F2));
+ ASSERT_NE(F1, F2);
+}
+
TEST_F(FileSystemTest, TempFiles) {
// Create a temp file.
int FileDescriptor;
SmallString<64> TempPath;
ASSERT_NO_ERROR(
- fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath));
+ fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath));
// Make sure it exists.
bool TempFileExists;
@@ -179,7 +294,8 @@ TEST_F(FileSystemTest, TempFiles) {
// Create another temp tile.
int FD2;
SmallString<64> TempPath2;
- ASSERT_NO_ERROR(fs::unique_file("%%-%%-%%-%%.temp", FD2, TempPath2));
+ ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD2, TempPath2));
+ ASSERT_TRUE(TempPath2.endswith(".temp"));
ASSERT_NE(TempPath.str(), TempPath2.str());
fs::file_status A, B;
@@ -187,22 +303,24 @@ TEST_F(FileSystemTest, TempFiles) {
ASSERT_NO_ERROR(fs::status(Twine(TempPath2), B));
EXPECT_FALSE(fs::equivalent(A, B));
- // Try to copy the first to the second.
- EXPECT_EQ(
- fs::copy_file(Twine(TempPath), Twine(TempPath2)), errc::file_exists);
-
::close(FD2);
- // Try again with the proper options.
- ASSERT_NO_ERROR(fs::copy_file(Twine(TempPath), Twine(TempPath2),
- fs::copy_option::overwrite_if_exists));
+
// Remove Temp2.
ASSERT_NO_ERROR(fs::remove(Twine(TempPath2), TempFileExists));
EXPECT_TRUE(TempFileExists);
+ error_code EC = fs::status(TempPath2.c_str(), B);
+ EXPECT_EQ(EC, errc::no_such_file_or_directory);
+ EXPECT_EQ(B.type(), fs::file_type::file_not_found);
+
// Make sure Temp2 doesn't exist.
ASSERT_NO_ERROR(fs::exists(Twine(TempPath2), TempFileExists));
EXPECT_FALSE(TempFileExists);
+ SmallString<64> TempPath3;
+ ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "", TempPath3));
+ ASSERT_FALSE(TempPath3.endswith("."));
+
// Create a hard link to Temp1.
ASSERT_NO_ERROR(fs::create_hard_link(Twine(TempPath), Twine(TempPath2)));
bool equal;
@@ -233,7 +351,7 @@ TEST_F(FileSystemTest, TempFiles) {
"abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4"
"abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2"
"abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0";
- EXPECT_EQ(fs::unique_file(Twine(Path270), FileDescriptor, TempPath),
+ EXPECT_EQ(fs::createUniqueFile(Twine(Path270), FileDescriptor, TempPath),
windows_error::path_not_found);
#endif
}
@@ -298,7 +416,25 @@ TEST_F(FileSystemTest, DirectoryIteration) {
ASSERT_LT(z0, za1);
}
-const char elf[] = {0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+const char archive[] = "!<arch>\x0A";
+const char bitcode[] = "\xde\xc0\x17\x0b";
+const char coff_object[] = "\x00\x00......";
+const char coff_import_library[] = "\x00\x00\xff\xff....";
+const char elf_relocatable[] = { 0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+const char macho_universal_binary[] = "\xca\xfe\xba\xbe...\0x00";
+const char macho_object[] = "\xfe\xed\xfa\xce..........\x00\x01";
+const char macho_executable[] = "\xfe\xed\xfa\xce..........\x00\x02";
+const char macho_fixed_virtual_memory_shared_lib[] =
+ "\xfe\xed\xfa\xce..........\x00\x03";
+const char macho_core[] = "\xfe\xed\xfa\xce..........\x00\x04";
+const char macho_preload_executable[] = "\xfe\xed\xfa\xce..........\x00\x05";
+const char macho_dynamically_linked_shared_lib[] =
+ "\xfe\xed\xfa\xce..........\x00\x06";
+const char macho_dynamic_linker[] = "\xfe\xed\xfa\xce..........\x00\x07";
+const char macho_bundle[] = "\xfe\xed\xfa\xce..........\x00\x08";
+const char macho_dsym_companion[] = "\xfe\xed\xfa\xce..........\x00\x0a";
+const char windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff";
TEST_F(FileSystemTest, Magic) {
struct type {
@@ -306,11 +442,27 @@ TEST_F(FileSystemTest, Magic) {
const char *magic_str;
size_t magic_str_len;
fs::file_magic magic;
- } types [] = {
- {"magic.archive", "!<arch>\x0A", 8, fs::file_magic::archive},
- {"magic.elf", elf, sizeof(elf),
- fs::file_magic::elf_relocatable}
- };
+ } types[] = {
+#define DEFINE(magic) \
+ { #magic, magic, sizeof(magic), fs::file_magic::magic }
+ DEFINE(archive),
+ DEFINE(bitcode),
+ DEFINE(coff_object),
+ DEFINE(coff_import_library),
+ DEFINE(elf_relocatable),
+ DEFINE(macho_universal_binary),
+ DEFINE(macho_object),
+ DEFINE(macho_executable),
+ DEFINE(macho_fixed_virtual_memory_shared_lib),
+ DEFINE(macho_core),
+ DEFINE(macho_preload_executable),
+ DEFINE(macho_dynamically_linked_shared_lib),
+ DEFINE(macho_dynamic_linker),
+ DEFINE(macho_bundle),
+ DEFINE(macho_dsym_companion),
+ DEFINE(windows_resource)
+#undef DEFINE
+ };
// Create some files filled with magic.
for (type *i = types, *e = types + (sizeof(types) / sizeof(type)); i != e;
@@ -318,8 +470,7 @@ TEST_F(FileSystemTest, Magic) {
SmallString<128> file_pathname(TestDirectory);
path::append(file_pathname, i->filename);
std::string ErrMsg;
- raw_fd_ostream file(file_pathname.c_str(), ErrMsg,
- raw_fd_ostream::F_Binary);
+ raw_fd_ostream file(file_pathname.c_str(), ErrMsg, sys::fs::F_Binary);
ASSERT_FALSE(file.has_error());
StringRef magic(i->magic_str, i->magic_str_len);
file << magic;
@@ -331,31 +482,33 @@ TEST_F(FileSystemTest, Magic) {
}
}
-#if !defined(_WIN32) // FIXME: Win32 has different permission schema.
-TEST_F(FileSystemTest, Permissions) {
- // Create a temp file.
- int FileDescriptor;
- SmallString<64> TempPath;
- ASSERT_NO_ERROR(
- fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath));
-
- // Mark file as read-only
- const fs::perms AllWrite = fs::owner_write|fs::group_write|fs::others_write;
- ASSERT_NO_ERROR(fs::permissions(Twine(TempPath), fs::remove_perms|AllWrite));
-
- // Verify file is read-only
- fs::file_status Status;
- ASSERT_NO_ERROR(fs::status(Twine(TempPath), Status));
- bool AnyWriteBits = (Status.permissions() & AllWrite);
- EXPECT_FALSE(AnyWriteBits);
-
- // Mark file as read-write
- ASSERT_NO_ERROR(fs::permissions(Twine(TempPath), fs::add_perms|AllWrite));
-
- // Verify file is read-write
- ASSERT_NO_ERROR(fs::status(Twine(TempPath), Status));
- AnyWriteBits = (Status.permissions() & AllWrite);
- EXPECT_TRUE(AnyWriteBits);
+#ifdef LLVM_ON_WIN32
+TEST_F(FileSystemTest, CarriageReturn) {
+ SmallString<128> FilePathname(TestDirectory);
+ std::string ErrMsg;
+ path::append(FilePathname, "test");
+
+ {
+ raw_fd_ostream File(FilePathname.c_str(), ErrMsg);
+ EXPECT_EQ(ErrMsg, "");
+ File << '\n';
+ }
+ {
+ OwningPtr<MemoryBuffer> Buf;
+ MemoryBuffer::getFile(FilePathname.c_str(), Buf);
+ EXPECT_EQ(Buf->getBuffer(), "\r\n");
+ }
+
+ {
+ raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_Binary);
+ EXPECT_EQ(ErrMsg, "");
+ File << '\n';
+ }
+ {
+ OwningPtr<MemoryBuffer> Buf;
+ MemoryBuffer::getFile(FilePathname.c_str(), Buf);
+ EXPECT_EQ(Buf->getBuffer(), "\n");
+ }
}
#endif
@@ -364,7 +517,7 @@ TEST_F(FileSystemTest, FileMapping) {
int FileDescriptor;
SmallString<64> TempPath;
ASSERT_NO_ERROR(
- fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath));
+ fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath));
// Map in temp file and add some content
error_code EC;
StringRef Val("hello there");
@@ -381,7 +534,7 @@ TEST_F(FileSystemTest, FileMapping) {
mfr.data()[Val.size()] = 0;
// Unmap temp file
}
-
+
// Map it back in read-only
fs::mapped_file_region mfr(Twine(TempPath),
fs::mapped_file_region::readonly,
@@ -389,10 +542,10 @@ TEST_F(FileSystemTest, FileMapping) {
0,
EC);
ASSERT_NO_ERROR(EC);
-
+
// Verify content
EXPECT_EQ(StringRef(mfr.const_data()), Val);
-
+
// Unmap temp file
#if LLVM_HAS_RVALUE_REFERENCES
diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp
index e57c0e6eaf81a..27c2318215d6b 100644
--- a/unittests/Support/ProcessTest.cpp
+++ b/unittests/Support/ProcessTest.cpp
@@ -26,7 +26,7 @@ TEST(ProcessTest, SelfProcess) {
#if defined(LLVM_ON_UNIX)
EXPECT_EQ(getpid(), process::get_self()->get_id());
#elif defined(LLVM_ON_WIN32)
- EXPECT_EQ(GetCurrentProcess(), process::get_self()->get_id());
+ EXPECT_EQ(GetCurrentProcessId(), process::get_self()->get_id());
#endif
EXPECT_LT(1u, process::get_self()->page_size());
@@ -39,4 +39,32 @@ TEST(ProcessTest, SelfProcess) {
EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_wall_time());
}
+#ifdef _MSC_VER
+#define setenv(name, var, ignore) _putenv_s(name, var)
+#endif
+
+#if HAVE_SETENV || _MSC_VER
+TEST(ProcessTest, Basic) {
+ setenv("__LLVM_TEST_ENVIRON_VAR__", "abc", true);
+ Optional<std::string> val(Process::GetEnv("__LLVM_TEST_ENVIRON_VAR__"));
+ EXPECT_TRUE(val.hasValue());
+ EXPECT_STREQ("abc", val->c_str());
+}
+
+TEST(ProcessTest, None) {
+ Optional<std::string> val(
+ Process::GetEnv("__LLVM_TEST_ENVIRON_NO_SUCH_VAR__"));
+ EXPECT_FALSE(val.hasValue());
+}
+#endif
+
+#ifdef LLVM_ON_WIN32
+TEST(ProcessTest, Wchar) {
+ SetEnvironmentVariableW(L"__LLVM_TEST_ENVIRON_VAR__", L"abcdefghijklmnopqrs");
+ Optional<std::string> val(Process::GetEnv("__LLVM_TEST_ENVIRON_VAR__"));
+ EXPECT_TRUE(val.hasValue());
+ EXPECT_STREQ("abcdefghijklmnopqrs", val->c_str());
+}
+#endif
+
} // end anonymous namespace
diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp
index 6cbb05454f804..6eb990f29d2a0 100644
--- a/unittests/Support/ProgramTest.cpp
+++ b/unittests/Support/ProgramTest.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "gtest/gtest.h"
@@ -20,6 +21,20 @@
extern char **environ;
#endif
+#if defined(LLVM_ON_UNIX)
+#include <unistd.h>
+void sleep_for(unsigned int seconds) {
+ sleep(seconds);
+}
+#elif defined(LLVM_ON_WIN32)
+#include <windows.h>
+void sleep_for(unsigned int seconds) {
+ Sleep(seconds * 1000);
+}
+#else
+#error sleep_for is not implemented on your platform.
+#endif
+
// From TestMain.cpp.
extern const char *TestMainArgv0;
@@ -55,10 +70,11 @@ TEST(ProgramTest, CreateProcessTrailingSlash) {
exit(1);
}
- Path my_exe = Path::GetMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+ std::string my_exe =
+ sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
const char *argv[] = {
my_exe.c_str(),
- "--gtest_filter=ProgramTest.CreateProcessTrailingSlashChild",
+ "--gtest_filter=ProgramTest.CreateProcessTrailingSlash",
"-program-test-string-arg1", "has\\\\ trailing\\",
"-program-test-string-arg2", "has\\\\ trailing\\",
0
@@ -74,16 +90,105 @@ TEST(ProgramTest, CreateProcessTrailingSlash) {
bool ExecutionFailed;
// Redirect stdout and stdin to NUL, but let stderr through.
#ifdef LLVM_ON_WIN32
- Path nul("NUL");
+ StringRef nul("NUL");
#else
- Path nul("/dev/null");
+ StringRef nul("/dev/null");
#endif
- const Path *redirects[] = { &nul, &nul, 0 };
- int rc = Program::ExecuteAndWait(my_exe, argv, &envp[0], redirects,
- /*secondsToWait=*/10, /*memoryLimit=*/0,
- &error, &ExecutionFailed);
+ const StringRef *redirects[] = { &nul, &nul, 0 };
+ int rc = ExecuteAndWait(my_exe, argv, &envp[0], redirects,
+ /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &error,
+ &ExecutionFailed);
EXPECT_FALSE(ExecutionFailed) << error;
EXPECT_EQ(0, rc);
}
+TEST(ProgramTest, TestExecuteNoWait) {
+ using namespace llvm::sys;
+
+ if (getenv("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT")) {
+ sleep_for(/*seconds*/ 1);
+ exit(0);
+ }
+
+ std::string Executable =
+ sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+ const char *argv[] = {
+ Executable.c_str(),
+ "--gtest_filter=ProgramTest.TestExecuteNoWait",
+ 0
+ };
+
+ // Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child.
+ std::vector<const char *> envp;
+ CopyEnvironment(envp);
+ envp.push_back("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1");
+ envp.push_back(0);
+
+ std::string Error;
+ bool ExecutionFailed;
+ ProcessInfo PI1 =
+ ExecuteNoWait(Executable, argv, &envp[0], 0, 0, &Error, &ExecutionFailed);
+ ASSERT_FALSE(ExecutionFailed) << Error;
+ ASSERT_NE(PI1.Pid, 0) << "Invalid process id";
+
+ unsigned LoopCount = 0;
+
+ // Test that Wait() with WaitUntilTerminates=true works. In this case,
+ // LoopCount should only be incremented once.
+ while (true) {
+ ++LoopCount;
+ ProcessInfo WaitResult = Wait(PI1, 0, true, &Error);
+ ASSERT_TRUE(Error.empty());
+ if (WaitResult.Pid == PI1.Pid)
+ break;
+ }
+
+ EXPECT_EQ(LoopCount, 1u) << "LoopCount should be 1";
+
+ ProcessInfo PI2 =
+ ExecuteNoWait(Executable, argv, &envp[0], 0, 0, &Error, &ExecutionFailed);
+ ASSERT_FALSE(ExecutionFailed) << Error;
+ ASSERT_NE(PI2.Pid, 0) << "Invalid process id";
+
+ // Test that Wait() with SecondsToWait=0 performs a non-blocking wait. In this
+ // cse, LoopCount should be greater than 1 (more than one increment occurs).
+ while (true) {
+ ++LoopCount;
+ ProcessInfo WaitResult = Wait(PI2, 0, false, &Error);
+ ASSERT_TRUE(Error.empty());
+ if (WaitResult.Pid == PI2.Pid)
+ break;
+ }
+
+ ASSERT_GT(LoopCount, 1u) << "LoopCount should be >1";
+}
+
+TEST(ProgramTest, TestExecuteNegative) {
+ std::string Executable = "i_dont_exist";
+ const char *argv[] = { Executable.c_str(), 0 };
+
+ {
+ std::string Error;
+ bool ExecutionFailed;
+ int RetCode =
+ ExecuteAndWait(Executable, argv, 0, 0, 0, 0, &Error, &ExecutionFailed);
+ ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or "
+ "positive value indicating the result code";
+ ASSERT_TRUE(ExecutionFailed);
+ ASSERT_FALSE(Error.empty());
+ }
+
+ {
+ std::string Error;
+ bool ExecutionFailed;
+ ProcessInfo PI =
+ ExecuteNoWait(Executable, argv, 0, 0, 0, &Error, &ExecutionFailed);
+ ASSERT_EQ(PI.Pid, 0)
+ << "On error ExecuteNoWait should return an invalid ProcessInfo";
+ ASSERT_TRUE(ExecutionFailed);
+ ASSERT_FALSE(Error.empty());
+ }
+
+}
+
} // end anonymous namespace
diff --git a/unittests/Support/RegexTest.cpp b/unittests/Support/RegexTest.cpp
index 3577d1015e915..7b977f7446681 100644
--- a/unittests/Support/RegexTest.cpp
+++ b/unittests/Support/RegexTest.cpp
@@ -112,4 +112,27 @@ TEST_F(RegexTest, Substitution) {
EXPECT_EQ(Error, "invalid backreference string '100'");
}
+TEST_F(RegexTest, IsLiteralERE) {
+ EXPECT_TRUE(Regex::isLiteralERE("abc"));
+ EXPECT_FALSE(Regex::isLiteralERE("a(bc)"));
+ EXPECT_FALSE(Regex::isLiteralERE("^abc"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc$"));
+ EXPECT_FALSE(Regex::isLiteralERE("a|bc"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc*"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc+"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc?"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc."));
+ EXPECT_FALSE(Regex::isLiteralERE("a[bc]"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc\\1"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc{1,2}"));
+}
+
+TEST_F(RegexTest, IsValid) {
+ std::string Error;
+ EXPECT_FALSE(Regex("(foo").isValid(Error));
+ EXPECT_EQ("parentheses not balanced", Error);
+ EXPECT_FALSE(Regex("a[b-").isValid(Error));
+ EXPECT_EQ("invalid character range", Error);
+}
+
}
diff --git a/unittests/Support/SourceMgrTest.cpp b/unittests/Support/SourceMgrTest.cpp
new file mode 100644
index 0000000000000..2b69fe984445e
--- /dev/null
+++ b/unittests/Support/SourceMgrTest.cpp
@@ -0,0 +1,174 @@
+//===- unittests/Support/SourceMgrTest.cpp - SourceMgr tests --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class SourceMgrTest : public testing::Test {
+public:
+ SourceMgr SM;
+ unsigned MainBufferID;
+ std::string Output;
+
+ void setMainBuffer(StringRef Text, StringRef BufferName) {
+ MemoryBuffer *MainBuffer = MemoryBuffer::getMemBuffer(Text, BufferName);
+ MainBufferID = SM.AddNewSourceBuffer(MainBuffer, llvm::SMLoc());
+ }
+
+ SMLoc getLoc(unsigned Offset) {
+ return SMLoc::getFromPointer(
+ SM.getMemoryBuffer(MainBufferID)->getBufferStart() + Offset);
+ }
+
+ SMRange getRange(unsigned Offset, unsigned Length) {
+ return SMRange(getLoc(Offset), getLoc(Offset + Length));
+ }
+
+ void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
+ const Twine &Msg, ArrayRef<SMRange> Ranges,
+ ArrayRef<SMFixIt> FixIts) {
+ raw_string_ostream OS(Output);
+ SM.PrintMessage(OS, Loc, Kind, Msg, Ranges, FixIts);
+ }
+};
+
+} // unnamed namespace
+
+TEST_F(SourceMgrTest, BasicError) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", None, None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicWarning) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Warning, "message", None, None);
+
+ EXPECT_EQ("file.in:1:5: warning: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicNote) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Note, "message", None, None);
+
+ EXPECT_EQ("file.in:1:5: note: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, LocationAtEndOfLine) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(6), SourceMgr::DK_Error, "message", None, None);
+
+ EXPECT_EQ("file.in:1:7: error: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, LocationAtNewline) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(7), SourceMgr::DK_Error, "message", None, None);
+
+ EXPECT_EQ("file.in:1:8: error: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicRange) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(4, 3), None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^~~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, RangeWithTab) {
+ setMainBuffer("aaa\tbbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(3, 3), None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ~~~~~^~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, MultiLineRange) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(4, 7), None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^~~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, MultipleRanges) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ SMRange Ranges[] = { getRange(0, 3), getRange(4, 3) };
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", Ranges, None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ "~~~ ^~~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, OverlappingRanges) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ SMRange Ranges[] = { getRange(0, 3), getRange(2, 4) };
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", Ranges, None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ "~~~~^~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicFixit) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", None,
+ makeArrayRef(SMFixIt(getRange(4, 3), "zzz")));
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^~~\n"
+ " zzz\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, FixitForTab) {
+ setMainBuffer("aaa\tbbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(3), SourceMgr::DK_Error, "message", None,
+ makeArrayRef(SMFixIt(getRange(3, 1), "zzz")));
+
+ EXPECT_EQ("file.in:1:4: error: message\n"
+ "aaa bbb\n"
+ " ^^^^^\n"
+ " zzz\n",
+ Output);
+}
+
diff --git a/unittests/Support/ThreadLocalTest.cpp b/unittests/Support/ThreadLocalTest.cpp
new file mode 100644
index 0000000000000..dd4d706f5cf52
--- /dev/null
+++ b/unittests/Support/ThreadLocalTest.cpp
@@ -0,0 +1,38 @@
+//===- llvm/unittest/Support/ThreadLocalTest.cpp - Therad Local tests ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ThreadLocal.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace sys;
+
+namespace {
+
+class ThreadLocalTest : public ::testing::Test {
+};
+
+struct S {
+ int i;
+};
+
+TEST_F(ThreadLocalTest, Basics) {
+ ThreadLocal<const S> x;
+
+ EXPECT_EQ(0, x.get());
+
+ S s;
+ x.set(&s);
+ EXPECT_EQ(&s, x.get());
+
+ x.erase();
+ EXPECT_EQ(0, x.get());
+}
+
+}
diff --git a/unittests/Support/TimeValue.cpp b/unittests/Support/TimeValue.cpp
deleted file mode 100644
index 27883ae335640..0000000000000
--- a/unittests/Support/TimeValue.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//===- llvm/unittest/Support/TimeValue.cpp - Time Value tests -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "gtest/gtest.h"
-#include "llvm/Support/TimeValue.h"
-#include <time.h>
-
-using namespace llvm;
-namespace {
-
-TEST(Support, TimeValue) {
- sys::TimeValue now = sys::TimeValue::now();
- time_t now_t = time(NULL);
- EXPECT_TRUE(abs(static_cast<long>(now_t - now.toEpochTime())) < 2);
-}
-
-}
diff --git a/unittests/Support/TimeValueTest.cpp b/unittests/Support/TimeValueTest.cpp
new file mode 100644
index 0000000000000..fb2abe382932f
--- /dev/null
+++ b/unittests/Support/TimeValueTest.cpp
@@ -0,0 +1,39 @@
+//===- llvm/unittest/Support/TimeValueTest.cpp - Time Value tests ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/Support/TimeValue.h"
+#include <time.h>
+
+using namespace llvm;
+namespace {
+
+TEST(TimeValue, time_t) {
+ sys::TimeValue now = sys::TimeValue::now();
+ time_t now_t = time(NULL);
+ EXPECT_TRUE(abs(static_cast<long>(now_t - now.toEpochTime())) < 2);
+}
+
+TEST(TimeValue, Win32FILETIME) {
+ uint64_t epoch_as_filetime = 0x19DB1DED53E8000ULL;
+ uint32_t ns = 765432100;
+ sys::TimeValue epoch;
+
+ // FILETIME has 100ns of intervals.
+ uint64_t ft1970 = epoch_as_filetime + ns / 100;
+ epoch.fromWin32Time(ft1970);
+
+ // The "seconds" part in Posix time may be expected as zero.
+ EXPECT_EQ(ns / 100, epoch.toPosixTime());
+
+ // Confirm it reversible.
+ EXPECT_EQ(ft1970, epoch.toWin32Time());
+}
+
+}
diff --git a/unittests/Support/UnicodeTest.cpp b/unittests/Support/UnicodeTest.cpp
new file mode 100644
index 0000000000000..0733397d45c66
--- /dev/null
+++ b/unittests/Support/UnicodeTest.cpp
@@ -0,0 +1,93 @@
+//===- unittests/Support/UnicodeTest.cpp - Unicode.h tests ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Unicode.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace sys {
+namespace unicode {
+namespace {
+
+TEST(Unicode, columnWidthUTF8) {
+ EXPECT_EQ(0, columnWidthUTF8(""));
+ EXPECT_EQ(1, columnWidthUTF8(" "));
+ EXPECT_EQ(1, columnWidthUTF8("a"));
+ EXPECT_EQ(1, columnWidthUTF8("~"));
+
+ EXPECT_EQ(6, columnWidthUTF8("abcdef"));
+
+ EXPECT_EQ(-1, columnWidthUTF8("\x01"));
+ EXPECT_EQ(-1, columnWidthUTF8("aaaaaaaaaa\x01"));
+ EXPECT_EQ(-1, columnWidthUTF8("\342\200\213")); // 200B ZERO WIDTH SPACE
+
+ // 00AD SOFT HYPHEN is displayed on most terminals as a space or a dash. Some
+ // text editors display it only when a line is broken at it, some use it as a
+ // line-break hint, but don't display. We choose terminal-oriented
+ // interpretation.
+ EXPECT_EQ(1, columnWidthUTF8("\302\255"));
+
+ EXPECT_EQ(0, columnWidthUTF8("\314\200")); // 0300 COMBINING GRAVE ACCENT
+ EXPECT_EQ(1, columnWidthUTF8("\340\270\201")); // 0E01 THAI CHARACTER KO KAI
+ EXPECT_EQ(2, columnWidthUTF8("\344\270\200")); // CJK UNIFIED IDEOGRAPH-4E00
+
+ EXPECT_EQ(4, columnWidthUTF8("\344\270\200\344\270\200"));
+ EXPECT_EQ(3, columnWidthUTF8("q\344\270\200"));
+ EXPECT_EQ(3, columnWidthUTF8("\314\200\340\270\201\344\270\200"));
+
+ // Invalid UTF-8 strings, columnWidthUTF8 should error out.
+ EXPECT_EQ(-2, columnWidthUTF8("\344"));
+ EXPECT_EQ(-2, columnWidthUTF8("\344\270"));
+ EXPECT_EQ(-2, columnWidthUTF8("\344\270\033"));
+ EXPECT_EQ(-2, columnWidthUTF8("\344\270\300"));
+ EXPECT_EQ(-2, columnWidthUTF8("\377\366\355"));
+
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344\270"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344\270\033"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344\270\300"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\377\366\355"));
+
+ // UTF-8 sequences longer than 4 bytes correspond to unallocated Unicode
+ // characters.
+ EXPECT_EQ(-2, columnWidthUTF8("\370\200\200\200\200")); // U+200000
+ EXPECT_EQ(-2, columnWidthUTF8("\374\200\200\200\200\200")); // U+4000000
+}
+
+TEST(Unicode, isPrintable) {
+ EXPECT_FALSE(isPrintable(0)); // <control-0000>-<control-001F>
+ EXPECT_FALSE(isPrintable(0x01));
+ EXPECT_FALSE(isPrintable(0x1F));
+ EXPECT_TRUE(isPrintable(' '));
+ EXPECT_TRUE(isPrintable('A'));
+ EXPECT_TRUE(isPrintable('~'));
+ EXPECT_FALSE(isPrintable(0x7F)); // <control-007F>..<control-009F>
+ EXPECT_FALSE(isPrintable(0x90));
+ EXPECT_FALSE(isPrintable(0x9F));
+
+ EXPECT_TRUE(isPrintable(0xAC));
+ EXPECT_TRUE(isPrintable(0xAD)); // SOFT HYPHEN is displayed on most terminals
+ // as either a space or a dash.
+ EXPECT_TRUE(isPrintable(0xAE));
+
+ EXPECT_TRUE(isPrintable(0x0377)); // GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
+ EXPECT_FALSE(isPrintable(0x0378)); // <reserved-0378>..<reserved-0379>
+
+ EXPECT_FALSE(isPrintable(0x0600)); // ARABIC NUMBER SIGN
+
+ EXPECT_FALSE(isPrintable(0x1FFFF)); // <reserved-1F774>..<noncharacter-1FFFF>
+ EXPECT_TRUE(isPrintable(0x20000)); // CJK UNIFIED IDEOGRAPH-20000
+
+ EXPECT_FALSE(isPrintable(0x10FFFF)); // noncharacter
+}
+
+} // namespace
+} // namespace unicode
+} // namespace sys
+} // namespace llvm
diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp
index 0993d8c0b555e..6c0b9e6151f20 100644
--- a/unittests/Support/YAMLIOTest.cpp
+++ b/unittests/Support/YAMLIOTest.cpp
@@ -58,14 +58,24 @@ namespace yaml {
//
TEST(YAMLIO, TestMapRead) {
FooBar doc;
- Input yin("---\nfoo: 3\nbar: 5\n...\n");
- yin >> doc;
+ {
+ Input yin("---\nfoo: 3\nbar: 5\n...\n");
+ yin >> doc;
- EXPECT_FALSE(yin.error());
- EXPECT_EQ(doc.foo, 3);
- EXPECT_EQ(doc.bar,5);
-}
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(doc.foo, 3);
+ EXPECT_EQ(doc.bar, 5);
+ }
+ {
+ Input yin("{foo: 3, bar: 5}");
+ yin >> doc;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(doc.foo, 3);
+ EXPECT_EQ(doc.bar, 5);
+ }
+}
//
// Test the reading of a yaml sequence of mappings
@@ -273,7 +283,64 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes) {
}
}
+struct StringTypes {
+ llvm::StringRef str1;
+ llvm::StringRef str2;
+ llvm::StringRef str3;
+ llvm::StringRef str4;
+ llvm::StringRef str5;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<StringTypes> {
+ static void mapping(IO &io, StringTypes& st) {
+ io.mapRequired("str1", st.str1);
+ io.mapRequired("str2", st.str2);
+ io.mapRequired("str3", st.str3);
+ io.mapRequired("str4", st.str4);
+ io.mapRequired("str5", st.str5);
+ }
+ };
+}
+}
+
+TEST(YAMLIO, TestReadWriteStringTypes) {
+ std::string intermediate;
+ {
+ StringTypes map;
+ map.str1 = "'aaa";
+ map.str2 = "\"bbb";
+ map.str3 = "`ccc";
+ map.str4 = "@ddd";
+ map.str5 = "";
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+ }
+ llvm::StringRef flowOut(intermediate);
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
+
+ {
+ Input yin(intermediate);
+ StringTypes map;
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_TRUE(map.str1.equals("'aaa"));
+ EXPECT_TRUE(map.str2.equals("\"bbb"));
+ EXPECT_TRUE(map.str3.equals("`ccc"));
+ EXPECT_TRUE(map.str4.equals("@ddd"));
+ EXPECT_TRUE(map.str5.equals(""));
+ }
+}
//===----------------------------------------------------------------------===//
// Test ScalarEnumerationTraits
@@ -600,9 +667,9 @@ TEST(YAMLIO, TestReadWriteMyFlowSequence) {
map.numbers.push_back(1024);
llvm::raw_string_ostream ostr(intermediate);
- Output yout(ostr);
+ Output yout(ostr);
yout << map;
-
+
// Verify sequences were written in flow style
ostr.flush();
llvm::StringRef flowOut(intermediate);
@@ -932,6 +999,161 @@ TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
}
}
+//===----------------------------------------------------------------------===//
+// Test document tags
+//===----------------------------------------------------------------------===//
+
+struct MyDouble {
+ MyDouble() : value(0.0) { }
+ MyDouble(double x) : value(x) { }
+ double value;
+};
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
+
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<MyDouble> {
+ static void mapping(IO &io, MyDouble &d) {
+ if (io.mapTag("!decimal", true)) {
+ mappingDecimal(io, d);
+ } else if (io.mapTag("!fraction")) {
+ mappingFraction(io, d);
+ }
+ }
+ static void mappingDecimal(IO &io, MyDouble &d) {
+ io.mapRequired("value", d.value);
+ }
+ static void mappingFraction(IO &io, MyDouble &d) {
+ double num, denom;
+ io.mapRequired("numerator", num);
+ io.mapRequired("denominator", denom);
+ // convert fraction to double
+ d.value = num/denom;
+ }
+ };
+ }
+}
+
+
+//
+// Test the reading of two different tagged yaml documents.
+//
+TEST(YAMLIO, TestTaggedDocuments) {
+ std::vector<MyDouble> docList;
+ Input yin("--- !decimal\nvalue: 3.0\n"
+ "--- !fraction\nnumerator: 9.0\ndenominator: 2\n...\n");
+ yin >> docList;
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(docList.size(), 2UL);
+ EXPECT_EQ(docList[0].value, 3.0);
+ EXPECT_EQ(docList[1].value, 4.5);
+}
+
+
+
+//
+// Test writing then reading back tagged documents
+//
+TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
+ std::string intermediate;
+ {
+ MyDouble a(10.25);
+ MyDouble b(-3.75);
+ std::vector<MyDouble> docList;
+ docList.push_back(a);
+ docList.push_back(b);
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << docList;
+ }
+
+ {
+ Input yin(intermediate);
+ std::vector<MyDouble> docList2;
+ yin >> docList2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(docList2.size(), 2UL);
+ EXPECT_EQ(docList2[0].value, 10.25);
+ EXPECT_EQ(docList2[1].value, -3.75);
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Test dyn_cast<> on IO object
+//===----------------------------------------------------------------------===//
+
+struct DynCast {
+ int value;
+};
+typedef std::vector<DynCast> DynCastSequence;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(DynCast)
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<DynCast> {
+ static void mapping(IO &io, DynCast& info) {
+ // Change 10 to 13 when writing yaml.
+ if (Output *output = dyn_cast<Output>(&io)) {
+ (void)output;
+ if (info.value == 10)
+ info.value = 13;
+ }
+ io.mapRequired("value", info.value);
+ // Change 20 to 23 when parsing yaml.
+ if (Input *input = dyn_cast<Input>(&io)) {
+ (void)input;
+ if (info.value == 20)
+ info.value = 23;
+ }
+ }
+ };
+}
+}
+
+//
+// Test writing then reading back a sequence of mappings
+//
+TEST(YAMLIO, TestDynCast) {
+ std::string intermediate;
+ {
+ DynCast entry1;
+ entry1.value = 10;
+ DynCast entry2;
+ entry2.value = 20;
+ DynCast entry3;
+ entry3.value = 30;
+ DynCastSequence seq;
+ seq.push_back(entry1);
+ seq.push_back(entry2);
+ seq.push_back(entry3);
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << seq;
+ }
+
+ {
+ Input yin(intermediate);
+ DynCastSequence seq2;
+ yin >> seq2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(seq2.size(), 3UL);
+ EXPECT_EQ(seq2[0].value, 13); // Verify changed to 13.
+ EXPECT_EQ(seq2[1].value, 23); // Verify changed to 23.
+ EXPECT_EQ(seq2[2].value, 30); // Verify stays same.
+ }
+}
+
+
//===----------------------------------------------------------------------===//
// Test error handling
@@ -952,8 +1174,9 @@ TEST(YAMLIO, TestColorsReadError) {
"c1: blue\n"
"c2: purple\n"
"c3: green\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> map;
EXPECT_TRUE(yin.error());
}
@@ -968,8 +1191,9 @@ TEST(YAMLIO, TestFlagsReadError) {
"f1: [ big ]\n"
"f2: [ round, hollow ]\n"
"f3: []\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> map;
EXPECT_TRUE(yin.error());
@@ -986,8 +1210,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
"- 255\n"
"- 0\n"
"- 257\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1004,8 +1229,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
"- 65535\n"
"- 0\n"
"- 66000\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1022,8 +1248,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
"- 4000000000\n"
"- 0\n"
"- 5000000000\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1040,8 +1267,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
"- 18446744073709551615\n"
"- 0\n"
"- 19446744073709551615\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1059,8 +1287,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
"- 0\n"
"- 127\n"
"- 128\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1076,8 +1305,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
"- 0\n"
"- 127\n"
"- -129\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1095,8 +1325,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
"- 0\n"
"- -32768\n"
"- -32769\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1113,8 +1344,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
"- 0\n"
"- -32768\n"
"- 32768\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1132,8 +1364,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
"- 0\n"
"- -2147483648\n"
"- -2147483649\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1149,8 +1382,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
"- 0\n"
"- -2147483648\n"
"- 2147483649\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1168,8 +1402,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
"- 0\n"
"- 9223372036854775807\n"
"- -9223372036854775809\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1185,8 +1420,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
"- 0\n"
"- 9223372036854775807\n"
"- 9223372036854775809\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1203,8 +1439,9 @@ TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
"- 1000.1\n"
"- -123.456\n"
"- 1.2.3\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1221,8 +1458,9 @@ TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
"- 1000.1\n"
"- -123.456\n"
"- 1.2.3\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1238,8 +1476,9 @@ TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
"- 0x12\n"
"- 0xFE\n"
"- 0x123\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1256,8 +1495,9 @@ TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
"- 0x0012\n"
"- 0xFEFF\n"
"- 0x12345\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1273,8 +1513,9 @@ TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
"- 0x0012\n"
"- 0xFEFF0000\n"
"- 0x1234556789\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1290,10 +1531,114 @@ TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
"- 0x0012\n"
"- 0xFFEEDDCCBBAA9988\n"
"- 0x12345567890ABCDEF0\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
}
+TEST(YAMLIO, TestMalformedMapFailsGracefully) {
+ FooBar doc;
+ {
+ // We pass the suppressErrorMessages handler to handle the error
+ // message generated in the constructor of Input.
+ Input yin("{foo:3, bar: 5}", /*Ctxt=*/NULL, suppressErrorMessages);
+ yin >> doc;
+ EXPECT_TRUE(yin.error());
+ }
+
+ {
+ Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/NULL, suppressErrorMessages);
+ yin >> doc;
+ EXPECT_TRUE(yin.error());
+ }
+}
+
+struct OptionalTest {
+ std::vector<int> Numbers;
+};
+
+struct OptionalTestSeq {
+ std::vector<OptionalTest> Tests;
+};
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<OptionalTest> {
+ static void mapping(IO& IO, OptionalTest &OT) {
+ IO.mapOptional("Numbers", OT.Numbers);
+ }
+ };
+
+ template <>
+ struct MappingTraits<OptionalTestSeq> {
+ static void mapping(IO &IO, OptionalTestSeq &OTS) {
+ IO.mapOptional("Tests", OTS.Tests);
+ }
+ };
+}
+}
+
+TEST(YAMLIO, SequenceElideTest) {
+ // Test that writing out a purely optional structure with its fields set to
+ // default followed by other data is properly read back in.
+ OptionalTestSeq Seq;
+ OptionalTest One, Two, Three, Four;
+ int N[] = {1, 2, 3};
+ Three.Numbers.assign(N, N + 3);
+ Seq.Tests.push_back(One);
+ Seq.Tests.push_back(Two);
+ Seq.Tests.push_back(Three);
+ Seq.Tests.push_back(Four);
+
+ std::string intermediate;
+ {
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << Seq;
+ }
+
+ Input yin(intermediate);
+ OptionalTestSeq Seq2;
+ yin >> Seq2;
+
+ EXPECT_FALSE(yin.error());
+
+ EXPECT_EQ(4UL, Seq2.Tests.size());
+
+ EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
+ EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
+
+ EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
+ EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
+ EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
+
+ EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
+}
+
+TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
+ FooBar doc;
+ Input yin("");
+ yin >> doc;
+ EXPECT_TRUE(yin.error());
+}
+
+TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
+ OptionalTest doc;
+ Input yin("");
+ yin >> doc;
+ EXPECT_FALSE(yin.error());
+}
+
+TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
+ std::vector<uint8_t> seq;
+ Input yin("", /*Ctxt=*/NULL, suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_TRUE(seq.empty());
+}