1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/zucchini/encoded_view.h"
6
7 #include <iterator>
8 #include <numeric>
9 #include <vector>
10
11 #include "components/zucchini/image_index.h"
12 #include "components/zucchini/test_disassembler.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace zucchini {
16
17 namespace {
18
19 constexpr size_t PADDING = kReferencePaddingProjection;
20
21 template <class It1, class It2>
TestInputIterator(It1 first_expected,It1 last_expected,It2 first_input,It2 last_input)22 void TestInputIterator(It1 first_expected,
23 It1 last_expected,
24 It2 first_input,
25 It2 last_input) {
26 while (first_expected != last_expected && first_input != last_input) {
27 EXPECT_EQ(*first_expected, *first_input);
28 ++first_expected;
29 ++first_input;
30 }
31 EXPECT_EQ(last_input, first_input);
32 EXPECT_EQ(last_expected, first_expected);
33 }
34
35 template <class It1, class It2>
TestForwardIterator(It1 first_expected,It1 last_expected,It2 first_input,It2 last_input)36 void TestForwardIterator(It1 first_expected,
37 It1 last_expected,
38 It2 first_input,
39 It2 last_input) {
40 TestInputIterator(first_expected, last_expected, first_input, last_input);
41
42 while (first_expected != last_expected && first_input != last_input) {
43 EXPECT_EQ(*(first_expected++), *(first_input++));
44 }
45 EXPECT_EQ(last_input, first_input);
46 EXPECT_EQ(last_expected, first_expected);
47 }
48
49 template <class It1, class It2>
TestBidirectionalIterator(It1 first_expected,It1 last_expected,It2 first_input,It2 last_input)50 void TestBidirectionalIterator(It1 first_expected,
51 It1 last_expected,
52 It2 first_input,
53 It2 last_input) {
54 TestForwardIterator(first_expected, last_expected, first_input, last_input);
55
56 while (first_expected != last_expected && first_input != last_input) {
57 EXPECT_EQ(*(--last_expected), *(--last_input));
58 }
59 EXPECT_EQ(last_input, first_input);
60 EXPECT_EQ(last_expected, first_expected);
61 }
62
63 template <class It1, class It2>
TestRandomAccessIterator(It1 first_expected,It1 last_expected,It2 first_input,It2 last_input)64 void TestRandomAccessIterator(It1 first_expected,
65 It1 last_expected,
66 It2 first_input,
67 It2 last_input) {
68 TestBidirectionalIterator(first_expected, last_expected, first_input,
69 last_input);
70
71 using difference_type = typename std::iterator_traits<It1>::difference_type;
72
73 difference_type expected_size = last_expected - first_expected;
74 difference_type input_size = last_input - first_input;
75 EXPECT_EQ(expected_size, input_size);
76
77 for (difference_type i = 0; i < expected_size; ++i) {
78 EXPECT_EQ(*(first_expected + i), *(first_input + i));
79 EXPECT_EQ(first_expected[i], first_input[i]);
80
81 EXPECT_EQ(0 < i, first_input < first_input + i);
82 EXPECT_EQ(0 > i, first_input > first_input + i);
83 EXPECT_EQ(0 <= i, first_input <= first_input + i);
84 EXPECT_EQ(0 >= i, first_input >= first_input + i);
85
86 EXPECT_EQ(expected_size < i, last_input < first_input + i);
87 EXPECT_EQ(expected_size > i, last_input > first_input + i);
88 EXPECT_EQ(expected_size <= i, last_input <= first_input + i);
89 EXPECT_EQ(expected_size >= i, last_input >= first_input + i);
90
91 It2 input = first_input;
92 input += i;
93 EXPECT_EQ(*input, first_expected[i]);
94 input -= i;
95 EXPECT_EQ(first_input, input);
96 input += i;
97
98 EXPECT_EQ(0 < i, first_input < input);
99 EXPECT_EQ(0 > i, first_input > input);
100 EXPECT_EQ(0 <= i, first_input <= input);
101 EXPECT_EQ(0 >= i, first_input >= input);
102
103 EXPECT_EQ(expected_size < i, last_input < input);
104 EXPECT_EQ(expected_size > i, last_input > input);
105 EXPECT_EQ(expected_size <= i, last_input <= input);
106 EXPECT_EQ(expected_size >= i, last_input >= input);
107 }
108 }
109
110 } // namespace
111
112 class EncodedViewTest : public testing::Test {
113 protected:
EncodedViewTest()114 EncodedViewTest()
115 : buffer_(20),
116 image_index_(ConstBufferView(buffer_.data(), buffer_.size())) {
117 std::iota(buffer_.begin(), buffer_.end(), 0);
118 TestDisassembler disasm({2, TypeTag(0), PoolTag(0)},
119 {{1, 0}, {8, 1}, {10, 2}},
120 {4, TypeTag(1), PoolTag(0)}, {{3, 3}},
121 {3, TypeTag(2), PoolTag(1)}, {{12, 4}, {17, 5}});
122 image_index_.Initialize(&disasm);
123 }
124
CheckView(std::vector<size_t> expected,const EncodedView & encoded_view) const125 void CheckView(std::vector<size_t> expected,
126 const EncodedView& encoded_view) const {
127 for (offset_t i = 0; i < encoded_view.size(); ++i) {
128 EXPECT_EQ(expected[i], encoded_view.Projection(i)) << i;
129 }
130 TestRandomAccessIterator(expected.begin(), expected.end(),
131 encoded_view.begin(), encoded_view.end());
132 }
133
134 std::vector<uint8_t> buffer_;
135 ImageIndex image_index_;
136 };
137
TEST_F(EncodedViewTest,Unlabeled)138 TEST_F(EncodedViewTest, Unlabeled) {
139 EncodedView encoded_view(image_index_);
140
141 encoded_view.SetLabels(PoolTag(0), {0, 0, 0, 0}, 1);
142 encoded_view.SetLabels(PoolTag(1), {0, 0}, 1);
143
144 std::vector<size_t> expected = {
145 0, // raw
146 kBaseReferenceProjection + 0 + 0 * 3, // ref 0
147 PADDING,
148 kBaseReferenceProjection + 1 + 0 * 3, // ref 1
149 PADDING,
150 PADDING,
151 PADDING,
152 7, // raw
153 kBaseReferenceProjection + 0 + 0 * 3, // ref 0
154 PADDING,
155 kBaseReferenceProjection + 0 + 0 * 3, // ref 0
156 PADDING,
157 kBaseReferenceProjection + 2 + 0 * 3, // ref 2
158 PADDING,
159 PADDING,
160 15, // raw
161 16,
162 kBaseReferenceProjection + 2 + 0 * 3, // ref 2
163 PADDING,
164 PADDING,
165 };
166 EXPECT_EQ(kBaseReferenceProjection + 3 * 1, encoded_view.Cardinality());
167 CheckView(expected, encoded_view);
168 }
169
TEST_F(EncodedViewTest,Labeled)170 TEST_F(EncodedViewTest, Labeled) {
171 EncodedView encoded_view(image_index_);
172
173 encoded_view.SetLabels(PoolTag(0), {0, 2, 1, 2}, 3);
174 encoded_view.SetLabels(PoolTag(1), {0, 0}, 1);
175
176 std::vector<size_t> expected = {
177 0, // raw
178 kBaseReferenceProjection + 0 + 0 * 3, // ref 0
179 PADDING,
180 kBaseReferenceProjection + 1 + 2 * 3, // ref 1
181 PADDING,
182 PADDING,
183 PADDING,
184 7, // raw
185 kBaseReferenceProjection + 0 + 2 * 3, // ref 0
186 PADDING,
187 kBaseReferenceProjection + 0 + 1 * 3, // ref 0
188 PADDING,
189 kBaseReferenceProjection + 2 + 0 * 3, // ref 2
190 PADDING,
191 PADDING,
192 15, // raw
193 16,
194 kBaseReferenceProjection + 2 + 0 * 3, // ref 2
195 PADDING,
196 PADDING,
197 };
198 EXPECT_EQ(kBaseReferenceProjection + 3 * 3, encoded_view.Cardinality());
199 CheckView(expected, encoded_view);
200 }
201
202 } // namespace zucchini
203