libui: PrintTo and comparisons for values for tests

Define `PrintTo` and (except for Region) ensure there is an appropriate
`operator==`. The Google Test framework will uses `PrintTo` to print out
values if available, and uses operator == to check if values match
expected values.

The following value types were modified:

  * Rect
  * FloatRect
  * Region
  * Transform

With these definitions, the Composition Engine tests no longer need
custom matchers to print/compare values (except for Region).

For Region it seemed unwise to define a general `operator==` as equality
of Regions might mean different things to different callers. Instead
this change just adds a `Region::hasSameRects(const Region& other)`
function to do the fast check that the tests were doing. As such a
matcher helper is still needed which calls that function, though now it
is much more trivial to write.

Bug: None
Test: libcompositionengine_test
Change-Id: I160cda695d99257966634e767ee1164bc6105e30
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 83ebeca..bf487c4 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -280,6 +280,20 @@
     return begin() == region.begin();
 }
 
+bool Region::hasSameRects(const Region& other) const {
+    size_t thisRectCount = 0;
+    android::Rect const* thisRects = getArray(&thisRectCount);
+    size_t otherRectCount = 0;
+    android::Rect const* otherRects = other.getArray(&otherRectCount);
+
+    if (thisRectCount != otherRectCount) return false;
+
+    for (size_t i = 0; i < thisRectCount; i++) {
+        if (thisRects[i] != otherRects[i]) return false;
+    }
+    return true;
+}
+
 // ----------------------------------------------------------------------------
 
 void Region::addRectUnchecked(int l, int t, int r, int b)
diff --git a/libs/ui/Transform.cpp b/libs/ui/Transform.cpp
index 85abb38..06b6bfe 100644
--- a/libs/ui/Transform.cpp
+++ b/libs/ui/Transform.cpp
@@ -49,6 +49,15 @@
     return isZero(fabs(f) - 1.0f);
 }
 
+bool Transform::operator==(const Transform& other) const {
+    return mMatrix[0][0] == other.mMatrix[0][0] && mMatrix[0][1] == other.mMatrix[0][1] &&
+            mMatrix[0][2] == other.mMatrix[0][2] && mMatrix[1][0] == other.mMatrix[1][0] &&
+            mMatrix[1][1] == other.mMatrix[1][1] && mMatrix[1][2] == other.mMatrix[1][2] &&
+            mMatrix[2][0] == other.mMatrix[2][0] && mMatrix[2][1] == other.mMatrix[2][1] &&
+            mMatrix[2][2] == other.mMatrix[2][2];
+    ;
+}
+
 Transform Transform::operator * (const Transform& rhs) const
 {
     if (CC_LIKELY(mType == IDENTITY))
diff --git a/libs/ui/include/ui/FloatRect.h b/libs/ui/include/ui/FloatRect.h
index 4cd9a0b..bec2552 100644
--- a/libs/ui/include/ui/FloatRect.h
+++ b/libs/ui/include/ui/FloatRect.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <ostream>
+
 namespace android {
 
 class FloatRect {
@@ -52,4 +54,9 @@
     return a.left == b.left && a.top == b.top && a.right == b.right && a.bottom == b.bottom;
 }
 
+static inline void PrintTo(const FloatRect& rect, ::std::ostream* os) {
+    *os << "FloatRect(" << rect.left << ", " << rect.top << ", " << rect.right << ", "
+        << rect.bottom << ")";
+}
+
 }  // namespace android
diff --git a/libs/ui/include/ui/Rect.h b/libs/ui/include/ui/Rect.h
index 1768805..2f2229e 100644
--- a/libs/ui/include/ui/Rect.h
+++ b/libs/ui/include/ui/Rect.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_UI_RECT
 #define ANDROID_UI_RECT
 
+#include <ostream>
+
 #include <utils/Flattenable.h>
 #include <utils/Log.h>
 #include <utils/TypeHelpers.h>
@@ -214,6 +216,12 @@
     }
 };
 
+// Defining PrintTo helps with Google Tests.
+static inline void PrintTo(const Rect& rect, ::std::ostream* os) {
+    *os << "Rect(" << rect.left << ", " << rect.top << ", " << rect.right << ", " << rect.bottom
+        << ")";
+}
+
 ANDROID_BASIC_TYPES_TRAITS(Rect)
 
 }; // namespace android
diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h
index 79642ae..2db3b10 100644
--- a/libs/ui/include/ui/Region.h
+++ b/libs/ui/include/ui/Region.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <ostream>
 
 #include <utils/Vector.h>
 
@@ -119,6 +120,8 @@
     // returns true if the regions share the same underlying storage
     bool isTriviallyEqual(const Region& region) const;
 
+    // returns true if the regions consist of the same rectangle sequence
+    bool hasSameRects(const Region& region) const;
 
     /* various ways to access the rectangle list */
 
@@ -213,6 +216,21 @@
 Region& Region::operator += (const Point& pt) {
     return translateSelf(pt.x, pt.y);
 }
+
+// Defining PrintTo helps with Google Tests.
+static inline void PrintTo(const Region& region, ::std::ostream* os) {
+    Region::const_iterator head = region.begin();
+    Region::const_iterator const tail = region.end();
+    bool first = true;
+    while (head != tail) {
+        *os << (first ? "Region(" : ", ");
+        PrintTo(*head, os);
+        head++;
+        first = false;
+    }
+    *os << ")";
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/libs/ui/include/ui/Transform.h b/libs/ui/include/ui/Transform.h
index fab2d9e..de07684 100644
--- a/libs/ui/include/ui/Transform.h
+++ b/libs/ui/include/ui/Transform.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <ostream>
 #include <string>
 
 #include <hardware/hardware.h>
@@ -63,6 +64,7 @@
     bool        preserveRects() const;
     uint32_t    getType() const;
     uint32_t    getOrientation() const;
+    bool operator==(const Transform& other) const;
 
     const vec3& operator [] (size_t i) const;  // returns column i
     float   tx() const;
@@ -115,6 +117,12 @@
     mutable uint32_t    mType;
 };
 
+static inline void PrintTo(const Transform& t, ::std::ostream* os) {
+    std::string out;
+    t.dump(out, "ui::Transform");
+    *os << out;
+}
+
 }  // namespace ui
 }  // namespace android
 
diff --git a/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h b/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h
deleted file mode 100644
index 6741cc9..0000000
--- a/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <string>
-
-#include <android-base/stringprintf.h>
-#include <gmock/gmock.h>
-
-namespace {
-
-using android::base::StringAppendF;
-using FloatRect = android::FloatRect;
-
-void dumpFloatRect(const FloatRect& rect, std::string& result, const char* name) {
-    StringAppendF(&result, "%s (%f %f %f %f) ", name, rect.left, rect.top, rect.right, rect.bottom);
-}
-
-// Checks for a region match
-MATCHER_P(FloatRectEq, expected, "") {
-    std::string buf;
-    buf.append("FloatRects are not equal\n");
-    dumpFloatRect(expected, buf, "expected rect");
-    dumpFloatRect(arg, buf, "actual rect");
-    *result_listener << buf;
-
-    const float TOLERANCE = 1e-3f;
-    return (std::fabs(expected.left - arg.left) < TOLERANCE) &&
-            (std::fabs(expected.top - arg.top) < TOLERANCE) &&
-            (std::fabs(expected.right - arg.right) < TOLERANCE) &&
-            (std::fabs(expected.bottom - arg.bottom) < TOLERANCE);
-}
-
-} // namespace
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 88acd04..2e030a1 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -23,10 +23,8 @@
 #include <compositionengine/mock/Output.h>
 #include <gtest/gtest.h>
 
-#include "FloatRectMatcher.h"
 #include "MockHWC2.h"
 #include "MockHWComposer.h"
-#include "RectMatcher.h"
 #include "RegionMatcher.h"
 
 namespace android::compositionengine {
@@ -159,19 +157,19 @@
     mLayerFEState.geomUsesSourceCrop = false;
 
     const FloatRect expected{};
-    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+    EXPECT_THAT(calculateOutputSourceCrop(), expected);
 }
 
 TEST_F(OutputLayerSourceCropTest, correctForSimpleDefaultCase) {
     const FloatRect expected{0.f, 0.f, 1920.f, 1080.f};
-    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+    EXPECT_THAT(calculateOutputSourceCrop(), expected);
 }
 
 TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewport) {
     mLayerFEState.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f};
 
     const FloatRect expected{0.f, 0.f, 1920.f, 1080.f};
