1 /**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "util/bit_vector.h"
17 #include "util/set_operations.h"
18 #include "util/range.h"
19 #include "util/lazy.h"
20
21 #include <gtest/gtest.h>
22 #include <rapidcheck/gtest.h>
23 #include "util/tests/environment.h"
24
25 #include <cstdint>
26 #include <initializer_list>
27 #include <string>
28 #include <set>
29
30 // NOLINTNEXTLINE(google-build-using-namespace)
31 using namespace ark::verifier;
32
33 using StdSet = std::set<size_t>;
34
35 struct BSet {
36 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
37 StdSet indices;
38 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
39 BitVector bits;
40
IsEqualBSet41 bool IsEqual() const
42 {
43 if (bits.SetBitsCount() != indices.size()) {
44 return false;
45 }
46 for (const auto &elem : indices) {
47 if (!bits[elem]) {
48 return false;
49 }
50 }
51 return true;
52 }
53 };
54
55 namespace rc {
56
57 constexpr size_t MAX_VALUE = 1024U;
58 // NOLINTNEXTLINE(cert-err58-cpp)
59 auto g_valueGen = gen::inRange<size_t>(0, MAX_VALUE);
60
61 template <>
62 struct Arbitrary<BSet> {
arbitraryrc::Arbitrary63 static Gen<BSet> arbitrary() // NOLINT(readability-identifier-naming)
64 {
65 // NOLINTNEXTLINE(readability-magic-numbers)
66 auto setNInc = gen::pair(gen::container<std::set<size_t>>(g_valueGen), gen::inRange(1, 100)); // N = 100
67 return gen::map(setNInc, [](auto paramSetNInc) {
68 auto &[set, inc] = paramSetNInc;
69 size_t size = (set.empty() ? 0 : *set.rbegin()) + inc;
70 BitVector bits {size};
71 for (const auto &idx : set) {
72 bits[idx] = 1;
73 }
74 return BSet {set, bits};
75 });
76 }
77 };
78
79 template <>
80 struct Arbitrary<Range<size_t>> {
arbitraryrc::Arbitrary81 static Gen<Range<size_t>> arbitrary() // NOLINT(readability-identifier-naming)
82 {
83 return gen::map(gen::pair(g_valueGen, g_valueGen), [](auto pair) {
84 return Range<size_t> {std::min(pair.first, pair.second), std::max(pair.first, pair.second)};
85 });
86 }
87 };
88
89 } // namespace rc
90
91 namespace ark::verifier::test {
92
93 // NOLINTNEXTLINE(google-build-using-namespace)
94 using namespace rc;
95
96 using Interval = ark::verifier::Range<size_t>;
97 using Intervals = std::initializer_list<Interval>;
98
ClassifySize(const std::string & name,size_t size,const Intervals & intervals)99 void ClassifySize(const std::string &name, size_t size, const Intervals &intervals)
100 {
101 for (const auto &i : intervals) {
102 RC_CLASSIFY(i.Contains(size), name + " " + std::to_string(i));
103 }
104 }
105
106 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects,cert-err58-cpp)
107 const EnvOptions OPTIONS {"VERIFIER_TEST"};
108 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects,cert-err58-cpp,readability-magic-numbers)
109 Intervals g_statIntervals = {{0, 10U}, {11U, 50U}, {51U, 100U}, {101U, MAX_VALUE}};
110
Stat(const BSet & bitset)111 void Stat(const BSet &bitset)
112 {
113 if (OPTIONS.Get<bool>("verbose", false)) {
114 ClassifySize("Bits.size() in", bitset.bits.Size(), g_statIntervals);
115 ClassifySize("Indices.size() in", bitset.indices.size(), g_statIntervals);
116 }
117 }
118
Universum(size_t size)119 StdSet Universum(size_t size)
120 {
121 return ToSet<StdSet>(Interval(0, size - 1));
122 }
123
124 RC_GTEST_PROP(TestBitvector, BasicTestSetBitsCount, (const BSet &bit_set))
125 {
126 Stat(bit_set);
127 RC_ASSERT(bit_set.bits.SetBitsCount() == bit_set.indices.size());
128 }
129
130 RC_GTEST_PROP(TestBitvector, BasicTestOperatorEq, (const BSet &bit_set))
131 {
132 Stat(bit_set);
133 auto bits = bit_set.bits;
134 RC_ASSERT(bits.Size() == bit_set.bits.Size());
135 for (size_t idx = 0; idx < bits.Size(); ++idx) {
136 RC_ASSERT(bits[idx] == bit_set.bits[idx]);
137 }
138 RC_ASSERT(bits.SetBitsCount() == bit_set.bits.SetBitsCount());
139 }
140
141 RC_GTEST_PROP(TestBitvector, BasicTestClr, (BSet && bset))
142 {
143 Stat(bset);
144 bset.bits.Clr();
145 RC_ASSERT(bset.bits.SetBitsCount() == 0U);
146 }
147
148 RC_GTEST_PROP(TestBitvector, BasicTestSet, (BSet && bset))
149 {
150 Stat(bset);
151 bset.bits.Set();
152 RC_ASSERT(bset.bits.SetBitsCount() == bset.bits.Size());
153 }
154
155 RC_GTEST_PROP(TestBitvector, BasicTestInvert, (BSet && bset))
156 {
157 Stat(bset);
158 auto zeroBits = bset.bits.Size() - bset.bits.SetBitsCount();
159 bset.bits.Invert();
160 RC_ASSERT(bset.bits.SetBitsCount() == zeroBits);
161 }
162
163 RC_GTEST_PROP(TestBitvector, BasicTestClrIdx, (BSet && bset, std::set<size_t> &&indices))
164 {
165 Stat(bset);
166 auto size = bset.bits.Size();
167 for (const auto &idx : indices) {
168 bset.bits.Clr(idx % size);
169 bset.indices.erase(idx % size);
170 }
171 RC_ASSERT(bset.bits.SetBitsCount() == bset.indices.size());
172 }
173
174 RC_GTEST_PROP(TestBitvector, BasicTestSetIdx, (BSet && bset, std::set<size_t> &&indices))
175 {
176 Stat(bset);
177 auto size = bset.bits.Size();
178 for (const auto &idx : indices) {
179 auto i = idx % size;
180 bset.bits.Set(i);
181 bset.indices.insert(i);
182 }
183 RC_ASSERT(bset.bits.SetBitsCount() == bset.indices.size());
184 }
185
186 RC_GTEST_PROP(TestBitvector, BasicTestInvertIdx, (BSet && bset, std::set<size_t> &&indices))
187 {
188 Stat(bset);
189 auto size = bset.bits.Size();
190 for (const auto &idx : indices) {
191 auto i = idx % size;
192 bset.bits.Invert(i);
193 if (bset.indices.count(i) > 0) {
194 bset.indices.erase(i);
195 } else {
196 bset.indices.insert(i);
197 }
198 }
199 RC_ASSERT(bset.bits.SetBitsCount() == bset.indices.size());
200 }
201
202 RC_GTEST_PROP(TestBitvector, BasicTestClrFromTo, (BSet && bset, Interval &&interval))
203 {
204 RC_PRE(interval.Finish() < bset.bits.Size());
205 Stat(bset);
206 bset.bits.Clr(interval.Start(), interval.Finish());
207 for (auto idx : interval) {
208 bset.indices.erase(idx);
209 }
210 RC_ASSERT(bset.bits.SetBitsCount() == bset.indices.size());
211 }
212
213 RC_GTEST_PROP(TestBitvector, BasicTestSetFromTo, (BSet && bset, Interval &&interval))
214 {
215 RC_PRE(interval.Finish() < bset.bits.Size());
216 Stat(bset);
217 bset.bits.Set(interval.Start(), interval.Finish());
218 for (auto idx : interval) {
219 bset.indices.insert(idx);
220 }
221 RC_ASSERT(bset.bits.SetBitsCount() == bset.indices.size());
222 }
223
224 RC_GTEST_PROP(TestBitvector, BasicTestInvertFromTo, (BSet && bset, Interval &&interval))
225 {
226 RC_PRE(interval.Finish() < bset.bits.Size());
227 Stat(bset);
228 bset.bits.Invert(interval.Start(), interval.Finish());
229 for (auto idx : interval) {
230 if (bset.indices.count(idx) > 0) {
231 bset.indices.erase(idx);
232 } else {
233 bset.indices.insert(idx);
234 }
235 }
236 RC_ASSERT(bset.bits.SetBitsCount() == bset.indices.size());
237 }
238
239 RC_GTEST_PROP(TestBitvector, BasicTestOperatorBitwise, (BSet && lhs, BSet &&rhs))
240 {
241 Stat(rhs);
242 Stat(lhs);
243 lhs.bits &= rhs.bits;
244 lhs.indices = SetIntersection(lhs.indices, rhs.indices);
245 RC_ASSERT(lhs.IsEqual());
246 }
247
248 RC_GTEST_PROP(TestBitvector, BasicTestOperatorOr, (BSet && lhs, BSet &&rhs))
249 {
250 Stat(rhs);
251 Stat(lhs);
252 StdSet universum = Universum(std::max(lhs.bits.Size(), rhs.bits.Size()));
253 StdSet clamped = SetIntersection(rhs.indices, universum);
254 lhs.bits |= rhs.bits;
255 lhs.indices = SetUnion(lhs.indices, clamped);
256 RC_ASSERT(lhs.IsEqual());
257 }
258
259 RC_GTEST_PROP(TestBitvector, BasicTestOperatorXor, (BSet && lhs, BSet &&rhs))
260 {
261 Stat(rhs);
262 Stat(lhs);
263 lhs.bits ^= rhs.bits;
264 lhs.indices = SetDifference(SetUnion(lhs.indices, rhs.indices), SetIntersection(lhs.indices, rhs.indices));
265 RC_ASSERT(lhs.IsEqual());
266 }
267
268 RC_GTEST_PROP(TestBitvector, BasicTestResise, (BSet && bset, size_t new_size))
269 {
270 Stat(bset);
271 new_size %= bset.bits.Size();
272 bset.bits.Resize(new_size);
273 auto universum = Universum(new_size);
274 bset.indices = SetIntersection(universum, bset.indices);
275 RC_ASSERT(bset.bits.SetBitsCount() == bset.indices.size());
276 RC_ASSERT(bset.bits.Size() == new_size);
277 }
278
279 RC_GTEST_PROP(TestBitvector, IteratorForAllIdxVal, (BSet && bset))
280 {
281 Stat(bset);
282 StdSet selected;
__anonb76ffb930302(auto idx, auto val) 283 auto handler = [&selected](auto idx, auto val) {
284 while (val) {
285 if (val & 1U) {
286 selected.insert(idx);
287 }
288 val >>= 1U;
289 ++idx;
290 }
291 return true;
292 };
293 bset.bits.ForAllIdxVal(handler);
294 RC_ASSERT(selected == bset.indices);
295 }
296
297 RC_GTEST_PROP(TestBitvector, IteratorForAllIdxOf1, (BSet && bset))
298 {
299 Stat(bset);
300 StdSet result;
__anonb76ffb930402(auto idx) 301 bset.bits.ForAllIdxOf<1>([&result](auto idx) {
302 result.insert(idx);
303 return true;
304 });
305 RC_ASSERT(result == bset.indices);
306 }
307
308 RC_GTEST_PROP(TestBitvector, IteratorForAllIdxOf0, (BSet && bset))
309 {
310 Stat(bset);
311 StdSet result;
__anonb76ffb930502(auto idx) 312 bset.bits.ForAllIdxOf<0>([&result](auto idx) {
313 result.insert(idx);
314 return true;
315 });
316 StdSet universum = Universum(bset.bits.Size());
317 RC_ASSERT(result == SetDifference(universum, bset.indices));
318 }
319
320 RC_GTEST_PROP(TestBitvector, LazyIteratorsLazyIndicesOf1, (BSet && bset))
321 {
322 Stat(bset);
323 size_t from = *gen::inRange<size_t>(0, bset.bits.Size() - 1);
324 size_t to =
325 *gen::oneOf(gen::inRange<size_t>(from, bset.bits.Size()), gen::just(std::numeric_limits<size_t>::max()));
326 auto result = ContainerOf<StdSet>(bset.bits.LazyIndicesOf<1>(from, to));
327 StdSet expected = bset.indices;
328 if (from > 0) {
329 expected.erase(expected.begin(), expected.lower_bound(from));
330 }
331 if (!expected.empty() && to < *expected.rbegin()) {
332 expected.erase(expected.upper_bound(to), expected.end());
333 }
334 RC_ASSERT(result == expected);
335 }
336
337 RC_GTEST_PROP(TestBitvector, LazyIteratorsLazyIndicesOf0, (BSet && bset))
338 {
339 Stat(bset);
340 size_t from = *gen::inRange<size_t>(0, bset.bits.Size() - 1);
341 auto result = ContainerOf<StdSet>(bset.bits.LazyIndicesOf<0>(from));
342 StdSet universum = Universum(bset.bits.Size());
343 StdSet expected = SetDifference(universum, bset.indices);
344 if (from > 0) {
345 expected.erase(expected.begin(), expected.lower_bound(from));
346 }
347 RC_ASSERT(result == expected);
348 }
349
350 RC_GTEST_PROP(TestBitvector, PowerOfFoldedBitsetsAnd2Arg, (BSet && bset1, BSet &&bset2))
351 {
352 Stat(bset1);
353 Stat(bset2);
354 auto result = BitVector::PowerOfAnd(bset1.bits, bset2.bits);
355 RC_ASSERT(result == SetIntersection(bset1.indices, bset2.indices).size());
356 }
357
358 RC_GTEST_PROP(TestBitvector, PowerOfFoldedBitsetsAnd3Arg, (BSet && bset1, BSet &&bset2, BSet &&bset3))
359 {
360 Stat(bset1);
361 Stat(bset2);
362 Stat(bset3);
363 auto result = BitVector::PowerOfAnd(bset1.bits, bset2.bits, bset3.bits);
364 RC_ASSERT(result == SetIntersection(bset1.indices, bset2.indices, bset3.indices).size());
365 }
366
367 RC_GTEST_PROP(TestBitvector, PowerOfFoldedBitsetsOr2Arg, (BSet && bset1, BSet &&bset2))
368 {
369 Stat(bset1);
370 Stat(bset2);
371 auto result = BitVector::PowerOfOr(bset1.bits, bset2.bits);
372 auto size = std::min(bset1.bits.Size(), bset2.bits.Size());
373 auto universum = Universum(size);
374 RC_ASSERT(result == SetIntersection(universum, SetUnion(bset1.indices, bset2.indices)).size());
375 }
376
377 RC_GTEST_PROP(TestBitvector, PowerOfFoldedBitsetsOr3Arg, (BSet && bset1, BSet &&bset2, BSet &&bset3))
378 {
379 Stat(bset1);
380 Stat(bset2);
381 Stat(bset3);
382 auto result = BitVector::PowerOfOr(bset1.bits, bset2.bits, bset3.bits);
383 auto size = std::min(std::min(bset1.bits.Size(), bset2.bits.Size()), bset3.bits.Size());
384 auto universum = Universum(size);
385 RC_ASSERT(result == SetIntersection(universum, SetUnion(bset1.indices, bset2.indices, bset3.indices)).size());
386 }
387
388 RC_GTEST_PROP(TestBitvector, PowerOfFoldedBitsetsXor2Arg, (BSet && bset1, BSet &&bset2))
389 {
390 Stat(bset1);
391 Stat(bset2);
392 auto result = BitVector::PowerOfXor(bset1.bits, bset2.bits);
393 auto size = std::min(bset1.bits.Size(), bset2.bits.Size());
394 auto universum = Universum(size);
395 auto setResult = SetIntersection(universum, SetDifference(SetUnion(bset1.indices, bset2.indices),
396 SetIntersection(bset1.indices, bset2.indices)));
397 RC_ASSERT(result == setResult.size());
398 }
399
400 RC_GTEST_PROP(TestBitvector, PowerOfFoldedBitsetsXor3Arg, (BSet && bset1, BSet &&bset2, BSet &&bset3))
401 {
402 Stat(bset1);
403 Stat(bset2);
404 Stat(bset3);
405 auto result = BitVector::PowerOfXor(bset1.bits, bset2.bits, bset3.bits);
406 auto size = std::min(std::min(bset1.bits.Size(), bset2.bits.Size()), bset3.bits.Size());
407 auto universum = Universum(size);
408 auto xor1 = SetDifference(SetUnion(bset1.indices, bset2.indices), SetIntersection(bset1.indices, bset2.indices));
409 auto xor2 = SetDifference(SetUnion(xor1, bset3.indices), SetIntersection(xor1, bset3.indices));
410 auto setResult = SetIntersection(universum, xor2);
411 RC_ASSERT(result == setResult.size());
412 }
413
414 RC_GTEST_PROP(TestBitvector, PowerOfFoldedBitsetsNot2Arg, (BSet && bset1, BSet &&bset2))
415 {
416 Stat(bset1);
417 Stat(bset2);
418 auto result = BitVector::PowerOfAndNot(bset1.bits, bset2.bits);
419 auto size = std::min(bset1.bits.Size(), bset2.bits.Size());
420 auto universum = Universum(size);
421 auto setResult = SetIntersection(universum, SetDifference(bset1.indices, bset2.indices));
422 RC_ASSERT(result == setResult.size());
423 }
424
425 RC_GTEST_PROP(TestBitvector, LazyIteratorsOverFoldedBitsetsAnd1, (BSet && bset1, BSet &&bset2, BSet &&bset3))
426 {
427 Stat(bset1);
428 Stat(bset2);
429 Stat(bset3);
430 auto result = ContainerOf<StdSet>(BitVector::LazyAndThenIndicesOf<1>(bset1.bits, bset2.bits, bset3.bits));
431 auto size = std::min(std::min(bset1.bits.Size(), bset2.bits.Size()), bset3.bits.Size());
432 auto universum = Universum(size);
433 auto setResult = SetIntersection(universum, bset1.indices, bset2.indices, bset3.indices);
434 RC_ASSERT(result == setResult);
435 }
436
437 RC_GTEST_PROP(TestBitvector, LazyIteratorsOverFoldedBitsetsAnd0, (BSet && bset1, BSet &&bset2, BSet &&bset3))
438 {
439 Stat(bset1);
440 Stat(bset2);
441 Stat(bset3);
442 auto result = ContainerOf<StdSet>(BitVector::LazyAndThenIndicesOf<0>(bset1.bits, bset2.bits, bset3.bits));
443 auto size = std::min(std::min(bset1.bits.Size(), bset2.bits.Size()), bset3.bits.Size());
444 auto universum = Universum(size);
445 auto setResult = SetDifference(universum, SetIntersection(bset1.indices, bset2.indices, bset3.indices));
446 RC_ASSERT(result == setResult);
447 }
448
449 RC_GTEST_PROP(TestBitvector, LazyIteratorsOverFoldedBitsetsOr1, (BSet && bset1, BSet &&bset2, BSet &&bset3))
450 {
451 Stat(bset1);
452 Stat(bset2);
453 Stat(bset3);
454 auto result = ContainerOf<StdSet>(BitVector::LazyOrThenIndicesOf<1>(bset1.bits, bset2.bits, bset3.bits));
455 auto size = std::min(std::min(bset1.bits.Size(), bset2.bits.Size()), bset3.bits.Size());
456 auto universum = Universum(size);
457 auto setResult = SetIntersection(universum, SetUnion(bset1.indices, bset2.indices, bset3.indices));
458 RC_ASSERT(result == setResult);
459 }
460
461 RC_GTEST_PROP(TestBitvector, LazyIteratorsOverFoldedBitsetsOr0, (BSet && bset1, BSet &&bset2, BSet &&bset3))
462 {
463 Stat(bset1);
464 Stat(bset2);
465 Stat(bset3);
466 auto result = ContainerOf<StdSet>(BitVector::LazyOrThenIndicesOf<0>(bset1.bits, bset2.bits, bset3.bits));
467 auto size = std::min(std::min(bset1.bits.Size(), bset2.bits.Size()), bset3.bits.Size());
468 auto universum = Universum(size);
469 auto setResult = SetDifference(universum, SetUnion(bset1.indices, bset2.indices, bset3.indices));
470 RC_ASSERT(result == setResult);
471 }
472
473 RC_GTEST_PROP(TestBitvector, LazyIteratorsOverFoldedBitsetsXor1, (BSet && bset1, BSet &&bset2, BSet &&bset3))
474 {
475 Stat(bset1);
476 Stat(bset2);
477 Stat(bset3);
478 auto result = ContainerOf<StdSet>(BitVector::LazyXorThenIndicesOf<1>(bset1.bits, bset2.bits, bset3.bits));
479 auto size = std::min(std::min(bset1.bits.Size(), bset2.bits.Size()), bset3.bits.Size());
480 auto universum = Universum(size);
481 auto xor1 = SetDifference(SetUnion(bset1.indices, bset2.indices), SetIntersection(bset1.indices, bset2.indices));
482 auto xor2 = SetDifference(SetUnion(xor1, bset3.indices), SetIntersection(xor1, bset3.indices));
483 auto setResult = SetIntersection(universum, xor2);
484 RC_ASSERT(result == setResult);
485 }
486
487 RC_GTEST_PROP(TestBitvector, LazyIteratorsOverFoldedBitsetsXor0, (BSet && bset1, BSet &&bset2, BSet &&bset3))
488 {
489 Stat(bset1);
490 Stat(bset2);
491 Stat(bset3);
492 auto result = ContainerOf<StdSet>(BitVector::LazyXorThenIndicesOf<0>(bset1.bits, bset2.bits, bset3.bits));
493 auto size = std::min(std::min(bset1.bits.Size(), bset2.bits.Size()), bset3.bits.Size());
494 auto universum = Universum(size);
495 auto xor1 = SetDifference(SetUnion(bset1.indices, bset2.indices), SetIntersection(bset1.indices, bset2.indices));
496 auto xor2 = SetDifference(SetUnion(xor1, bset3.indices), SetIntersection(xor1, bset3.indices));
497 auto setResult = SetDifference(universum, xor2);
498 RC_ASSERT(result == setResult);
499 }
500
501 RC_GTEST_PROP(TestBitvector, LazyIteratorsOverFoldedBitsetsNot1, (BSet && bset1, BSet &&bset2, BSet &&bset3))
502 {
503 Stat(bset1);
504 Stat(bset2);
505 Stat(bset3);
506 auto result = ContainerOf<StdSet>(BitVector::LazyAndNotThenIndicesOf<1>(bset1.bits, bset2.bits, bset3.bits));
507 auto size = std::min(std::min(bset1.bits.Size(), bset2.bits.Size()), bset3.bits.Size());
508 auto universum = Universum(size);
509 auto setAnd = SetIntersection(bset1.indices, bset2.indices);
510 auto setNot = SetDifference(universum, bset3.indices);
511 auto setResult = SetIntersection(setAnd, setNot);
512 RC_ASSERT(result == setResult);
513 }
514
515 RC_GTEST_PROP(TestBitvector, LazyIteratorsOverFoldedBitsetsNot0, (BSet && bset1, BSet &&bset2, BSet &&bset3))
516 {
517 Stat(bset1);
518 Stat(bset2);
519 Stat(bset3);
520 auto result = ContainerOf<StdSet>(BitVector::LazyAndNotThenIndicesOf<0>(bset1.bits, bset2.bits, bset3.bits));
521 auto size = std::min(std::min(bset1.bits.Size(), bset2.bits.Size()), bset3.bits.Size());
522 auto universum = Universum(size);
523 auto setAnd = SetIntersection(bset1.indices, bset2.indices);
524 auto setNot = SetDifference(universum, bset3.indices);
525 auto setResult = SetDifference(universum, SetIntersection(setAnd, setNot));
526 RC_ASSERT(result == setResult);
527 }
528
529 } // namespace ark::verifier::test
530