From ea35899927bafce2adc846f44343db09f570b4ae Mon Sep 17 00:00:00 2001 From: Dan Field Date: Wed, 21 Apr 2021 13:04:01 -0700 Subject: [PATCH] Provide a stub platform view embedder for tester to avoid emitting errors (flutter/engine#25661) --- .../flutter/lib/ui/painting/image_decoder.cc | 6 ++-- .../lib/ui/painting/image_descriptor.cc | 6 ++-- engine/src/flutter/shell/testing/BUILD.gn | 1 + .../src/flutter/shell/testing/tester_main.cc | 34 +++++++++++++++++++ .../testing/dart/platform_view_test.dart | 19 +++++++++++ engine/src/flutter/testing/run_tests.py | 25 ++++++++++---- 6 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 engine/src/flutter/testing/dart/platform_view_test.dart diff --git a/engine/src/flutter/lib/ui/painting/image_decoder.cc b/engine/src/flutter/lib/ui/painting/image_decoder.cc index 3d497f9aea8..d9566346c8d 100644 --- a/engine/src/flutter/lib/ui/painting/image_decoder.cc +++ b/engine/src/flutter/lib/ui/painting/image_decoder.cc @@ -286,7 +286,7 @@ void ImageDecoder::Decode(fml::RefPtr descriptor_ref_ptr, flow); if (!decompressed) { - FML_LOG(ERROR) << "Could not decompress image."; + FML_DLOG(ERROR) << "Could not decompress image."; result({}, std::move(flow)); return; } @@ -298,7 +298,7 @@ void ImageDecoder::Decode(fml::RefPtr descriptor_ref_ptr, flow = std::move(flow)]() mutable { if (!io_manager) { - FML_LOG(ERROR) << "Could not acquire IO manager."; + FML_DLOG(ERROR) << "Could not acquire IO manager."; result({}, std::move(flow)); return; } @@ -316,7 +316,7 @@ void ImageDecoder::Decode(fml::RefPtr descriptor_ref_ptr, UploadRasterImage(std::move(decompressed), io_manager, flow); if (!uploaded.get()) { - FML_LOG(ERROR) << "Could not upload image to the GPU."; + FML_DLOG(ERROR) << "Could not upload image to the GPU."; result({}, std::move(flow)); return; } diff --git a/engine/src/flutter/lib/ui/painting/image_descriptor.cc b/engine/src/flutter/lib/ui/painting/image_descriptor.cc index 76cd577c13c..698e7cc21a7 100644 --- a/engine/src/flutter/lib/ui/painting/image_descriptor.cc +++ b/engine/src/flutter/lib/ui/painting/image_descriptor.cc @@ -171,14 +171,14 @@ void ImageDescriptor::instantiateCodec(Dart_Handle codec_handle, sk_sp ImageDescriptor::image() const { SkBitmap bitmap; if (!bitmap.tryAllocPixels(image_info_)) { - FML_LOG(ERROR) << "Failed to allocate memory for bitmap of size " - << image_info_.computeMinByteSize() << "B"; + FML_DLOG(ERROR) << "Failed to allocate memory for bitmap of size " + << image_info_.computeMinByteSize() << "B"; return nullptr; } const auto& pixmap = bitmap.pixmap(); if (!get_pixels(pixmap)) { - FML_LOG(ERROR) << "Failed to get pixels for image."; + FML_DLOG(ERROR) << "Failed to get pixels for image."; return nullptr; } bitmap.setImmutable(); diff --git a/engine/src/flutter/shell/testing/BUILD.gn b/engine/src/flutter/shell/testing/BUILD.gn index 678f6207c88..247b168bae9 100644 --- a/engine/src/flutter/shell/testing/BUILD.gn +++ b/engine/src/flutter/shell/testing/BUILD.gn @@ -25,6 +25,7 @@ executable("testing") { deps = [ "//flutter/assets", "//flutter/common", + "//flutter/flow", "//flutter/fml", "//flutter/lib/snapshot", "//flutter/shell/common", diff --git a/engine/src/flutter/shell/testing/tester_main.cc b/engine/src/flutter/shell/testing/tester_main.cc index cbdaabfe1e8..8b06e06641f 100644 --- a/engine/src/flutter/shell/testing/tester_main.cc +++ b/engine/src/flutter/shell/testing/tester_main.cc @@ -10,6 +10,7 @@ #include "flutter/assets/asset_manager.h" #include "flutter/assets/directory_asset_bundle.h" +#include "flutter/flow/embedded_views.h" #include "flutter/fml/build_config.h" #include "flutter/fml/file.h" #include "flutter/fml/make_copyable.h" @@ -32,6 +33,32 @@ namespace flutter { +class TesterExternalViewEmbedder : public ExternalViewEmbedder { + // |ExternalViewEmbedder| + SkCanvas* GetRootCanvas() override { return nullptr; } + + // |ExternalViewEmbedder| + void CancelFrame() override {} + + // |ExternalViewEmbedder| + void BeginFrame( + SkISize frame_size, + GrDirectContext* context, + double device_pixel_ratio, + fml::RefPtr raster_thread_merger) override {} + + // |ExternalViewEmbedder| + void PrerollCompositeEmbeddedView( + int view_id, + std::unique_ptr params) override {} + + // |ExternalViewEmbedder| + std::vector GetCurrentCanvases() override { return {}; } + + // |ExternalViewEmbedder| + SkCanvas* CompositeEmbeddedView(int view_id) override { return nullptr; } +}; + class TesterPlatformView : public PlatformView, public GPUSurfaceSoftwareDelegate { public: @@ -73,8 +100,15 @@ class TesterPlatformView : public PlatformView, return true; } + // |PlatformView| + std::shared_ptr CreateExternalViewEmbedder() override { + return external_view_embedder_; + } + private: sk_sp sk_surface_ = nullptr; + std::shared_ptr external_view_embedder_ = + std::make_shared(); }; // Checks whether the engine's main Dart isolate has no pending work. If so, diff --git a/engine/src/flutter/testing/dart/platform_view_test.dart b/engine/src/flutter/testing/dart/platform_view_test.dart new file mode 100644 index 00000000000..9d363513a09 --- /dev/null +++ b/engine/src/flutter/testing/dart/platform_view_test.dart @@ -0,0 +1,19 @@ +// 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. + +import 'dart:ui'; + +import 'package:test/test.dart'; + +void main() { + test('PlatformView layers do not emit errors from tester', () async { + final SceneBuilder builder = SceneBuilder(); + builder.addPlatformView(1); + final Scene scene = builder.build(); + + window.render(scene); + scene.dispose(); + // Test harness asserts that this does not emit an error from the shell logs. + }); +} diff --git a/engine/src/flutter/testing/run_tests.py b/engine/src/flutter/testing/run_tests.py index 4a21171e2da..cf095400de4 100755 --- a/engine/src/flutter/testing/run_tests.py +++ b/engine/src/flutter/testing/run_tests.py @@ -31,21 +31,31 @@ def PrintDivider(char='='): print(''.join([char for _ in xrange(80)])) print '\n' -def RunCmd(cmd, **kwargs): +def RunCmd(cmd, forbidden_output=[], **kwargs): command_string = ' '.join(cmd) PrintDivider('>') print 'Running command "%s"' % command_string start_time = time.time() - process = subprocess.Popen(cmd, stdout=sys.stdout, stderr=sys.stderr, **kwargs) - process.communicate() + stdout_pipe = sys.stdout if not forbidden_output else subprocess.PIPE + stderr_pipe = sys.stderr if not forbidden_output else subprocess.PIPE + process = subprocess.Popen(cmd, stdout=stdout_pipe, stderr=stderr_pipe, **kwargs) + stdout, stderr = process.communicate() end_time = time.time() if process.returncode != 0: PrintDivider('!') raise Exception('Command "%s" exited with code %d' % (command_string, process.returncode)) + if stdout or stderr: + print(stdout) + print(stderr) + + for forbidden_string in forbidden_output: + if (stdout and forbidden_string in stdout) or (stderr and forbidden_string in stderr): + raise Exception('command "%s" contained forbidden string %s' % (command_string, forbidden_string)) + PrintDivider('<') print 'Command run successfully in %.2f seconds: %s' % (end_time - start_time, command_string) @@ -81,7 +91,7 @@ def FindExecutablePath(path): raise Exception('Executable %s does not exist!' % path) -def RunEngineExecutable(build_dir, executable_name, filter, flags=[], cwd=buildroot_dir): +def RunEngineExecutable(build_dir, executable_name, filter, flags=[], cwd=buildroot_dir, forbidden_output=[]): if filter is not None and executable_name not in filter: print('Skipping %s due to filter.' % executable_name) return @@ -91,7 +101,7 @@ def RunEngineExecutable(build_dir, executable_name, filter, flags=[], cwd=buildr print('Running %s in %s' % (executable_name, cwd)) test_command = [ executable ] + flags print(' '.join(test_command)) - RunCmd(test_command, cwd=cwd) + RunCmd(test_command, cwd=cwd, forbidden_output=forbidden_output) def RunCCTests(build_dir, filter): @@ -247,7 +257,8 @@ def RunDartTest(build_dir, dart_file, verbose_dart_snapshot, multithreaded, enab threading = 'single-threaded' print("Running test '%s' using 'flutter_tester' (%s)" % (kernel_file_name, threading)) - RunEngineExecutable(build_dir, 'flutter_tester', None, command_args) + forbidden_output = [] if 'unopt' in build_dir else ['[ERROR'] + RunEngineExecutable(build_dir, 'flutter_tester', None, command_args, forbidden_output=forbidden_output) def RunPubGet(build_dir, directory): print("Running 'pub get' in the tests directory %s" % dart_tests_dir) @@ -263,7 +274,7 @@ def EnsureDebugUnoptSkyPackagesAreBuilt(): variant_out_dir = os.path.join(out_dir, 'host_debug_unopt') ninja_command = [ - 'autoninja', + 'ninja', '-C', variant_out_dir, 'flutter/sky/packages'