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