-    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+    EXPECT_THAT(calculateOutputSourceCrop(), expected);
 }
 
 TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewportRotated) {
@@ -179,7 +177,7 @@
     mLayerFEState.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080);
 
     const FloatRect expected{0.f, 0.f, 1080.f, 1080.f};
-    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+    EXPECT_THAT(calculateOutputSourceCrop(), expected);
 }
 
 TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformedBuffer) {
@@ -218,7 +216,7 @@
         mLayerFEState.geomBufferTransform = entry.buffer;
         mOutputState.orientation = entry.display;
 
-        EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(entry.expected)) << "entry " << i;
+        EXPECT_THAT(calculateOutputSourceCrop(), entry.expected) << "entry " << i;
     }
 }
 
@@ -226,14 +224,14 @@
     mLayerFEState.geomContentCrop = Rect{0, 0, 960, 540};
 
     const FloatRect expected{0.f, 0.f, 960.f, 540.f};
-    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+    EXPECT_THAT(calculateOutputSourceCrop(), expected);
 }
 
 TEST_F(OutputLayerSourceCropTest, viewportAffectsCrop) {
     mOutputState.viewport = Rect{0, 0, 960, 540};
 
     const FloatRect expected{0.f, 0.f, 960.f, 540.f};
-    EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
+    EXPECT_THAT(calculateOutputSourceCrop(), expected);
 }
 
 /*
@@ -265,50 +263,50 @@
 
 TEST_F(OutputLayerDisplayFrameTest, correctForSimpleDefaultCase) {
     const Rect expected{0, 0, 1920, 1080};
-    EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
+    EXPECT_THAT(calculateOutputDisplayFrame(), expected);
 }
 
 TEST_F(OutputLayerDisplayFrameTest, fullActiveTransparentRegionReturnsEmptyFrame) {
     mLayerFEState.transparentRegionHint = Region{Rect{0, 0, 1920, 1080}};
     const Rect expected{0, 0, 0, 0};
-    EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
+    EXPECT_THAT(calculateOutputDisplayFrame(), expected);
 }
 
 TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrame) {
     mLayerFEState.geomCrop = Rect{100, 200, 300, 500};
     const Rect expected{100, 200, 300, 500};
-    EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
+    EXPECT_THAT(calculateOutputDisplayFrame(), expected);
 }
 
 TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrameRotated) {
     mLayerFEState.geomCrop = Rect{100, 200, 300, 500};
     mLayerFEState.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080);
     const Rect expected{1420, 100, 1720, 300};
-    EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
+    EXPECT_THAT(calculateOutputDisplayFrame(), expected);
 }
 
 TEST_F(OutputLayerDisplayFrameTest, emptyGeomCropIsNotUsedToComputeFrame) {
     mLayerFEState.geomCrop = Rect{};
     const Rect expected{0, 0, 1920, 1080};
-    EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
+    EXPECT_THAT(calculateOutputDisplayFrame(), expected);
 }
 
 TEST_F(OutputLayerDisplayFrameTest, geomLayerBoundsAffectsFrame) {
     mLayerFEState.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f};
     const Rect expected{0, 0, 960, 540};
-    EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
+    EXPECT_THAT(calculateOutputDisplayFrame(), expected);
 }
 
 TEST_F(OutputLayerDisplayFrameTest, viewportAffectsFrame) {
     mOutputState.viewport = Rect{0, 0, 960, 540};
     const Rect expected{0, 0, 960, 540};
-    EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
+    EXPECT_THAT(calculateOutputDisplayFrame(), expected);
 }
 
 TEST_F(OutputLayerDisplayFrameTest, outputTransformAffectsDisplayFrame) {
     mOutputState.transform = ui::Transform{HAL_TRANSFORM_ROT_90};
     const Rect expected{-1080, 0, 0, 1920};
-    EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
+    EXPECT_THAT(calculateOutputDisplayFrame(), expected);
 }
 
 /*
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 37b62d8..08b8818 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -35,7 +35,6 @@
 #include "CallOrderStateMachineHelper.h"
 #include "MockHWC2.h"
 #include "RegionMatcher.h"
-#include "TransformMatcher.h"
 
 namespace android::compositionengine {
 namespace {
@@ -244,7 +243,7 @@
 
     mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
 
-    EXPECT_THAT(mOutput->getState().transform, TransformEq(transform));
+    EXPECT_THAT(mOutput->getState().transform, transform);
     EXPECT_EQ(orientation, mOutput->getState().orientation);
     EXPECT_EQ(frame, mOutput->getState().frame);
     EXPECT_EQ(viewport, mOutput->getState().viewport);
diff --git a/services/surfaceflinger/CompositionEngine/tests/RectMatcher.h b/services/surfaceflinger/CompositionEngine/tests/RectMatcher.h
deleted file mode 100644
index d4c76bc..0000000
--- a/services/surfaceflinger/CompositionEngine/tests/RectMatcher.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <string>
-
-#include <android-base/stringprintf.h>
-#include <gmock/gmock.h>
-
-namespace {
-
-using android::base::StringAppendF;
-using Rect = android::Rect;
-
-void dumpRect(const Rect& rect, std::string& result, const char* name) {
-    StringAppendF(&result, "%s (%d %d %d %d) ", name, rect.left, rect.top, rect.right, rect.bottom);
-}
-
-// Checks for a region match
-MATCHER_P(RectEq, expected, "") {
-    std::string buf;
-    buf.append("Rects are not equal\n");
-    dumpRect(expected, buf, "expected rect");
-    dumpRect(arg, buf, "actual rect");
-    *result_listener << buf;
-
-    return (expected.left == arg.left) && (expected.top == arg.top) &&
-            (expected.right == arg.right) && (expected.bottom == arg.bottom);
-}
-
-} // namespace
diff --git a/services/surfaceflinger/CompositionEngine/tests/RegionMatcher.h b/services/surfaceflinger/CompositionEngine/tests/RegionMatcher.h
index 5a4efa9..2adde23 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RegionMatcher.h
+++ b/services/surfaceflinger/CompositionEngine/tests/RegionMatcher.h
@@ -20,24 +20,22 @@
 
 namespace {
 
-// Checks for a region match
-MATCHER_P(RegionEq, expected, "") {
-    std::string buf;
-    buf.append("Regions are not equal\n");
-    expected.dump(buf, "expected region");
-    arg.dump(buf, "actual region");
-    *result_listener << buf;
+using Region = android::Region;
 
-    size_t expectedRectCount = 0;
-    android::Rect const* expectedRects = expected.getArray(&expectedRectCount);
-    size_t actualRectCount = 0;
-    android::Rect const* actualRects = arg.getArray(&actualRectCount);
+struct RegionMatcher : public testing::MatcherInterface<const Region&> {
+    const Region expected;
 
-    if (expectedRectCount != actualRectCount) return false;
-    for (size_t i = 0; i < expectedRectCount; i++) {
-        if (expectedRects[i] != actualRects[i]) return false;
+    explicit RegionMatcher(const Region& expectedValue) : expected(expectedValue) {}
+
+    bool MatchAndExplain(const Region& actual, testing::MatchResultListener*) const override {
+        return expected.hasSameRects(actual);
     }
-    return true;
+
+    void DescribeTo(::std::ostream* os) const override { PrintTo(expected, os); }
+};
+
+testing::Matcher<const Region&> RegionEq(const Region& expected) {
+    return MakeMatcher(new RegionMatcher(expected));
 }
 
 } // namespace
diff --git a/services/surfaceflinger/CompositionEngine/tests/TransformMatcher.h b/services/surfaceflinger/CompositionEngine/tests/TransformMatcher.h
deleted file mode 100644
index ea07bed..0000000
--- a/services/surfaceflinger/CompositionEngine/tests/TransformMatcher.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <string>
-
-#include <gmock/gmock.h>
-
-namespace {
-
-// Check for a transform match
-MATCHER_P(TransformEq, expected, "") {
-    std::string buf;
-    buf.append("Transforms are not equal\n");
-    expected.dump(buf, "expected transform");
-    arg.dump(buf, "actual transform");
-    *result_listener << buf;
-
-    const float TOLERANCE = 1e-3f;
-
-    for (int i = 0; i < 3; i++) {
-        for (int j = 0; j < 3; j++) {
-            if (std::fabs(expected[i][j] - arg[i][j]) > TOLERANCE) {
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-} // namespace