1 /*
2  * Copyright 2020 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef gmverifier_DEFINED
9 #define gmverifier_DEFINED
10 
11 #include "include/core/SkColor.h"
12 #include "include/core/SkRect.h"
13 #include "include/core/SkString.h"
14 
15 #include <vector>
16 
17 class SkBitmap;
18 
19 namespace skiagm {
20 
21 class GM;
22 
23 namespace verifiers {
24 
25 /** Result type for GM verifiers. */
26 class VerifierResult {
27 public:
28     VerifierResult();
29 
30     /** Returns true if the result is ok (non-error). */
31     bool ok() const;
32 
33     /** Returns reference to any message associated with the result. */
34     const SkString& message() const;
35 
36     /** Constructs an "ok" (non-error) result. */
37     static VerifierResult Ok();
38 
39     /** Constructs a "fail" (error) result with a specific message. */
40     static VerifierResult Fail(const SkString& msg);
41 
42 private:
43     /** Underlying error code. */
44     enum class Code {
45         kOk, kFail
46     };
47 
48     /** Result code */
49     Code fCode;
50 
51     /** Result message (may be empty). */
52     SkString fMessage;
53 
54     /** Private constructor for a result with a specific code and message. */
55     VerifierResult(Code code, const SkString& msg);
56 };
57 
58 /**
59  * Abstract base class for GM verifiers. A verifier checks the rendered output image of a GM.
60  *
61  * Different verifiers perform different types of transforms and checks. Verifiers may check the
62  * output of a GM against a given "golden" image which represents the correct output, or just
63  * check the output image of the GM by itself.
64  *
65  * Most verifiers have configurable fuzziness in the comparisons performed against the golden image.
66  *
67  * Subclasses should inherit from one of StandaloneVerifier or GoldImageVerifier instead of
68  * directly from this base class.
69  */
70 class GMVerifier {
71 public:
72     GMVerifier() = delete;
73 
74     virtual ~GMVerifier();
75 
76     /** Returns the human-friendly name of the verifier. */
77     virtual SkString name() const = 0;
78 
79     /** Returns true if this verifier needs the gold image as input. */
80     bool needsGoldImage() const;
81 
82     /**
83      * Runs the verifier. This method should be used if the verifier needs the gold image as input.
84      *
85      * @param gold Bitmap containing the "correct" image.
86      * @param actual Bitmap containing rendered output of a GM.
87      * @return Ok if the verification passed, or an error if not.
88      */
89     VerifierResult verify(const SkBitmap& gold, const SkBitmap& actual);
90 
91     /**
92      * Runs the verifier.
93      *
94      * @param actual Bitmap containing rendered output of a GM.
95      * @return Ok if the verification passed, or an error if not.
96      */
97     VerifierResult verify(const SkBitmap& actual);
98 
99     /** Renders the GM using the "golden" configuration. This is common across all GMs/verifiers. */
100     static SkBitmap RenderGoldBmp(skiagm::GM* gm, const SkColorInfo& colorInfo);
101 
102     /**
103      * Gets the color information that all verifier inputs should be transformed into.
104      *
105      * The primary reason for having a single shared colorspace/color type is making per-pixel
106      * comparisons easier. Both the image under test and gold image are transformed into a shared
107      * colorspace which allows for getting per-pixel colors in SkColor4f.
108      */
109     static SkColorInfo VerifierColorInfo();
110 
111 protected:
112     /** The type of input required for the verifier. */
113     enum class InputType {
114         kGoldImageRequired, kStandalone
115     };
116 
117     /** Set depending if the verifier needs a golden image as an input. */
118     InputType fInputType;
119 
120     /** Constructor. */
121     GMVerifier(InputType inputType);
122 
123     /** Implementation of the verification. */
124     virtual VerifierResult verifyWithGold(
125         const SkIRect& region, const SkBitmap& gold, const SkBitmap& actual) = 0;
126 
127     /** Implementation of the verification. */
128     virtual VerifierResult verify(const SkIRect& region, const SkBitmap& actual) = 0;
129 
130     /** Returns an error result formatted appropriately. */
131     VerifierResult makeError(const SkString& msg) const;
132 };
133 
134 /**
135  * A verifier that operates standalone on the given input image (no comparison against a golden
136  * image).
137  */
138 class StandaloneVerifier : public GMVerifier {
139 public:
StandaloneVerifier()140     StandaloneVerifier() : GMVerifier(InputType::kStandalone) {}
141 
142 protected:
verifyWithGold(const SkIRect &,const SkBitmap &,const SkBitmap &)143     VerifierResult verifyWithGold(const SkIRect&, const SkBitmap&, const SkBitmap&) final {
144         return makeError(SkString("Verifier does not accept gold image input"));
145     }
146 };
147 
148 /**
149  * A verifier that operates compares input image against a golden image.
150  */
151 class GoldImageVerifier : public GMVerifier {
152 public:
GoldImageVerifier()153     GoldImageVerifier() : GMVerifier(InputType::kGoldImageRequired) {}
154 
155 protected:
verify(const SkIRect &,const SkBitmap &)156     VerifierResult verify(const SkIRect&, const SkBitmap&) final {
157         return makeError(SkString("Verifier does not accept standalone input"));
158     }
159 };
160 
161 /** A list of GM verifiers. */
162 class VerifierList {
163 public:
164     /** Constructs a VerifierList with the given gm instance. */
165     explicit VerifierList(GM* gm);
166 
167     /** Adds a verifier to the list of verifiers. */
168     void add(std::unique_ptr<GMVerifier> verifier);
169 
170     /**
171      * Runs all verifiers against the given input. If any verifiers fail, returns the first error.
172      * Else, returns ok. This version can be used if no verifiers in the list require the gold
173      * image as input.
174      */
175     VerifierResult verifyAll(const SkColorInfo& colorInfo, const SkBitmap& actual);
176 
177 private:
178     /** The parent GM instance of this VerifierList. */
179     GM* fGM;
180 
181     /** The list of verifiers. */
182     std::vector<std::unique_ptr<GMVerifier>> fVerifiers;
183 
184     /** After running, set to the first verifier that failed, or nullptr if none failed. */
185     const GMVerifier* fFailedVerifier;
186 
187     /** Returns true if any verifiers in the list need the gold image as input. */
188     bool needsGoldImage() const;
189 };
190 
191 }  // namespace verifiers
192 }  // namespace skiagm
193 
194 #endif
195