xref: /llvm-project/lldb/unittests/Utility/StreamTeeTest.cpp (revision 808142876c10b52e7ee57cdc6dcf0acc5c97c1b7)
1*80814287SRaphael Isemann //===-- StreamTeeTest.cpp -------------------------------------------------===//
26188a425SRaphael Isemann //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66188a425SRaphael Isemann //
76188a425SRaphael Isemann //===----------------------------------------------------------------------===//
86188a425SRaphael Isemann 
96188a425SRaphael Isemann #include "lldb/Utility/StreamTee.h"
106188a425SRaphael Isemann #include "lldb/Utility/StreamString.h"
116188a425SRaphael Isemann #include "gtest/gtest.h"
126188a425SRaphael Isemann 
136188a425SRaphael Isemann using namespace lldb_private;
146188a425SRaphael Isemann 
TEST(StreamTeeTest,DefaultConstructor)156188a425SRaphael Isemann TEST(StreamTeeTest, DefaultConstructor) {
166188a425SRaphael Isemann   // Test the default constructor.
176188a425SRaphael Isemann   StreamTee tee;
186188a425SRaphael Isemann   ASSERT_EQ(0U, tee.GetNumStreams());
196188a425SRaphael Isemann }
206188a425SRaphael Isemann 
TEST(StreamTeeTest,Constructor1Stream)216188a425SRaphael Isemann TEST(StreamTeeTest, Constructor1Stream) {
226188a425SRaphael Isemann   // Test the constructor for a single stream.
236188a425SRaphael Isemann   lldb::StreamSP s1(std::make_shared<StreamString>());
246188a425SRaphael Isemann   StreamTee tee(s1);
256188a425SRaphael Isemann 
266188a425SRaphael Isemann   ASSERT_EQ(1U, tee.GetNumStreams());
276188a425SRaphael Isemann   EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
286188a425SRaphael Isemann }
296188a425SRaphael Isemann 
TEST(StreamTeeTest,Constructor2Streams)306188a425SRaphael Isemann TEST(StreamTeeTest, Constructor2Streams) {
316188a425SRaphael Isemann   // Test the constructor for two streams.
326188a425SRaphael Isemann   lldb::StreamSP s1(std::make_shared<StreamString>());
336188a425SRaphael Isemann   lldb::StreamSP s2(std::make_shared<StreamString>());
346188a425SRaphael Isemann   StreamTee tee(s1, s2);
356188a425SRaphael Isemann 
366188a425SRaphael Isemann   ASSERT_EQ(2U, tee.GetNumStreams());
376188a425SRaphael Isemann   EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
386188a425SRaphael Isemann   EXPECT_EQ(s2, tee.GetStreamAtIndex(1U));
396188a425SRaphael Isemann }
406188a425SRaphael Isemann 
TEST(StreamTeeTest,CopyConstructor)416188a425SRaphael Isemann TEST(StreamTeeTest, CopyConstructor) {
426188a425SRaphael Isemann   // Test the copy constructor.
436188a425SRaphael Isemann   lldb::StreamSP s1(std::make_shared<StreamString>());
446188a425SRaphael Isemann   lldb::StreamSP s2(std::make_shared<StreamString>());
456188a425SRaphael Isemann   StreamTee tee1(s1, s2);
466188a425SRaphael Isemann   StreamTee tee2(tee1);
476188a425SRaphael Isemann 
486188a425SRaphael Isemann   ASSERT_EQ(2U, tee2.GetNumStreams());
496188a425SRaphael Isemann   EXPECT_EQ(s1, tee2.GetStreamAtIndex(0U));
506188a425SRaphael Isemann   EXPECT_EQ(s2, tee2.GetStreamAtIndex(1U));
516188a425SRaphael Isemann }
526188a425SRaphael Isemann 
TEST(StreamTeeTest,Assignment)536188a425SRaphael Isemann TEST(StreamTeeTest, Assignment) {
546188a425SRaphael Isemann   // Test the assignment of StreamTee.
556188a425SRaphael Isemann   lldb::StreamSP s1(std::make_shared<StreamString>());
566188a425SRaphael Isemann   lldb::StreamSP s2(std::make_shared<StreamString>());
576188a425SRaphael Isemann   StreamTee tee1(s1, s2);
586188a425SRaphael Isemann   StreamTee tee2 = tee1;
596188a425SRaphael Isemann 
606188a425SRaphael Isemann   ASSERT_EQ(2U, tee2.GetNumStreams());
616188a425SRaphael Isemann   EXPECT_EQ(s1, tee2.GetStreamAtIndex(0U));
626188a425SRaphael Isemann   EXPECT_EQ(s2, tee2.GetStreamAtIndex(1U));
636188a425SRaphael Isemann }
646188a425SRaphael Isemann 
TEST(StreamTeeTest,Write)656188a425SRaphael Isemann TEST(StreamTeeTest, Write) {
666188a425SRaphael Isemann   // Test that write is sent out to all children.
676188a425SRaphael Isemann   auto ss1 = new StreamString();
686188a425SRaphael Isemann   auto ss2 = new StreamString();
696188a425SRaphael Isemann   lldb::StreamSP s1(ss1);
706188a425SRaphael Isemann   lldb::StreamSP s2(ss2);
716188a425SRaphael Isemann   StreamTee tee(s1, s2);
726188a425SRaphael Isemann 
736188a425SRaphael Isemann   tee << "foo";
746188a425SRaphael Isemann   tee.Flush();
756188a425SRaphael Isemann 
766188a425SRaphael Isemann   ASSERT_EQ(2U, tee.GetNumStreams());
776188a425SRaphael Isemann   EXPECT_EQ("foo", ss1->GetString().str());
786188a425SRaphael Isemann   EXPECT_EQ("foo", ss2->GetString().str());
796188a425SRaphael Isemann 
806188a425SRaphael Isemann   tee << "bar";
816188a425SRaphael Isemann   tee.Flush();
826188a425SRaphael Isemann   EXPECT_EQ("foobar", ss1->GetString().str());
836188a425SRaphael Isemann   EXPECT_EQ("foobar", ss2->GetString().str());
846188a425SRaphael Isemann }
856188a425SRaphael Isemann 
866188a425SRaphael Isemann namespace {
876188a425SRaphael Isemann   struct FlushTestStream : public Stream {
886188a425SRaphael Isemann     unsigned m_flush_count = false;
Flush__anon1fdb2d2f0111::FlushTestStream896188a425SRaphael Isemann     void Flush() override {
906188a425SRaphael Isemann       ++m_flush_count;
916188a425SRaphael Isemann     }
WriteImpl__anon1fdb2d2f0111::FlushTestStream9292b16738SRaphael Isemann     size_t WriteImpl(const void *src, size_t src_len) override {
9392b16738SRaphael Isemann       return src_len;
9492b16738SRaphael Isemann     }
956188a425SRaphael Isemann   };
966188a425SRaphael Isemann }
976188a425SRaphael Isemann 
TEST(StreamTeeTest,Flush)986188a425SRaphael Isemann TEST(StreamTeeTest, Flush) {
996188a425SRaphael Isemann   // Check that Flush is distributed to all streams.
1006188a425SRaphael Isemann   auto fs1 = new FlushTestStream();
1016188a425SRaphael Isemann   auto fs2 = new FlushTestStream();
1026188a425SRaphael Isemann   lldb::StreamSP s1(fs1);
1036188a425SRaphael Isemann   lldb::StreamSP s2(fs2);
1046188a425SRaphael Isemann   StreamTee tee(s1, s2);
1056188a425SRaphael Isemann 
1066188a425SRaphael Isemann   tee << "foo";
1076188a425SRaphael Isemann   tee.Flush();
1086188a425SRaphael Isemann 
1096188a425SRaphael Isemann   ASSERT_EQ(2U, tee.GetNumStreams());
1106188a425SRaphael Isemann   EXPECT_EQ(1U, fs1->m_flush_count);
1116188a425SRaphael Isemann   EXPECT_EQ(1U, fs2->m_flush_count);
1126188a425SRaphael Isemann 
1136188a425SRaphael Isemann   tee << "bar";
1146188a425SRaphael Isemann   tee.Flush();
1156188a425SRaphael Isemann   EXPECT_EQ(2U, fs1->m_flush_count);
1166188a425SRaphael Isemann   EXPECT_EQ(2U, fs2->m_flush_count);
1176188a425SRaphael Isemann }
1186188a425SRaphael Isemann 
TEST(StreamTeeTest,AppendStream)1196188a425SRaphael Isemann TEST(StreamTeeTest, AppendStream) {
1206188a425SRaphael Isemann   // Append new streams to our StreamTee.
1216188a425SRaphael Isemann   auto ss1 = new StreamString();
1226188a425SRaphael Isemann   auto ss2 = new StreamString();
1236188a425SRaphael Isemann   lldb::StreamSP s1(ss1);
1246188a425SRaphael Isemann   lldb::StreamSP s2(ss2);
1256188a425SRaphael Isemann 
1266188a425SRaphael Isemann   StreamTee tee;
1276188a425SRaphael Isemann 
1286188a425SRaphael Isemann   ASSERT_EQ(0U, tee.GetNumStreams());
1296188a425SRaphael Isemann 
1306188a425SRaphael Isemann   tee.AppendStream(s1);
1316188a425SRaphael Isemann   ASSERT_EQ(1U, tee.GetNumStreams());
1326188a425SRaphael Isemann   EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
1336188a425SRaphael Isemann 
1346188a425SRaphael Isemann   tee.AppendStream(s2);
1356188a425SRaphael Isemann   ASSERT_EQ(2U, tee.GetNumStreams());
1366188a425SRaphael Isemann   EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
1376188a425SRaphael Isemann   EXPECT_EQ(s2, tee.GetStreamAtIndex(1U));
1386188a425SRaphael Isemann }
1396188a425SRaphael Isemann 
TEST(StreamTeeTest,GetStreamAtIndexOutOfBounds)1406188a425SRaphael Isemann TEST(StreamTeeTest, GetStreamAtIndexOutOfBounds) {
1416188a425SRaphael Isemann   // The index we check for is not in the bounds of the StreamTee.
1426188a425SRaphael Isemann   lldb::StreamSP s1(std::make_shared<StreamString>());
1436188a425SRaphael Isemann   StreamTee tee(s1);
1446188a425SRaphael Isemann 
1456188a425SRaphael Isemann   ASSERT_EQ(1U, tee.GetNumStreams());
1466188a425SRaphael Isemann   EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1));
1476188a425SRaphael Isemann }
1486188a425SRaphael Isemann 
TEST(StreamTeeTest,GetStreamAtIndexOutOfBoundsEmpty)1496188a425SRaphael Isemann TEST(StreamTeeTest, GetStreamAtIndexOutOfBoundsEmpty) {
1506188a425SRaphael Isemann   // Same as above, but with an empty StreamTee.
1516188a425SRaphael Isemann   StreamTee tee;
1526188a425SRaphael Isemann   ASSERT_EQ(0U, tee.GetNumStreams());
1536188a425SRaphael Isemann   EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(0U));
1546188a425SRaphael Isemann   EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U));
1556188a425SRaphael Isemann }
1566188a425SRaphael Isemann 
TEST(StreamTeeTest,SetStreamAtIndexOverwrite)1576188a425SRaphael Isemann TEST(StreamTeeTest, SetStreamAtIndexOverwrite) {
1586188a425SRaphael Isemann   // We overwrite an existing stream at a given index.
1596188a425SRaphael Isemann   lldb::StreamSP s1(std::make_shared<StreamString>());
1606188a425SRaphael Isemann   StreamTee tee(s1);
1616188a425SRaphael Isemann 
1626188a425SRaphael Isemann   ASSERT_EQ(1U, tee.GetNumStreams());
1636188a425SRaphael Isemann   EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
1646188a425SRaphael Isemann   EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U));
1656188a425SRaphael Isemann 
1666188a425SRaphael Isemann   lldb::StreamSP s2(std::make_shared<StreamString>());
1676188a425SRaphael Isemann   tee.SetStreamAtIndex(0U, s2);
1686188a425SRaphael Isemann   EXPECT_EQ(1U, tee.GetNumStreams());
1696188a425SRaphael Isemann   EXPECT_EQ(s2, tee.GetStreamAtIndex(0U));
1706188a425SRaphael Isemann   EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1));
1716188a425SRaphael Isemann }
1726188a425SRaphael Isemann 
TEST(StreamTeeTest,SetStreamAtIndexOutOfBounds)1736188a425SRaphael Isemann TEST(StreamTeeTest, SetStreamAtIndexOutOfBounds) {
1746188a425SRaphael Isemann   // We place a new stream out of the bounds of the current StreamTee.
1756188a425SRaphael Isemann   lldb::StreamSP s1(std::make_shared<StreamString>());
1766188a425SRaphael Isemann   StreamTee tee(s1);
1776188a425SRaphael Isemann 
1786188a425SRaphael Isemann   ASSERT_EQ(1U, tee.GetNumStreams());
1796188a425SRaphael Isemann   EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
1806188a425SRaphael Isemann   EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U));
1816188a425SRaphael Isemann 
1826188a425SRaphael Isemann   // Place a new stream out of bounds of the current array. The StreamTee should
1836188a425SRaphael Isemann   // resize itself until it can contain this index.
1846188a425SRaphael Isemann   lldb::StreamSP s2(std::make_shared<StreamString>());
1856188a425SRaphael Isemann   tee.SetStreamAtIndex(4U, s2);
1866188a425SRaphael Isemann   // Check that the vector has been resized.
1876188a425SRaphael Isemann   EXPECT_EQ(5U, tee.GetNumStreams());
1886188a425SRaphael Isemann   // Is our stream at the right place?
1896188a425SRaphael Isemann   EXPECT_EQ(s2, tee.GetStreamAtIndex(4U));
1906188a425SRaphael Isemann 
1916188a425SRaphael Isemann   // Existing stream should still be there.
1926188a425SRaphael Isemann   EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
1936188a425SRaphael Isemann   // Other elements are all invalid StreamSPs.
1946188a425SRaphael Isemann   EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U));
1956188a425SRaphael Isemann   EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(2U));
1966188a425SRaphael Isemann   EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(3U));
1976188a425SRaphael Isemann   EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(5U));
1986188a425SRaphael Isemann }
199