aboutsummaryrefslogtreecommitdiff
path: root/src/decoder/test/partition_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/decoder/test/partition_test.cc')
-rw-r--r--src/decoder/test/partition_test.cc263
1 files changed, 263 insertions, 0 deletions
diff --git a/src/decoder/test/partition_test.cc b/src/decoder/test/partition_test.cc
new file mode 100644
index 0000000..63adfb5
--- /dev/null
+++ b/src/decoder/test/partition_test.cc
@@ -0,0 +1,263 @@
+// Copyright 2018 Google LLC
+//
+// 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
+//
+// https://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.
+
+#include "src/decoder/partition.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <array>
+#include <random>
+#include <string>
+#include <vector>
+
+namespace {
+
+using ::testing::ElementsAreArray;
+using ::testing::Eq;
+using ::testing::Le;
+using ::testing::Not;
+
+using astc_codec::Footprint;
+using astc_codec::Partition;
+using astc_codec::PartitionMetric;
+using astc_codec::GetASTCPartition;
+using astc_codec::FindClosestASTCPartition;
+
+// Test to make sure that a simple difference between two partitions where
+// most of the values are the same returns what we expect.
+TEST(PartitionTest, TestSimplePartitionMetric) {
+ Partition a = {Footprint::Get6x6(), /* num_parts = */ 2,
+ /* partition_id = */ {}, /* assignment = */ {}};
+ Partition b = a;
+
+ a.assignment = {
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1,
+ };
+
+ b.assignment = {
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ };
+
+ const int dist = PartitionMetric(a, b);
+ EXPECT_EQ(dist, 2);
+}
+
+// Test to make sure that if one partition is a subset of another that we still
+// return the proper difference against the subset of the larger one.
+TEST(PartitionDeathTest, TestPartitionMetric) {
+ Partition a = {Footprint::Get4x4(), /* num_parts = */ 2,
+ /* partition_id = */ {}, /* assignment = */ {}};
+ Partition b = {Footprint::Get6x6(), /* num_parts = */ 2,
+ /* partition_id = */ {}, /* assignment = */ {}};
+
+ a.assignment = {{
+ 1, 1, 1, 1,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 1,
+ }};
+
+ b.assignment = {{
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0,
+ }};
+
+ EXPECT_DEATH(PartitionMetric(a, b), "");
+}
+
+// Test to make sure that even if we have different numbers of subsets for each
+// partition, that the returned value is what we'd expect.
+TEST(PartitionTest, TestDiffPartsPartitionMetric) {
+ Partition a = {Footprint::Get4x4(), /* num_parts = */ 2,
+ /* partition_id = */ {}, /* assignment = */ {}};
+ Partition b = {Footprint::Get4x4(), /* num_parts = */ 3,
+ /* partition_id = */ {}, /* assignment = */ {}};
+
+ a.assignment = {{
+ 2, 2, 2, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 1,
+ }};
+
+ b.assignment = {{
+ 1, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+ }};
+
+ const int dist = PartitionMetric(a, b);
+ EXPECT_EQ(dist, 3);
+}
+
+// An additional sanity check test that makes sure that we're not always mapping
+// zero to zero in our tests.
+TEST(PartitionTest, TestDiffMappingPartitionMetric) {
+ Partition a = {Footprint::Get4x4(), /* num_parts = */ 2,
+ /* partition_id = */ {}, /* assignment = */ {}};
+ Partition b = {Footprint::Get4x4(), /* num_parts = */ 3,
+ /* partition_id = */ {}, /* assignment = */ {}};
+
+ a.assignment = {{
+ 0, 1, 2, 2,
+ 2, 2, 2, 2,
+ 2, 2, 2, 2,
+ 2, 2, 2, 2,
+ }};
+
+ b.assignment = {{
+ 1, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }};
+
+ const int dist = PartitionMetric(a, b);
+ EXPECT_EQ(dist, 1);
+}
+
+// Finally, if we grab an ASTC partition and modify it a tad, the closest
+// partition should still be the same ASTC partition.
+TEST(PartitionTest, TestFindingASTCPartition) {
+ const Partition astc = GetASTCPartition(Footprint::Get12x12(), 3, 0x3CB);
+ Partition almost_astc = astc;
+ almost_astc.assignment[0]++;
+
+ const Partition& closest_astc = FindClosestASTCPartition(almost_astc);
+ EXPECT_EQ(astc, closest_astc);
+}
+
+// Test a partition that was obtained from the reference ASTC encoder. We should
+// be able to match it exactly
+TEST(PartitionTest, TestSpecificPartition) {
+ const Partition astc = GetASTCPartition(Footprint::Get10x6(), 3, 557);
+ EXPECT_THAT(astc.assignment, ElementsAreArray(std::array<int, 60> {{
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2,
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2,
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2,
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2,
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2,
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2 }}));
+}
+
+// Make sure that when we match against this specific partition, it'll return a
+// partition with the same number of subsets
+TEST(PartitionTest, EstimatedPartitionSubsets) {
+ Partition partition = {
+ /* footprint = */ Footprint::Get6x6(),
+ /* num_parts = */ 2,
+ /* partition_id = */ {},
+ /* assignment = */ {
+ 0, 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1
+ }};
+
+ const Partition astc = FindClosestASTCPartition(partition);
+ EXPECT_THAT(astc.num_parts, Eq(partition.num_parts));
+}
+
+// Make sure that regardless of what partition we match against, it'll return a
+// partition with at most a fewer number of subsets
+TEST(PartitionTest, EstimatedPartitionFewerSubsets) {
+ std::mt19937 random(0xdeadbeef);
+ auto randUniform = [&random](int max) {
+ std::uniform_int_distribution<> dist(0, max - 1);
+ return dist(random);
+ };
+
+ constexpr int kNumFootprints = Footprint::NumValidFootprints();
+ const auto kFootprints = std::array<Footprint, kNumFootprints> {{
+ Footprint::Get4x4(),
+ Footprint::Get5x4(),
+ Footprint::Get5x5(),
+ Footprint::Get6x5(),
+ Footprint::Get6x6(),
+ Footprint::Get8x5(),
+ Footprint::Get8x6(),
+ Footprint::Get8x8(),
+ Footprint::Get10x5(),
+ Footprint::Get10x6(),
+ Footprint::Get10x8(),
+ Footprint::Get10x10(),
+ Footprint::Get12x10(),
+ Footprint::Get12x12()
+ }};
+
+ constexpr int kNumTests = 200;
+ for (int i = 0; i < kNumTests; ++i) {
+ const auto& footprint = kFootprints[randUniform(kNumFootprints)];
+ const int num_parts = 2 + randUniform(3);
+ Partition partition = {
+ footprint,
+ num_parts,
+ /* partition_id = */ {},
+ /* assignment = */ std::vector<int>(footprint.NumPixels(), 0)};
+
+ for (auto& p : partition.assignment) {
+ p = randUniform(num_parts);
+ }
+
+ const Partition astc = FindClosestASTCPartition(partition);
+ EXPECT_THAT(astc.num_parts, Le(partition.num_parts))
+ << "Test #" << i << ": "
+ << "Selected partition with ID " << astc.partition_id.value();
+ }
+}
+
+// Make sure that we generate unique partitions that are close to the
+// candidates.
+TEST(PartitionTest, UniquePartitionResults) {
+ Partition partition = {
+ /* footprint = */ Footprint::Get6x6(),
+ /* num_parts = */ 2,
+ /* partition_id = */ {},
+ /* assignment = */ {
+ 0, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1
+ }};
+
+ const auto parts = FindKClosestASTCPartitions(partition, 2);
+ EXPECT_THAT(*parts[0], Not(Eq(*parts[1])));
+}
+
+// TODO(google): Verify somehow that the assignment generated from
+// GetASTCPartition actually matches what's in the spec. The selection
+// function was more or less copy/pasted though so it's unclear how to
+// measure that against e.g. the ASTC encoder.
+
+} // namespace