Flutter Engine
embedder_unittests_util.cc
Go to the documentation of this file.
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 #define FML_USED_ON_EMBEDDER
6 
7 #include "flutter/shell/platform/embedder/tests/embedder_unittests_util.h"
8 
9 namespace flutter {
10 namespace testing {
11 
12 sk_sp<SkSurface> CreateRenderSurface(const FlutterLayer& layer,
13  GrDirectContext* context) {
14  const auto image_info =
15  SkImageInfo::MakeN32Premul(layer.size.width, layer.size.height);
16  auto surface = context ? SkSurface::MakeRenderTarget(
17  context, // context
18  SkBudgeted::kNo, // budgeted
19  image_info, // image info
20  1, // sample count
21  kTopLeft_GrSurfaceOrigin, // surface origin
22  nullptr, // surface properties
23  false // mipmaps
24 
25  )
26  : SkSurface::MakeRaster(image_info);
27  FML_CHECK(surface != nullptr);
28  return surface;
29 }
30 
31 bool RasterImagesAreSame(sk_sp<SkImage> a, sk_sp<SkImage> b) {
32  FML_CHECK(!a->isTextureBacked());
33  FML_CHECK(!b->isTextureBacked());
34 
35  if (!a || !b) {
36  return false;
37  }
38 
39  SkPixmap pixmapA;
40  SkPixmap pixmapB;
41 
42  if (!a->peekPixels(&pixmapA)) {
43  FML_LOG(ERROR) << "Could not peek pixels of image A.";
44  return false;
45  }
46 
47  if (!b->peekPixels(&pixmapB)) {
48  FML_LOG(ERROR) << "Could not peek pixels of image B.";
49 
50  return false;
51  }
52 
53  const auto sizeA = pixmapA.rowBytes() * pixmapA.height();
54  const auto sizeB = pixmapB.rowBytes() * pixmapB.height();
55 
56  if (sizeA != sizeB) {
57  FML_LOG(ERROR) << "Pixmap sizes were inconsistent.";
58  return false;
59  }
60 
61  return ::memcmp(pixmapA.addr(), pixmapB.addr(), sizeA) == 0;
62 }
63 
64 bool WriteImageToDisk(const fml::UniqueFD& directory,
65  const std::string& name,
66  sk_sp<SkImage> image) {
67  if (!image) {
68  return false;
69  }
70 
71  auto data = image->encodeToData(SkEncodedImageFormat::kPNG, 100);
72 
73  if (!data) {
74  return false;
75  }
76 
77  fml::NonOwnedMapping mapping(static_cast<const uint8_t*>(data->data()),
78  data->size());
79  return WriteAtomically(directory, name.c_str(), mapping);
80 }
81 
82 bool ImageMatchesFixture(const std::string& fixture_file_name,
83  sk_sp<SkImage> scene_image) {
84  fml::FileMapping fixture_image_mapping(OpenFixture(fixture_file_name));
85 
86  FML_CHECK(fixture_image_mapping.GetSize() != 0u)
87  << "Could not find fixture: " << fixture_file_name;
88 
89  auto encoded_image = SkData::MakeWithoutCopy(
90  fixture_image_mapping.GetMapping(), fixture_image_mapping.GetSize());
91  auto fixture_image =
92  SkImage::MakeFromEncoded(std::move(encoded_image))->makeRasterImage();
93 
94  FML_CHECK(fixture_image) << "Could not create image from fixture: "
95  << fixture_file_name;
96 
97  auto scene_image_subset = scene_image->makeSubset(
98  SkIRect::MakeWH(fixture_image->width(), fixture_image->height()));
99 
100  FML_CHECK(scene_image_subset)
101  << "Could not create image subset for fixture comparison: "
102  << scene_image_subset;
103 
104  const auto images_are_same =
105  RasterImagesAreSame(scene_image_subset, fixture_image);
106 
107  // If the images are not the same, this predicate is going to indicate test
108  // failure. Dump both the actual image and the expectation to disk to the
109  // test author can figure out what went wrong.
110  if (!images_are_same) {
111  const auto fixtures_path = GetFixturesPath();
112 
113  const auto actual_file_name = "actual_" + fixture_file_name;
114  const auto expect_file_name = "expectation_" + fixture_file_name;
115 
116  auto fixtures_fd = OpenFixturesDirectory();
117 
118  FML_CHECK(
119  WriteImageToDisk(fixtures_fd, actual_file_name, scene_image_subset))
120  << "Could not write file to disk: " << actual_file_name;
121 
122  FML_CHECK(WriteImageToDisk(fixtures_fd, expect_file_name, fixture_image))
123  << "Could not write file to disk: " << expect_file_name;
124 
125  FML_LOG(ERROR) << "Image did not match expectation." << std::endl
126  << "Expected:"
127  << fml::paths::JoinPaths({fixtures_path, expect_file_name})
128  << std::endl
129  << "Got:"
130  << fml::paths::JoinPaths({fixtures_path, actual_file_name})
131  << std::endl;
132  }
133  return images_are_same;
134 }
135 
136 bool ImageMatchesFixture(const std::string& fixture_file_name,
137  std::future<sk_sp<SkImage>>& scene_image) {
138  return ImageMatchesFixture(fixture_file_name, scene_image.get());
139 }
140 
142  const FlutterPlatformViewMutation** mutations,
143  size_t count,
145  std::function<void(const FlutterPlatformViewMutation& mutation)> handler) {
146  if (mutations == nullptr) {
147  return;
148  }
149 
150  for (size_t i = 0; i < count; ++i) {
151  const FlutterPlatformViewMutation* mutation = mutations[i];
152  if (mutation->type != type) {
153  continue;
154  }
155 
156  handler(*mutation);
157  }
158 }
159 
161  const FlutterPlatformView* view,
163  std::function<void(const FlutterPlatformViewMutation& mutation)> handler) {
164  return FilterMutationsByType(view->mutations, view->mutations_count, type,
165  handler);
166 }
167 
169  const FlutterPlatformViewMutation** mutations,
170  size_t count) {
171  SkMatrix collected;
172 
175  [&](const auto& mutation) {
176  collected.preConcat(SkMatrixMake(mutation.transformation));
177  });
178 
179  return collected;
180 }
181 
184  view->mutations_count);
185 }
186 
187 } // namespace testing
188 } // namespace flutter
SkMatrix GetTotalMutationTransformationMatrix(const FlutterPlatformViewMutation **mutations, size_t count)
FlutterPlatformViewMutationType
Definition: embedder.h:790
void FilterMutationsByType(const FlutterPlatformViewMutation **mutations, size_t count, FlutterPlatformViewMutationType type, std::function< void(const FlutterPlatformViewMutation &mutation)> handler)
FlutterSize size
The size of the layer (in physical pixels).
Definition: embedder.h:902
sk_sp< SkSurface > CreateRenderSurface(const FlutterLayer &layer, GrDirectContext *context)
Dart_NativeFunction function
Definition: fuchsia.cc:51
#define FML_LOG(severity)
Definition: logging.h:65
SkMatrix SkMatrixMake(const FlutterTransformation &xformation)
fml::UniqueFD OpenFixturesDirectory()
Opens the fixtures directory for the unit-test harness.
Definition: testing.cc:16
std::string JoinPaths(std::initializer_list< std::string > components)
Definition: paths.cc:14
bool RasterImagesAreSame(sk_sp< SkImage > a, sk_sp< SkImage > b)
fml::UniqueFD OpenFixture(std::string fixture_name)
Opens a fixture of the given file name.
Definition: testing.cc:30
const char * GetFixturesPath()
Returns the directory containing the test fixture for the target if this target has fixtures configur...
size_t mutations_count
Definition: embedder.h:825
double width
Definition: embedder.h:311
const uint8_t * GetMapping() const override
const FlutterPlatformViewMutation ** mutations
Definition: embedder.h:838
size_t GetSize() const override
const char * name
Definition: fuchsia.cc:50
#define FML_CHECK(condition)
Definition: logging.h:68
double height
Definition: embedder.h:312
FlutterPlatformViewMutationType type
The type of the mutation described by the subsequent union.
Definition: embedder.h:807
bool WriteImageToDisk(const fml::UniqueFD &directory, const std::string &name, sk_sp< SkImage > image)
bool ImageMatchesFixture(const std::string &fixture_file_name, sk_sp< SkImage > scene_image)
bool WriteAtomically(const fml::UniqueFD &base_directory, const char *file_name, const Mapping &mapping)
Definition: file_posix.cc:188