diff --git a/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm b/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm index 4aa073de93506..1aac3a88d7e71 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm @@ -25,6 +25,7 @@ #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/embedder/embedder_engine.h" #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h" +#include "flutter/testing/stream_capture.h" #include "flutter/testing/test_dart_native_resolver.h" #include "gtest/gtest.h" @@ -189,9 +190,7 @@ + (void)registerWithRegistrar:(id)registrar { CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { latch.Signal(); })); // Replace stdout stream buffer with our own. - std::stringstream buffer; - std::streambuf* old_buffer = std::cout.rdbuf(); - std::cout.rdbuf(buffer.rdbuf()); + StreamCapture stdout_capture(&std::cout); // Launch the test entrypoint. FlutterEngine* engine = GetFlutterEngine(); @@ -200,12 +199,10 @@ + (void)registerWithRegistrar:(id)registrar { latch.Wait(); - // Restore old stdout stream buffer. - std::cout.rdbuf(old_buffer); + stdout_capture.Stop(); // Verify hello world was written to stdout. - std::string logs = buffer.str(); - EXPECT_TRUE(logs.find("Hello logging") != std::string::npos); + EXPECT_TRUE(stdout_capture.GetOutput().find("Hello logging") != std::string::npos); } // TODO(cbracken): Needs deflaking. https://github.com/flutter/flutter/issues/124677 diff --git a/shell/platform/windows/flutter_windows_unittests.cc b/shell/platform/windows/flutter_windows_unittests.cc index 38d613301bc80..bab9d89b01523 100644 --- a/shell/platform/windows/flutter_windows_unittests.cc +++ b/shell/platform/windows/flutter_windows_unittests.cc @@ -15,6 +15,7 @@ #include "flutter/shell/platform/windows/testing/windows_test.h" #include "flutter/shell/platform/windows/testing/windows_test_config_builder.h" #include "flutter/shell/platform/windows/testing/windows_test_context.h" +#include "flutter/testing/stream_capture.h" #include "gtest/gtest.h" #include "third_party/tonic/converter/dart_converter.h" @@ -45,27 +46,20 @@ TEST_F(WindowsTest, LaunchMain) { // Verify there is no unexpected output from launching main. TEST_F(WindowsTest, LaunchMainHasNoOutput) { // Replace stdout & stderr stream buffers with our own. - std::stringstream cout_buffer; - std::stringstream cerr_buffer; - std::streambuf* old_cout_buffer = std::cout.rdbuf(); - std::streambuf* old_cerr_buffer = std::cerr.rdbuf(); - std::cout.rdbuf(cout_buffer.rdbuf()); - std::cerr.rdbuf(cerr_buffer.rdbuf()); + StreamCapture stdout_capture(&std::cout); + StreamCapture stderr_capture(&std::cerr); auto& context = GetContext(); WindowsConfigBuilder builder(context); ViewControllerPtr controller{builder.Run()}; ASSERT_NE(controller, nullptr); - // Restore original stdout & stderr stream buffer. - std::cout.rdbuf(old_cout_buffer); - std::cerr.rdbuf(old_cerr_buffer); + stdout_capture.Stop(); + stderr_capture.Stop(); // Verify stdout & stderr have no output. - std::string cout = cout_buffer.str(); - std::string cerr = cerr_buffer.str(); - EXPECT_TRUE(cout.empty()); - EXPECT_TRUE(cerr.empty()); + EXPECT_TRUE(stdout_capture.GetOutput().empty()); + EXPECT_TRUE(stderr_capture.GetOutput().empty()); } // Verify we can successfully launch a custom entry point. diff --git a/testing/BUILD.gn b/testing/BUILD.gn index 5a56313330d6a..cdc185aac29ac 100644 --- a/testing/BUILD.gn +++ b/testing/BUILD.gn @@ -25,6 +25,8 @@ source_set("testing_lib") { "mock_canvas.h", "post_task_sync.cc", "post_task_sync.h", + "stream_capture.cc", + "stream_capture.h", "test_args.cc", "test_args.h", "test_timeout_listener.cc", diff --git a/testing/stream_capture.cc b/testing/stream_capture.cc new file mode 100644 index 0000000000000..ed02282f4dc19 --- /dev/null +++ b/testing/stream_capture.cc @@ -0,0 +1,31 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/testing/stream_capture.h" + +namespace flutter { +namespace testing { + +StreamCapture::StreamCapture(std::ostream* ostream) + : ostream_(ostream), old_buffer_(ostream_->rdbuf()) { + ostream_->rdbuf(buffer_.rdbuf()); +} + +StreamCapture::~StreamCapture() { + Stop(); +} + +void StreamCapture::Stop() { + if (old_buffer_) { + ostream_->rdbuf(old_buffer_); + old_buffer_ = nullptr; + } +} + +std::string StreamCapture::GetOutput() const { + return buffer_.str(); +} + +} // namespace testing +} // namespace flutter diff --git a/testing/stream_capture.h b/testing/stream_capture.h new file mode 100644 index 0000000000000..d40a38045d255 --- /dev/null +++ b/testing/stream_capture.h @@ -0,0 +1,47 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_TESTING_STREAM_CAPTURE_H_ +#define FLUTTER_TESTING_STREAM_CAPTURE_H_ + +#include +#include +#include + +namespace flutter { +namespace testing { + +// Temporarily replaces the specified stream's output buffer to capture output. +// +// Example: +// StreamCapture captured_stdout(&std::cout); +// ... code that writest to std::cout ... +// std::string output = captured_stdout.GetCapturedOutput(); +class StreamCapture { + public: + // Begins capturing output to the specified stream. + StreamCapture(std::ostream* ostream); + + // Stops capturing output to the specified stream, and restores the original + // output buffer, if |Stop| has not already been called. + ~StreamCapture(); + + // Stops capturing output to the specified stream, and restores the original + // output buffer. + void Stop(); + + // Returns any output written to the captured stream between construction and + // the first call to |Stop|, if any, or now. + std::string GetOutput() const; + + private: + std::ostream* ostream_; + std::stringstream buffer_; + std::streambuf* old_buffer_; +}; + +} // namespace testing +} // namespace flutter + +#endif // FLUTTER_TESTING_STREAM_CAPTURE_H_