Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 3a562d8

Browse files
committed
[testing] Extract StreamCapture test utility
Factors out an RAII-based class that can be used to capture std::cout, std::cerr, or technically any other std::ostream, though that's unlikely to be useful. This makes the logic reusable but more importantly, ensures the capture is cleaned up at the end of the test.
1 parent a1bad07 commit 3a562d8

File tree

5 files changed

+95
-20
lines changed

5 files changed

+95
-20
lines changed

shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "flutter/shell/platform/embedder/embedder.h"
2626
#include "flutter/shell/platform/embedder/embedder_engine.h"
2727
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
28+
#include "flutter/testing/stream_capture.h"
2829
#include "flutter/testing/test_dart_native_resolver.h"
2930
#include "gtest/gtest.h"
3031

@@ -189,9 +190,7 @@ + (void)registerWithRegistrar:(id<FlutterPluginRegistrar>)registrar {
189190
CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { latch.Signal(); }));
190191

191192
// Replace stdout stream buffer with our own.
192-
std::stringstream buffer;
193-
std::streambuf* old_buffer = std::cout.rdbuf();
194-
std::cout.rdbuf(buffer.rdbuf());
193+
StreamCapture stdout_capture(&std::cout);
195194

196195
// Launch the test entrypoint.
197196
FlutterEngine* engine = GetFlutterEngine();
@@ -200,12 +199,10 @@ + (void)registerWithRegistrar:(id<FlutterPluginRegistrar>)registrar {
200199

201200
latch.Wait();
202201

203-
// Restore old stdout stream buffer.
204-
std::cout.rdbuf(old_buffer);
202+
stdout_capture.Stop();
205203

206204
// Verify hello world was written to stdout.
207-
std::string logs = buffer.str();
208-
EXPECT_TRUE(logs.find("Hello logging") != std::string::npos);
205+
EXPECT_TRUE(stdout_capture.GetOutput().find("Hello logging") != std::string::npos);
209206
}
210207

211208
// TODO(cbracken): Needs deflaking. https://github.com/flutter/flutter/issues/124677

shell/platform/windows/flutter_windows_unittests.cc

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "flutter/shell/platform/windows/testing/windows_test.h"
1616
#include "flutter/shell/platform/windows/testing/windows_test_config_builder.h"
1717
#include "flutter/shell/platform/windows/testing/windows_test_context.h"
18+
#include "flutter/testing/stream_capture.h"
1819
#include "gtest/gtest.h"
1920
#include "third_party/tonic/converter/dart_converter.h"
2021

@@ -45,27 +46,20 @@ TEST_F(WindowsTest, LaunchMain) {
4546
// Verify there is no unexpected output from launching main.
4647
TEST_F(WindowsTest, LaunchMainHasNoOutput) {
4748
// Replace stdout & stderr stream buffers with our own.
48-
std::stringstream cout_buffer;
49-
std::stringstream cerr_buffer;
50-
std::streambuf* old_cout_buffer = std::cout.rdbuf();
51-
std::streambuf* old_cerr_buffer = std::cerr.rdbuf();
52-
std::cout.rdbuf(cout_buffer.rdbuf());
53-
std::cerr.rdbuf(cerr_buffer.rdbuf());
49+
StreamCapture stdout_capture(std::cout&);
50+
StreamCapture stderr_capture(std::cerr&);
5451

5552
auto& context = GetContext();
5653
WindowsConfigBuilder builder(context);
5754
ViewControllerPtr controller{builder.Run()};
5855
ASSERT_NE(controller, nullptr);
5956

60-
// Restore original stdout & stderr stream buffer.
61-
std::cout.rdbuf(old_cout_buffer);
62-
std::cerr.rdbuf(old_cerr_buffer);
57+
stdout_capture.Stop();
58+
stderr_capture.Stop();
6359

6460
// Verify stdout & stderr have no output.
65-
std::string cout = cout_buffer.str();
66-
std::string cerr = cerr_buffer.str();
67-
EXPECT_TRUE(cout.empty());
68-
EXPECT_TRUE(cerr.empty());
61+
EXPECT_TRUE(stdout_capture.GetOutput().empty());
62+
EXPECT_TRUE(stderr_capture.GetOutput().empty());
6963
}
7064

7165
// Verify we can successfully launch a custom entry point.

testing/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ source_set("testing_lib") {
2525
"mock_canvas.h",
2626
"post_task_sync.cc",
2727
"post_task_sync.h",
28+
"stream_capture.cc",
29+
"stream_capture.h",
2830
"test_args.cc",
2931
"test_args.h",
3032
"test_timeout_listener.cc",

testing/stream_capture.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/testing/stream_capture.h"
6+
7+
#include "flutter/fml/logging.h"
8+
9+
namespace flutter {
10+
namespace testing {
11+
12+
StreamCapture::StreamCapture(std::ostream* ostream) {
13+
FML_DCHECK(ostream != nullptr);
14+
ostream_ = ostream;
15+
old_buffer_ = ostream_->rdbuf();
16+
ostream_->rdbuf(buffer_.rdbuf());
17+
}
18+
19+
StreamCapture::~StreamCapture() {
20+
Stop();
21+
}
22+
23+
void StreamCapture::Stop() {
24+
if (old_buffer_) {
25+
ostream_->rdbuf(old_buffer_);
26+
old_buffer_ = nullptr;
27+
}
28+
}
29+
30+
std::string StreamCapture::GetOutput() const {
31+
return buffer_.str();
32+
}
33+
34+
} // namespace testing
35+
} // namespace flutter

testing/stream_capture.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_TESTING_STREAM_CAPTURE_H_
6+
#define FLUTTER_TESTING_STREAM_CAPTURE_H_
7+
8+
#include <ostream>
9+
#include <sstream>
10+
#include <string>
11+
12+
namespace flutter {
13+
namespace testing {
14+
15+
// Temporarily replaces the specified stream's output buffer to capture output.
16+
//
17+
// Example:
18+
// StreamCapture captured_stdout(&std::cout);
19+
// ... code that writest to std::cout ...
20+
// std::string output = captured_stdout.GetCapturedOutput();
21+
class StreamCapture {
22+
public:
23+
// Begins capturing output to the specified stream.
24+
StreamCapture(std::ostream* ostream);
25+
26+
// Stops capturing output to the specified stream, and restores the original
27+
// output buffer, if |Stop| has not already been called.
28+
~StreamCapture();
29+
30+
// Stops capturing output to the specified stream, and restores the original
31+
// output buffer.
32+
void Stop();
33+
34+
// Returns any output written to the captured stream between construction and
35+
// the first call to |Stop|, if any, or now.
36+
std::string GetOutput() const;
37+
38+
private:
39+
std::ostream* ostream_;
40+
std::stringstream buffer_;
41+
std::streambuf* old_buffer_;
42+
};
43+
44+
} // namespace testing
45+
} // namespace flutter
46+
47+
#endif // FLUTTER_TESTING_STREAM_CAPTURE_H_

0 commit comments

Comments
 (0)