brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.7 KiB · 446e64a Raw
224 lines · cpp
1//===- raw_ostream_proxy_test.cpp - Tests for raw ostream proxies ---------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/SmallString.h"10#include "llvm/Support/WithColor.h"11#include "llvm/Support/raw_ostream.h"12#include "llvm/Support/raw_ostream_proxy.h"13#include "gtest/gtest.h"14 15using namespace llvm;16 17namespace {18 19/// Naive version of raw_svector_ostream that is buffered (by default) and20/// doesn't support pwrite.21class BufferedNoPwriteSmallVectorStream : public raw_ostream {22public:23  // Choose a strange buffer size to ensure it doesn't collide with the default24  // on \a raw_ostream.25  static constexpr size_t PreferredBufferSize = 63;26 27  size_t preferred_buffer_size() const override { return PreferredBufferSize; }28  uint64_t current_pos() const override { return Vector.size(); }29  void write_impl(const char *Ptr, size_t Size) override {30    Vector.append(Ptr, Ptr + Size);31  }32 33  bool is_displayed() const override { return IsDisplayed; }34 35  explicit BufferedNoPwriteSmallVectorStream(SmallVectorImpl<char> &Vector)36      : Vector(Vector) {}37  ~BufferedNoPwriteSmallVectorStream() override { flush(); }38 39  SmallVectorImpl<char> &Vector;40  bool IsDisplayed = false;41};42 43TEST(raw_ostream_proxyTest, write) {44  // Besides confirming that "write" works, this test confirms that the proxy45  // takes on the buffer from the stream it's proxying, such that writes to the46  // proxy are flushed to the underlying stream as if no proxy were present.47  SmallString<128> Dest;48  {49    // Confirm that BufferedNoPwriteSmallVectorStream is buffered by default,50    // and that setting up a proxy effectively transfers a buffer of the same51    // size to the proxy.52    BufferedNoPwriteSmallVectorStream DestOS(Dest);53    EXPECT_EQ(BufferedNoPwriteSmallVectorStream::PreferredBufferSize,54              DestOS.GetBufferSize());55    raw_ostream_proxy ProxyOS(DestOS);56    EXPECT_EQ(0u, DestOS.GetBufferSize());57    EXPECT_EQ(BufferedNoPwriteSmallVectorStream::PreferredBufferSize,58              ProxyOS.GetBufferSize());59 60    // Flushing should send through to Dest.61    ProxyOS << "abcd";62    EXPECT_EQ("", Dest);63    ProxyOS.flush();64    EXPECT_EQ("abcd", Dest);65 66    // Buffer should still work.67    ProxyOS << "e";68    EXPECT_EQ("abcd", Dest);69  }70 71  // Destructing ProxyOS should flush (and not crash).72  EXPECT_EQ("abcde", Dest);73 74  {75    // Set up another stream, this time unbuffered.76    BufferedNoPwriteSmallVectorStream DestOS(Dest);77    DestOS.SetUnbuffered();78    EXPECT_EQ(0u, DestOS.GetBufferSize());79    raw_ostream_proxy ProxyOS(DestOS);80    EXPECT_EQ(0u, DestOS.GetBufferSize());81    EXPECT_EQ(0u, ProxyOS.GetBufferSize());82 83    // Flushing should not be required.84    ProxyOS << "f";85    EXPECT_EQ("abcdef", Dest);86  }87  EXPECT_EQ("abcdef", Dest);88}89 90TEST(raw_ostream_proxyTest, pwrite) {91  // This test confirms that the proxy takes on the buffer from the stream it's92  // proxying, such that writes to the proxy are flushed to the underlying93  // stream as if no proxy were present.94  SmallString<128> Dest;95  raw_svector_ostream DestOS(Dest);96  raw_pwrite_stream_proxy ProxyOS(DestOS);97  EXPECT_EQ(0u, ProxyOS.GetBufferSize());98 99  // Get some initial data.100  ProxyOS << "abcd";101  EXPECT_EQ("abcd", Dest);102 103  // Confirm that pwrite works.104  ProxyOS.pwrite("BC", 2, 1);105  EXPECT_EQ("aBCd", Dest);106}107 108TEST(raw_ostream_proxyTest, pwriteWithBuffer) {109  // This test confirms that when a buffer is configured, pwrite still works.110  SmallString<128> Dest;111  raw_svector_ostream DestOS(Dest);112  DestOS.SetBufferSize(256);113  EXPECT_EQ(256u, DestOS.GetBufferSize());114 115  // Confirm that the proxy steals the buffer.116  raw_pwrite_stream_proxy ProxyOS(DestOS);117  EXPECT_EQ(0u, DestOS.GetBufferSize());118  EXPECT_EQ(256u, ProxyOS.GetBufferSize());119 120  // Check that the buffer is working.121  ProxyOS << "abcd";122  EXPECT_EQ("", Dest);123 124  // Confirm that pwrite flushes.125  ProxyOS.pwrite("BC", 2, 1);126  EXPECT_EQ("aBCd", Dest);127}128 129class ProxyWithReset : public raw_ostream_proxy_adaptor<> {130public:131  ProxyWithReset(raw_ostream &OS) : raw_ostream_proxy_adaptor<>(OS) {}132 133  // Allow this to be called outside the class.134  using raw_ostream_proxy_adaptor<>::hasProxiedOS;135  using raw_ostream_proxy_adaptor<>::getProxiedOS;136  using raw_ostream_proxy_adaptor<>::resetProxiedOS;137};138 139TEST(raw_ostream_proxyTest, resetProxiedOS) {140  // Confirm that base classes can drop the proxied OS before destruction and141  // get consistent crashes.142  SmallString<128> Dest;143  BufferedNoPwriteSmallVectorStream DestOS(Dest);144  ProxyWithReset ProxyOS(DestOS);145  EXPECT_TRUE(ProxyOS.hasProxiedOS());146  EXPECT_EQ(&DestOS, &ProxyOS.getProxiedOS());147 148  // Write some data.149  ProxyOS << "abcd";150  EXPECT_EQ("", Dest);151 152  // Reset the underlying stream.153  ProxyOS.resetProxiedOS();154  EXPECT_EQ("abcd", Dest);155  EXPECT_EQ(0u, ProxyOS.GetBufferSize());156  EXPECT_FALSE(ProxyOS.hasProxiedOS());157 158#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)159  EXPECT_DEATH(ProxyOS << "e", "use after reset");160  EXPECT_DEATH(ProxyOS.getProxiedOS(), "use after reset");161#endif162}163 164TEST(raw_ostream_proxyTest, ColorMode) {165  {166    SmallString<128> Dest;167    BufferedNoPwriteSmallVectorStream DestOS(Dest);168    DestOS.IsDisplayed = true;169    raw_ostream_proxy ProxyOS(DestOS);170    ProxyOS.enable_colors(true);171 172    WithColor(ProxyOS, raw_ostream::Colors::RED, /*Bold=*/true, /*BG=*/false,173              ColorMode::Disable)174        << "test";175    EXPECT_EQ("", Dest);176    ProxyOS.flush();177    EXPECT_EQ("test", Dest);178  }179 180  {181    SmallString<128> Dest;182    BufferedNoPwriteSmallVectorStream DestOS(Dest);183    raw_ostream_proxy ProxyOS(DestOS);184 185    WithColor(ProxyOS, raw_ostream::Colors::RED, /*Bold=*/true, /*BG=*/false,186              ColorMode::Auto)187        << "test";188    EXPECT_EQ("", Dest);189    ProxyOS.flush();190    EXPECT_EQ("test", Dest);191  }192 193#ifdef LLVM_ON_UNIX194  {195    SmallString<128> Dest;196    BufferedNoPwriteSmallVectorStream DestOS(Dest);197    raw_ostream_proxy ProxyOS(DestOS);198    ProxyOS.enable_colors(true);199 200    WithColor(ProxyOS, raw_ostream::Colors::RED, /*Bold=*/true, /*BG=*/false,201              ColorMode::Enable)202        << "test";203    EXPECT_EQ("", Dest);204    ProxyOS.flush();205    EXPECT_EQ("\x1B[0;1;31mtest\x1B[0m", Dest);206  }207 208  {209    SmallString<128> Dest;210    BufferedNoPwriteSmallVectorStream DestOS(Dest);211    DestOS.IsDisplayed = true;212    raw_ostream_proxy ProxyOS(DestOS);213    ProxyOS.enable_colors(true);214 215    WithColor(ProxyOS, HighlightColor::Error, ColorMode::Auto) << "test";216    EXPECT_EQ("", Dest);217    ProxyOS.flush();218    EXPECT_EQ("\x1B[0;1;31mtest\x1B[0m", Dest);219  }220#endif221}222 223} // end namespace224