1 //===-- StreamTeeTest.cpp ---------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Utility/StreamTee.h" 11 #include "lldb/Utility/StreamString.h" 12 #include "gtest/gtest.h" 13 14 using namespace lldb_private; 15 16 TEST(StreamTeeTest, DefaultConstructor) { 17 // Test the default constructor. 18 StreamTee tee; 19 ASSERT_EQ(0U, tee.GetNumStreams()); 20 } 21 22 TEST(StreamTeeTest, Constructor1Stream) { 23 // Test the constructor for a single stream. 24 lldb::StreamSP s1(std::make_shared<StreamString>()); 25 StreamTee tee(s1); 26 27 ASSERT_EQ(1U, tee.GetNumStreams()); 28 EXPECT_EQ(s1, tee.GetStreamAtIndex(0U)); 29 } 30 31 TEST(StreamTeeTest, Constructor2Streams) { 32 // Test the constructor for two streams. 33 lldb::StreamSP s1(std::make_shared<StreamString>()); 34 lldb::StreamSP s2(std::make_shared<StreamString>()); 35 StreamTee tee(s1, s2); 36 37 ASSERT_EQ(2U, tee.GetNumStreams()); 38 EXPECT_EQ(s1, tee.GetStreamAtIndex(0U)); 39 EXPECT_EQ(s2, tee.GetStreamAtIndex(1U)); 40 } 41 42 TEST(StreamTeeTest, CopyConstructor) { 43 // Test the copy constructor. 44 lldb::StreamSP s1(std::make_shared<StreamString>()); 45 lldb::StreamSP s2(std::make_shared<StreamString>()); 46 StreamTee tee1(s1, s2); 47 StreamTee tee2(tee1); 48 49 ASSERT_EQ(2U, tee2.GetNumStreams()); 50 EXPECT_EQ(s1, tee2.GetStreamAtIndex(0U)); 51 EXPECT_EQ(s2, tee2.GetStreamAtIndex(1U)); 52 } 53 54 TEST(StreamTeeTest, Assignment) { 55 // Test the assignment of StreamTee. 56 lldb::StreamSP s1(std::make_shared<StreamString>()); 57 lldb::StreamSP s2(std::make_shared<StreamString>()); 58 StreamTee tee1(s1, s2); 59 StreamTee tee2 = tee1; 60 61 ASSERT_EQ(2U, tee2.GetNumStreams()); 62 EXPECT_EQ(s1, tee2.GetStreamAtIndex(0U)); 63 EXPECT_EQ(s2, tee2.GetStreamAtIndex(1U)); 64 } 65 66 TEST(StreamTeeTest, Write) { 67 // Test that write is sent out to all children. 68 auto ss1 = new StreamString(); 69 auto ss2 = new StreamString(); 70 lldb::StreamSP s1(ss1); 71 lldb::StreamSP s2(ss2); 72 StreamTee tee(s1, s2); 73 74 tee << "foo"; 75 tee.Flush(); 76 77 ASSERT_EQ(2U, tee.GetNumStreams()); 78 EXPECT_EQ("foo", ss1->GetString().str()); 79 EXPECT_EQ("foo", ss2->GetString().str()); 80 81 tee << "bar"; 82 tee.Flush(); 83 EXPECT_EQ("foobar", ss1->GetString().str()); 84 EXPECT_EQ("foobar", ss2->GetString().str()); 85 } 86 87 namespace { 88 struct FlushTestStream : public Stream { 89 unsigned m_flush_count = false; 90 void Flush() override { 91 ++m_flush_count; 92 } 93 size_t WriteImpl(const void *src, size_t src_len) override { 94 return src_len; 95 } 96 }; 97 } 98 99 TEST(StreamTeeTest, Flush) { 100 // Check that Flush is distributed to all streams. 101 auto fs1 = new FlushTestStream(); 102 auto fs2 = new FlushTestStream(); 103 lldb::StreamSP s1(fs1); 104 lldb::StreamSP s2(fs2); 105 StreamTee tee(s1, s2); 106 107 tee << "foo"; 108 tee.Flush(); 109 110 ASSERT_EQ(2U, tee.GetNumStreams()); 111 EXPECT_EQ(1U, fs1->m_flush_count); 112 EXPECT_EQ(1U, fs2->m_flush_count); 113 114 tee << "bar"; 115 tee.Flush(); 116 EXPECT_EQ(2U, fs1->m_flush_count); 117 EXPECT_EQ(2U, fs2->m_flush_count); 118 } 119 120 TEST(StreamTeeTest, AppendStream) { 121 // Append new streams to our StreamTee. 122 auto ss1 = new StreamString(); 123 auto ss2 = new StreamString(); 124 lldb::StreamSP s1(ss1); 125 lldb::StreamSP s2(ss2); 126 127 StreamTee tee; 128 129 ASSERT_EQ(0U, tee.GetNumStreams()); 130 131 tee.AppendStream(s1); 132 ASSERT_EQ(1U, tee.GetNumStreams()); 133 EXPECT_EQ(s1, tee.GetStreamAtIndex(0U)); 134 135 tee.AppendStream(s2); 136 ASSERT_EQ(2U, tee.GetNumStreams()); 137 EXPECT_EQ(s1, tee.GetStreamAtIndex(0U)); 138 EXPECT_EQ(s2, tee.GetStreamAtIndex(1U)); 139 } 140 141 TEST(StreamTeeTest, GetStreamAtIndexOutOfBounds) { 142 // The index we check for is not in the bounds of the StreamTee. 143 lldb::StreamSP s1(std::make_shared<StreamString>()); 144 StreamTee tee(s1); 145 146 ASSERT_EQ(1U, tee.GetNumStreams()); 147 EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1)); 148 } 149 150 TEST(StreamTeeTest, GetStreamAtIndexOutOfBoundsEmpty) { 151 // Same as above, but with an empty StreamTee. 152 StreamTee tee; 153 ASSERT_EQ(0U, tee.GetNumStreams()); 154 EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(0U)); 155 EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U)); 156 } 157 158 TEST(StreamTeeTest, SetStreamAtIndexOverwrite) { 159 // We overwrite an existing stream at a given index. 160 lldb::StreamSP s1(std::make_shared<StreamString>()); 161 StreamTee tee(s1); 162 163 ASSERT_EQ(1U, tee.GetNumStreams()); 164 EXPECT_EQ(s1, tee.GetStreamAtIndex(0U)); 165 EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U)); 166 167 lldb::StreamSP s2(std::make_shared<StreamString>()); 168 tee.SetStreamAtIndex(0U, s2); 169 EXPECT_EQ(1U, tee.GetNumStreams()); 170 EXPECT_EQ(s2, tee.GetStreamAtIndex(0U)); 171 EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1)); 172 } 173 174 TEST(StreamTeeTest, SetStreamAtIndexOutOfBounds) { 175 // We place a new stream out of the bounds of the current StreamTee. 176 lldb::StreamSP s1(std::make_shared<StreamString>()); 177 StreamTee tee(s1); 178 179 ASSERT_EQ(1U, tee.GetNumStreams()); 180 EXPECT_EQ(s1, tee.GetStreamAtIndex(0U)); 181 EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U)); 182 183 // Place a new stream out of bounds of the current array. The StreamTee should 184 // resize itself until it can contain this index. 185 lldb::StreamSP s2(std::make_shared<StreamString>()); 186 tee.SetStreamAtIndex(4U, s2); 187 // Check that the vector has been resized. 188 EXPECT_EQ(5U, tee.GetNumStreams()); 189 // Is our stream at the right place? 190 EXPECT_EQ(s2, tee.GetStreamAtIndex(4U)); 191 192 // Existing stream should still be there. 193 EXPECT_EQ(s1, tee.GetStreamAtIndex(0U)); 194 // Other elements are all invalid StreamSPs. 195 EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U)); 196 EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(2U)); 197 EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(3U)); 198 EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(5U)); 199 } 200