Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d6d5695
Added golden image tests to impeller
gaaclarke Mar 16, 2023
b17819e
started writing a digest
gaaclarke Mar 20, 2023
345d019
added docstrings
gaaclarke Mar 20, 2023
93725ba
added harvester
gaaclarke Mar 20, 2023
aca9c66
updated readme
gaaclarke Mar 20, 2023
1ec9eb3
added logger wrapper
gaaclarke Mar 20, 2023
d079bd2
made the tests only run on mac
gaaclarke Mar 20, 2023
3141ca1
updated the run_tests.py script
gaaclarke Mar 22, 2023
f8c4431
added readme
gaaclarke Mar 22, 2023
0a6757f
made sure that the golden image tests are only compiled for mac
gaaclarke Mar 22, 2023
b881ff5
updated licenses
gaaclarke Mar 22, 2023
28ef8ff
lint fixes for run_tests.py
gaaclarke Mar 22, 2023
e9e796a
updated licenses again
gaaclarke Mar 22, 2023
9d902bb
more lints
gaaclarke Mar 22, 2023
e87078c
unused import
gaaclarke Mar 22, 2023
83c93fe
sorted imports
gaaclarke Mar 22, 2023
5735ac3
turned on the golden tests by default
gaaclarke Mar 22, 2023
1f863c9
fixed remote execution
gaaclarke Mar 22, 2023
3f00b5d
turned the tests off for the engine runs, going to specify it in the …
gaaclarke Mar 22, 2023
7d0058b
added goldctl dependency to "Mac host engine"
gaaclarke Mar 23, 2023
d0c5781
tried switching to engine_v2 to run the golden tests
gaaclarke Mar 23, 2023
386ddb4
tried adding the dependency to the drone
gaaclarke Mar 23, 2023
bfa2200
tried flipping the image in ciimage since it wasn't working when writ…
gaaclarke Mar 24, 2023
8267da7
switched to sending the filename to skia gold client, since the code …
gaaclarke Mar 24, 2023
79cc6fd
zach feedback 1
gaaclarke Mar 24, 2023
02b9f03
updated licenses golden
gaaclarke Mar 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,10 @@ targets:
properties:
release_build: "true"
config_name: mac_host_engine
dependencies: >-
[
{"dependency": "goldctl", "version": "git_revision:3a77d0b12c697a840ca0c7705208e8622dc94603"}
]
$flutter/osx_sdk : >-
{ "sdk_version": "14a5294e" }

Expand Down
4 changes: 2 additions & 2 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ group("unittests") {
}

