blob: ac627b93e0511098cac384e4cb98d127708ab663 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_BASE_TEST_SKIA_GOLD_MATCHING_ALGORITHM_H_
#define UI_BASE_TEST_SKIA_GOLD_MATCHING_ALGORITHM_H_
#include <string>
namespace base {
class CommandLine;
}
namespace ui {
namespace test {
// Describes what algorithm to use to match golden images.
// Fuzzy and Sobel algorithms have adjustable parameters:
//
// Fuzzy has the max number of different pixels, the max per-channel delta sum
// (i.e. how much a pixel can differ by and still be considered the same), and
// how many border pixels to ignore. The number of ignored border pixels is
// mainly to make the Sobel filter work better, as if an edge goes all the way
// to the border of the image, the pixels along the border won't be blacked
// out due to the Sobel filter.
//
// Sobel has the parameters of fuzzy + the edge threshold, which determines how
// much of the image should be blacked out based on the generated Sobel filter.
//
// In general, it works like this:
// 1. Try an exact comparison check against all approved images for the test,
// returning success if a hash matches.
// 2. Get the most recent image for the trace (test + any reported JSON keys,
// e.g. OS/hardware information)
// 3. If the algorithm is Sobel, generate a Sobel filter and black out parts
// of the image based on the provided edge threshold.
// 4. Do a fuzzy comparison of the images.
//
// To determine the suitable parameter values using historical data for a test:
// https://cs.chromium.org/chromium/src/content/test/gpu/gold_inexact_matching/determine_gold_inexact_parameters.py
class SkiaGoldMatchingAlgorithm {
public:
SkiaGoldMatchingAlgorithm();
virtual ~SkiaGoldMatchingAlgorithm();
// Append the algorithm parameter to |cmd|.
virtual void AppendAlgorithmToCmdline(base::CommandLine& cmd) const;
// The algorithm name for commandline.
virtual std::string GetCommandLineSwitchName() const = 0;
};
class ExactSkiaGoldMatchingAlgorithm : public SkiaGoldMatchingAlgorithm {
public:
ExactSkiaGoldMatchingAlgorithm();
~ExactSkiaGoldMatchingAlgorithm() override;
void AppendAlgorithmToCmdline(base::CommandLine& cmd) const override;
protected:
std::string GetCommandLineSwitchName() const override;
};
class FuzzySkiaGoldMatchingAlgorithm : public SkiaGoldMatchingAlgorithm {
public:
FuzzySkiaGoldMatchingAlgorithm(int max_different_pixels,
int pixel_delta_threshold,
int ignored_border_thickness = 0);
~FuzzySkiaGoldMatchingAlgorithm() override;
void AppendAlgorithmToCmdline(base::CommandLine& cmd) const override;
protected:
std::string GetCommandLineSwitchName() const override;
private:
int max_different_pixels_{0};
int pixel_delta_threshold_{0};
int ignored_border_thickness_{0};
};
class SobelSkiaGoldMatchingAlgorithm : public FuzzySkiaGoldMatchingAlgorithm {
public:
SobelSkiaGoldMatchingAlgorithm(int max_different_pixels,
int pixel_delta_threshold,
int edge_threshold,
int ignored_border_thickness = 0);
~SobelSkiaGoldMatchingAlgorithm() override;
void AppendAlgorithmToCmdline(base::CommandLine& cmd) const override;
protected:
std::string GetCommandLineSwitchName() const override;
private:
int edge_threshold_{0};
};
// With this algorithm, an image is regarded to match a golden image when:
// 1. the image is an exact match, and
// 2. the set of golden images for the test must only contain a single image.
// This algorithm is used in Ash pixel testing to facilitate the gold image
// revision update.
// The main difference between this and `ExactSkiaGoldMatchingAlgorithm` is:
// * ExactSkiaGoldMatchingAlgorithm
// Your test can match multiple valid Gold images. For a test run, if the
// pixel output is one of the Gold images, we consider it's valid and test
// would pass.
// Any committers can approve a new Gold image. The new Gold image would be
// added to the valid Gold images set.
//
// * PositiveIfOnlyImageAlgorithm
// There is only 1 valid Gold image. No one can approve a new Gold image if
// there is already a Gold image. In order to updating the Gold image, you
// need to add a revision to the screenshot name, so it's treated as a new
// test from Gold's perspective.
//
// Say you have a button pixel test with screenshot name `pwd_manager_button1`.
// With ExactSkiaGoldMatchingAlgorithm:
// When a cl updates all button styles, the cl owner may approve all new
// styles via Skia Gold, gets a button style owner to approve it, and merges
// the change.
// In this case, the feature owner(pwd manager UI owner) would not get
// notified. If you as feature owner don't want this behavior, you can use
// PositiveIfOnlyImageAlgorithm:
// Your screenshot name would be `pwd_manager_button1.rev0`. When a cl updates
// all button styles, the cl owner need to edit your test case, change the
// screenshot name to `pwd_manager_button1.rev1`, and seek feature owner's
// approval for the test case change. In this way, feature owner would know
// the UI changes.
//
// This algorithm would increase the Gold image maintenance cost. Toolkit owners
// who regularly update styles might be hindered as they need to edit all test
// cases. So use your best judgement for the algorithm you choose.
class PositiveIfOnlyImageAlgorithm : public SkiaGoldMatchingAlgorithm {
public:
PositiveIfOnlyImageAlgorithm();
~PositiveIfOnlyImageAlgorithm() override;
private:
// SkiaGoldMatchingAlgorithm:
void AppendAlgorithmToCmdline(base::CommandLine& cmd) const override;
std::string GetCommandLineSwitchName() const override;
};
} // namespace test
} // namespace ui
#endif // UI_BASE_TEST_SKIA_GOLD_MATCHING_ALGORITHM_H_