llvm-project/lldb/unittests/Utility/StreamTeeTest.cpp

200 lines
5.8 KiB
C++
Raw Normal View History

//===-- StreamTeeTest.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Utility/StreamTee.h"
#include "lldb/Utility/StreamString.h"
#include "gtest/gtest.h"
using namespace lldb_private;
TEST(StreamTeeTest, DefaultConstructor) {
// Test the default constructor.
StreamTee tee;
ASSERT_EQ(0U, tee.GetNumStreams());
}
TEST(StreamTeeTest, Constructor1Stream) {
// Test the constructor for a single stream.
lldb::StreamSP s1(std::make_shared<StreamString>());
StreamTee tee(s1);
ASSERT_EQ(1U, tee.GetNumStreams());
EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
}
TEST(StreamTeeTest, Constructor2Streams) {
// Test the constructor for two streams.
lldb::StreamSP s1(std::make_shared<StreamString>());
lldb::StreamSP s2(std::make_shared<StreamString>());
StreamTee tee(s1, s2);
ASSERT_EQ(2U, tee.GetNumStreams());
EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
EXPECT_EQ(s2, tee.GetStreamAtIndex(1U));
}
TEST(StreamTeeTest, CopyConstructor) {
// Test the copy constructor.
lldb::StreamSP s1(std::make_shared<StreamString>());
lldb::StreamSP s2(std::make_shared<StreamString>());
StreamTee tee1(s1, s2);
StreamTee tee2(tee1);
ASSERT_EQ(2U, tee2.GetNumStreams());
EXPECT_EQ(s1, tee2.GetStreamAtIndex(0U));
EXPECT_EQ(s2, tee2.GetStreamAtIndex(1U));
}
TEST(StreamTeeTest, Assignment) {
// Test the assignment of StreamTee.
lldb::StreamSP s1(std::make_shared<StreamString>());
lldb::StreamSP s2(std::make_shared<StreamString>());
StreamTee tee1(s1, s2);
StreamTee tee2 = tee1;
ASSERT_EQ(2U, tee2.GetNumStreams());
EXPECT_EQ(s1, tee2.GetStreamAtIndex(0U));
EXPECT_EQ(s2, tee2.GetStreamAtIndex(1U));
}
TEST(StreamTeeTest, Write) {
// Test that write is sent out to all children.
auto ss1 = new StreamString();
auto ss2 = new StreamString();
lldb::StreamSP s1(ss1);
lldb::StreamSP s2(ss2);
StreamTee tee(s1, s2);
tee << "foo";
tee.Flush();
ASSERT_EQ(2U, tee.GetNumStreams());
EXPECT_EQ("foo", ss1->GetString().str());
EXPECT_EQ("foo", ss2->GetString().str());
tee << "bar";
tee.Flush();
EXPECT_EQ("foobar", ss1->GetString().str());
EXPECT_EQ("foobar", ss2->GetString().str());
}
namespace {
struct FlushTestStream : public Stream {
unsigned m_flush_count = false;
void Flush() override {
++m_flush_count;
}
Add byte counting mechanism to LLDB's Stream class. Summary: This patch allows LLDB's Stream class to count the bytes it has written to so far. There are two major motivations for this patch: The first one is that this will allow us to get rid of all the handwritten byte counting code we have in LLDB so far. Examples for this are pretty much all functions in LLDB that take a Stream to write to and return a size_t, which usually represents the bytes written. By moving to this centralized byte counting mechanism, we hopefully can avoid some tricky errors that happen when some code forgets to count the written bytes while writing something to a stream. The second motivation is that this is needed for the migration away from LLDB's `Stream` and towards LLVM's `raw_ostream`. My current plan is to start offering a fake raw_ostream class that just forwards to a LLDB Stream. However, for this raw_ostream wrapper we need to fulfill the raw_ostream interface with LLDB's Stream, which currently lacks the ability to count the bytes written so far (which raw_ostream exposes by it's `tell()` method). By adding this functionality it is trivial to start rolling out our raw_ostream wrapper (and then eventually completely move to raw_ostream). Also, once this fake raw_ostream is available, we can start replacing our own code writing to LLDB's Stream by LLVM code writing to raw_ostream. The best example for this is the LEB128 encoding we currently ship, which can be replaced with by LLVM's version which accepts an raw_ostream. From the point of view of the pure source changes this test does, we essentially just renamed the Write implementation in Stream to `WriteImpl` while the `Write` method everyone is using to write its raw bytes is now just forwarding and counting the written bytes. Reviewers: labath, davide Reviewed By: labath Subscribers: JDevlieghere, lldb-commits Differential Revision: https://reviews.llvm.org/D50159 llvm-svn: 338733
2018-08-03 00:38:34 +08:00
size_t WriteImpl(const void *src, size_t src_len) override {
return src_len;
}
};
}
TEST(StreamTeeTest, Flush) {
// Check that Flush is distributed to all streams.
auto fs1 = new FlushTestStream();
auto fs2 = new FlushTestStream();
lldb::StreamSP s1(fs1);
lldb::StreamSP s2(fs2);
StreamTee tee(s1, s2);
tee << "foo";
tee.Flush();
ASSERT_EQ(2U, tee.GetNumStreams());
EXPECT_EQ(1U, fs1->m_flush_count);
EXPECT_EQ(1U, fs2->m_flush_count);
tee << "bar";
tee.Flush();
EXPECT_EQ(2U, fs1->m_flush_count);
EXPECT_EQ(2U, fs2->m_flush_count);
}
TEST(StreamTeeTest, AppendStream) {
// Append new streams to our StreamTee.
auto ss1 = new StreamString();
auto ss2 = new StreamString();
lldb::StreamSP s1(ss1);
lldb::StreamSP s2(ss2);
StreamTee tee;
ASSERT_EQ(0U, tee.GetNumStreams());
tee.AppendStream(s1);
ASSERT_EQ(1U, tee.GetNumStreams());
EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
tee.AppendStream(s2);
ASSERT_EQ(2U, tee.GetNumStreams());
EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
EXPECT_EQ(s2, tee.GetStreamAtIndex(1U));
}
TEST(StreamTeeTest, GetStreamAtIndexOutOfBounds) {
// The index we check for is not in the bounds of the StreamTee.
lldb::StreamSP s1(std::make_shared<StreamString>());
StreamTee tee(s1);
ASSERT_EQ(1U, tee.GetNumStreams());
EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1));
}
TEST(StreamTeeTest, GetStreamAtIndexOutOfBoundsEmpty) {
// Same as above, but with an empty StreamTee.
StreamTee tee;
ASSERT_EQ(0U, tee.GetNumStreams());
EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(0U));
EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U));
}
TEST(StreamTeeTest, SetStreamAtIndexOverwrite) {
// We overwrite an existing stream at a given index.
lldb::StreamSP s1(std::make_shared<StreamString>());
StreamTee tee(s1);
ASSERT_EQ(1U, tee.GetNumStreams());
EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U));
lldb::StreamSP s2(std::make_shared<StreamString>());
tee.SetStreamAtIndex(0U, s2);
EXPECT_EQ(1U, tee.GetNumStreams());
EXPECT_EQ(s2, tee.GetStreamAtIndex(0U));
EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1));
}
TEST(StreamTeeTest, SetStreamAtIndexOutOfBounds) {
// We place a new stream out of the bounds of the current StreamTee.
lldb::StreamSP s1(std::make_shared<StreamString>());
StreamTee tee(s1);
ASSERT_EQ(1U, tee.GetNumStreams());
EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U));
// Place a new stream out of bounds of the current array. The StreamTee should
// resize itself until it can contain this index.
lldb::StreamSP s2(std::make_shared<StreamString>());
tee.SetStreamAtIndex(4U, s2);
// Check that the vector has been resized.
EXPECT_EQ(5U, tee.GetNumStreams());
// Is our stream at the right place?
EXPECT_EQ(s2, tee.GetStreamAtIndex(4U));
// Existing stream should still be there.
EXPECT_EQ(s1, tee.GetStreamAtIndex(0U));
// Other elements are all invalid StreamSPs.
EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(1U));
EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(2U));
EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(3U));
EXPECT_EQ(lldb::StreamSP(), tee.GetStreamAtIndex(5U));
}