if (is_mac) {
public_deps +=
[ "//flutter/shell/platform/darwin:flutter_channels_unittests" ]
public_deps += [
"//flutter/impeller/golden_tests:impeller_golden_tests",
"//flutter/shell/platform/darwin:flutter_channels_unittests",
"//flutter/third_party/spring_animation:spring_animation_unittests",
]
}
Expand Down
21 changes: 19 additions & 2 deletions ci/builders/mac_host_engine.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
"os=Mac-12",
"cpu=x86"
],
"dependencies": [
{"dependency": "goldctl", "version": "git_revision:3a77d0b12c697a840ca0c7705208e8622dc94603"}
],
"gclient_custom_vars": {
"download_android_deps": false
},
Expand All @@ -124,13 +127,27 @@
"ninja": {
"config": "host_release",
"targets": [
"flutter/shell/platform/darwin/macos:zip_macos_flutter_framework",
"flutter/build/archives:archive_gen_snapshot",
"flutter/build/archives:artifacts",
"flutter/impeller/golden_tests:impeller_golden_tests",
"flutter/shell/platform/darwin/macos:zip_macos_flutter_framework",
"flutter/tools/font-subset"
]
},
"tests": []
"tests": [
{
"language": "python3",
"name": "Impeller golden Tests for host_release",
"parameters": [
"--variant",
"host_release",
"--type",
"impeller-golden"
],
"script": "flutter/testing/run_tests.py",
"type": "local"
}
]
},
{
"archives": [
Expand Down
8 changes: 8 additions & 0 deletions ci/licenses_golden/excluded_files
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,14 @@
../../../flutter/impeller/geometry/README.md
../../../flutter/impeller/geometry/geometry_unittests.cc
../../../flutter/impeller/geometry/geometry_unittests.h
../../../flutter/impeller/golden_tests/README.md
../../../flutter/impeller/golden_tests_harvester/.dart_tool
../../../flutter/impeller/golden_tests_harvester/.gitignore
../../../flutter/impeller/golden_tests_harvester/README.md
../../../flutter/impeller/golden_tests_harvester/analysis_options.yaml
../../../flutter/impeller/golden_tests_harvester/pubspec.lock
../../../flutter/impeller/golden_tests_harvester/pubspec.yaml
../../../flutter/impeller/golden_tests_harvester/test
../../../flutter/impeller/image/README.md
../../../flutter/impeller/playground
../../../flutter/impeller/renderer/compute_subgroup_unittests.cc
Expand Down
26 changes: 26 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1315,6 +1315,19 @@ ORIGIN: ../../../flutter/impeller/geometry/type_traits.cc + ../../../flutter/LIC
ORIGIN: ../../../flutter/impeller/geometry/type_traits.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/vector.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/vector.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests/golden_digest.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests/golden_digest.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests/golden_tests.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests/main.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests/metal_screenshot.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests/metal_screenshot.mm + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests/metal_screenshoter.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests/metal_screenshoter.mm + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests/working_directory.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests/working_directory.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests_harvester/bin/golden_tests_harvester.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests_harvester/lib/golden_tests_harvester.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/golden_tests_harvester/lib/logger.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/image/backends/skia/compressed_image_skia.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/image/backends/skia/compressed_image_skia.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/image/compressed_image.cc + ../../../flutter/LICENSE
Expand Down Expand Up @@ -3853,6 +3866,19 @@ FILE: ../../../flutter/impeller/geometry/type_traits.cc
FILE: ../../../flutter/impeller/geometry/type_traits.h
FILE: ../../../flutter/impeller/geometry/vector.cc
FILE: ../../../flutter/impeller/geometry/vector.h
FILE: ../../../flutter/impeller/golden_tests/golden_digest.cc
FILE: ../../../flutter/impeller/golden_tests/golden_digest.h
FILE: ../../../flutter/impeller/golden_tests/golden_tests.cc
FILE: ../../../flutter/impeller/golden_tests/main.cc
FILE: ../../../flutter/impeller/golden_tests/metal_screenshot.h
FILE: ../../../flutter/impeller/golden_tests/metal_screenshot.mm
FILE: ../../../flutter/impeller/golden_tests/metal_screenshoter.h
FILE: ../../../flutter/impeller/golden_tests/metal_screenshoter.mm
FILE: ../../../flutter/impeller/golden_tests/working_directory.cc
FILE: ../../../flutter/impeller/golden_tests/working_directory.h
FILE: ../../../flutter/impeller/golden_tests_harvester/bin/golden_tests_harvester.dart
FILE: ../../../flutter/impeller/golden_tests_harvester/lib/golden_tests_harvester.dart
FILE: ../../../flutter/impeller/golden_tests_harvester/lib/logger.dart
FILE: ../../../flutter/impeller/image/backends/skia/compressed_image_skia.cc
FILE: ../../../flutter/impeller/image/backends/skia/compressed_image_skia.h
FILE: ../../../flutter/impeller/image/compressed_image.cc
Expand Down
39 changes: 39 additions & 0 deletions impeller/golden_tests/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 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("//flutter/common/config.gni")
import("//flutter/impeller/tools/impeller.gni")

if (is_mac) {
test_fixtures("impeller_golden_tests_fixtures") {
fixtures = []
}

impeller_component("impeller_golden_tests") {
target_type = "executable"

testonly = true

sources = [
"golden_digest.cc",
"golden_digest.h",
"golden_tests.cc",
"main.cc",
"metal_screenshot.h",
"metal_screenshot.mm",
"metal_screenshoter.h",
"metal_screenshoter.mm",
"working_directory.cc",
"working_directory.h",
]

deps = [
":impeller_golden_tests_fixtures",
"//flutter/impeller/aiks",
"//flutter/impeller/playground",
"//flutter/impeller/renderer/backend/metal:metal",
"//third_party/googletest:gtest",
]
}
}
20 changes: 20 additions & 0 deletions impeller/golden_tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Impeller Golden Tests

This is the executable that will generate the golden image results that can then
be sent to Skia Gold vial the
[golden_tests_harvester]("../golden_tests_harvester").

Running these tests should happen from
[//flutter/testing/run_tests.py](../../testing/run_tests.py). That will do all
the steps to generate the golden images and transmit them to Skia Gold. If you
run the tests locally it will not actually upload anything. That only happens if
the script is executed from LUCI.

Example invocation:

```sh
./run_tests.py --variant="host_debug_unopt_arm64" --type="impeller-golden"
```

Currently these tests are only supported on macOS and only test the Metal
backend to Impeller.
58 changes: 58 additions & 0 deletions impeller/golden_tests/golden_digest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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 "impeller/golden_tests/golden_digest.h"

#include <fstream>

namespace impeller {
namespace testing {

GoldenDigest* GoldenDigest::instance_ = nullptr;

GoldenDigest* GoldenDigest::Instance() {
if (!instance_) {
instance_ = new GoldenDigest();
}
return instance_;
}

GoldenDigest::GoldenDigest() {}

void GoldenDigest::AddImage(const std::string& test_name,
const std::string& filename,
int32_t width,
int32_t height) {
entries_.push_back({test_name, filename, width, height});
}

bool GoldenDigest::Write(WorkingDirectory* working_directory) {
std::ofstream fout;
fout.open(working_directory->GetFilenamePath("digest.json"));
if (!fout.good()) {
return false;
}

fout << "[" << std::endl;
bool is_first = true;
for (const auto& entry : entries_) {
if (!is_first) {
fout << "," << std::endl;
is_first = false;
}
fout << " { "
<< "\"testName\" : \"" << entry.test_name << "\", "
<< "\"filename\" : \"" << entry.filename << "\", "
<< "\"width\" : " << entry.width << ", "
<< "\"height\" : " << entry.height << " "
<< "}";
}
fout << std::endl << "]" << std::endl;

fout.close();
return true;
}

} // namespace testing
} // namespace impeller
45 changes: 45 additions & 0 deletions impeller/golden_tests/golden_digest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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.

#pragma once

#include <string>
#include <vector>

#include "flutter/fml/macros.h"
#include "flutter/impeller/golden_tests/working_directory.h"

namespace impeller {
namespace testing {

/// Manages a global variable for tracking instances of golden images.
class GoldenDigest {
public:
static GoldenDigest* Instance();

void AddImage(const std::string& test_name,
const std::string& filename,
int32_t width,
int32_t height);

/// Writes a "digest.json" file to `working_directory`.
///
/// Returns `true` on success.
bool Write(WorkingDirectory* working_directory);

private:
FML_DISALLOW_COPY_AND_ASSIGN(GoldenDigest);
GoldenDigest();
struct Entry {
std::string test_name;
std::string filename;
int32_t width;
int32_t height;
Comment on lines +37 to +38
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No action needed, but why isn't this just included in the file itself? Or is this for a human verifying to make sure something didn't go wrong if the file is suddenly smaller than expected or something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storing it in the image file would require a library to parse the image to get the width and height in the harvester. Since we already know it here, it was more convenient to report it. Our dart instances in the engine have a limited set of packages available so they might not even have the ability to easily parse image headers.

};

static GoldenDigest* instance_;
std::vector<Entry> entries_;
};
} // namespace testing
} // namespace impeller
79 changes: 79 additions & 0 deletions impeller/golden_tests/golden_tests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// 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 "gtest/gtest.h"

#include <sstream>

#include "impeller/aiks/canvas.h"
#include "impeller/entity/contents/conical_gradient_contents.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/golden_tests/golden_digest.h"
#include "impeller/golden_tests/metal_screenshot.h"
#include "impeller/golden_tests/metal_screenshoter.h"
#include "impeller/golden_tests/working_directory.h"

namespace impeller {
namespace testing {

namespace {
std::string GetTestName() {
std::string suite_name =
::testing::UnitTest::GetInstance()->current_test_suite()->name();
std::string test_name =
::testing::UnitTest::GetInstance()->current_test_info()->name();
std::stringstream ss;
ss << "impeller_" << suite_name << "_" << test_name;
return ss.str();
}

std::string GetGoldenFilename() {
return GetTestName() + ".png";
}

bool SaveScreenshot(std::unique_ptr<MetalScreenshot> screenshot) {
if (!screenshot || !screenshot->GetBytes()) {
return false;
}
std::string test_name = GetTestName();
std::string filename = GetGoldenFilename();
GoldenDigest::Instance()->AddImage(
test_name, filename, screenshot->GetWidth(), screenshot->GetHeight());
return screenshot->WriteToPNG(
WorkingDirectory::Instance()->GetFilenamePath(filename));
}
} // namespace

class GoldenTests : public ::testing::Test {
public:
GoldenTests() : screenshoter_(new MetalScreenshoter()) {}

MetalScreenshoter& Screenshoter() { return *screenshoter_; }

private:
std::unique_ptr<MetalScreenshoter> screenshoter_;
};

TEST_F(GoldenTests, ConicalGradient) {
Canvas canvas;
Paint paint;
paint.color_source_type = Paint::ColorSourceType::kConicalGradient;
paint.color_source = []() {
auto result = std::make_shared<ConicalGradientContents>();
result->SetCenterAndRadius(Point(125, 125), 125);
result->SetColors({Color(1.0, 0.0, 0.0, 1.0), Color(0.0, 0.0, 1.0, 1.0)});
result->SetStops({0, 1});
result->SetFocus(Point(180, 180), 0);
result->SetTileMode(Entity::TileMode::kClamp);
return result;
};
paint.stroke_width = 0.0;
paint.style = Paint::Style::kFill;
canvas.DrawRect(Rect(10, 10, 250, 250), paint);
Picture picture = canvas.EndRecordingAsPicture();
auto screenshot = Screenshoter().MakeScreenshot(std::move(picture));
ASSERT_TRUE(SaveScreenshot(std::move(screenshot)));
}
} // namespace testing
} // namespace impeller
Loading