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

source code of lldb/unittests/Utility/StreamTeeTest.cpp