1 /**
2 * Copyright (c) 2021-2022 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 "utils/bit_memory_region-inl.h"
17
18 #include <gtest/gtest.h>
19 #include <array>
20
21 namespace panda::test {
22
CompareData(uint8_t * data,size_t offset,size_t length,uint32_t value,uint8_t fill_value)23 static void CompareData(uint8_t *data, size_t offset, size_t length, uint32_t value, uint8_t fill_value)
24 {
25 for (size_t i = 0; i < length; i++) {
26 uint8_t expected = (offset <= i && i < offset + length) ? value >> (i - offset) : fill_value;
27 uint8_t actual = data[i / BITS_PER_BYTE] >> (i % BITS_PER_BYTE);
28 ASSERT_EQ(expected & 1, actual & 1);
29 }
30 }
31
TEST(BitMemoryRegion,TestBitAccess)32 TEST(BitMemoryRegion, TestBitAccess)
33 {
34 std::array<uint8_t, 16> data;
35 static constexpr std::array<uint8_t, 2> fill_data = {0x00, 0xff};
36 static constexpr std::array<bool, 2> value_data = {false, true};
37 static constexpr size_t MAX_BITS_COUNT = (data.size() - sizeof(uint32_t)) * BITS_PER_BYTE;
38
39 for (size_t offset = 0; offset < MAX_BITS_COUNT; offset++) {
40 uint32_t mask = 0;
41 for (auto fill_value : fill_data) {
42 for (auto value : value_data) {
43 std::fill(data.begin(), data.end(), fill_value);
44 BitMemoryRegion region1(data.data(), offset, 1);
45 region1.Write(value, 0);
46 ASSERT_EQ(region1.Read(0), value);
47 CompareData(data.data(), offset, 1, value, fill_value);
48 std::fill(data.begin(), data.end(), fill_value);
49 BitMemoryRegion region2(data.data(), data.size() * BITS_PER_BYTE);
50 region2.Write(value, offset);
51 ASSERT_EQ(region2.Read(offset), value);
52 CompareData(data.data(), offset, 1, value, fill_value);
53 }
54 }
55 }
56 }
57
TEST(BitMemoryRegion,TestBitsAccess)58 TEST(BitMemoryRegion, TestBitsAccess)
59 {
60 std::array<uint8_t, 16> data;
61 static constexpr std::array<uint8_t, 2> fill_data = {0x00, 0xff};
62 static constexpr size_t MAX_BITS_COUNT = (data.size() - sizeof(uint32_t)) * BITS_PER_BYTE;
63
64 for (size_t offset = 0; offset < MAX_BITS_COUNT; offset++) {
65 uint32_t mask = 0;
66 for (size_t length = 0; length < BITS_PER_UINT32; length++) {
67 const uint32_t value = 0xBADDCAFE & mask;
68 for (auto fill_value : fill_data) {
69 std::fill(data.begin(), data.end(), fill_value);
70 BitMemoryRegion region1(data.data(), offset, length);
71 region1.Write(value, 0, length);
72 ASSERT_EQ(region1.Read(0, length), value);
73 CompareData(data.data(), offset, length, value, fill_value);
74 std::fill(data.begin(), data.end(), fill_value);
75 BitMemoryRegion region2(data.data(), data.size() * BITS_PER_BYTE);
76 region2.Write(value, offset, length);
77 ASSERT_EQ(region2.Read(offset, length), value);
78 CompareData(data.data(), offset, length, value, fill_value);
79 }
80 mask = (mask << 1) | 1;
81 }
82 }
83 }
84
TEST(BitMemoryRegion,Dumping)85 TEST(BitMemoryRegion, Dumping)
86 {
87 std::array<uint64_t, 4> data {};
88 std::stringstream ss;
89 auto clear = [&]() {
90 data.fill(0);
91 ss.str(std::string());
92 };
93
94 {
95 clear();
96 BitMemoryRegion region(data.data(), 0, data.size() * BITS_PER_UINT64);
97 ss << region;
98 ASSERT_EQ(ss.str(), "0x0");
99 }
100
101 {
102 clear();
103 data[0] = 0x5;
104 BitMemoryRegion region(data.data(), 0, 130);
105 ss << region;
106 ASSERT_EQ(ss.str(), "0x5");
107 }
108
109 {
110 clear();
111 data[0] = 0x1;
112 data[1] = 0x2;
113 BitMemoryRegion region(data.data(), 1, 65);
114 ss << region;
115 ASSERT_EQ(ss.str(), "0x10000000000000000");
116 }
117
118 {
119 clear();
120 data[0] = 0x1;
121 data[1] = 0x500;
122 BitMemoryRegion region(data.data(), 0, 129);
123 ss << region;
124 ASSERT_EQ(ss.str(), "0x5000000000000000001");
125 }
126
127 {
128 clear();
129 data[0] = 0x1234560000000000;
130 data[1] = 0x4321;
131 BitMemoryRegion region(data.data(), 40, 40);
132 ss << region;
133 ASSERT_EQ(ss.str(), "0x4321123456");
134 }
135
136 {
137 clear();
138 data[0] = 0x123456789abcdef0;
139 BitMemoryRegion region(data.data(), 2, 20);
140 ss << region;
141 ASSERT_EQ(ss.str(), "0xf37bc");
142 }
143
144 {
145 clear();
146 data[0] = 0x123456789abcdef0;
147 data[1] = 0xfedcba9876543210;
148 BitMemoryRegion region(data.data(), 16, 96);
149 ss << region;
150 ASSERT_EQ(ss.str(), "0xba9876543210123456789abc");
151 }
152
153 {
154 clear();
155 data[0] = 0x1111111111111111;
156 data[1] = 0x2222222222222222;
157 data[2] = 0x4444444444444444;
158 BitMemoryRegion region(data.data(), 31, 120);
159 ss << region;
160 ASSERT_EQ(ss.str(), "0x888888444444444444444422222222");
161 }
162 }
163
164 } // namespace panda::test
165