xref: /aosp_15_r20/external/bcc/tests/cc/test_hash_table.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) 2017 Politecnico di Torino
3*387f9dfdSAndroid Build Coastguard Worker  *
4*387f9dfdSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*387f9dfdSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*387f9dfdSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*387f9dfdSAndroid Build Coastguard Worker  *
8*387f9dfdSAndroid Build Coastguard Worker  * http://www.apache.org/licenses/LICENSE-2.0
9*387f9dfdSAndroid Build Coastguard Worker  *
10*387f9dfdSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*387f9dfdSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*387f9dfdSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*387f9dfdSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*387f9dfdSAndroid Build Coastguard Worker  * limitations under the License.
15*387f9dfdSAndroid Build Coastguard Worker  */
16*387f9dfdSAndroid Build Coastguard Worker 
17*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h"
18*387f9dfdSAndroid Build Coastguard Worker #include <linux/version.h>
19*387f9dfdSAndroid Build Coastguard Worker 
20*387f9dfdSAndroid Build Coastguard Worker #include "catch.hpp"
21*387f9dfdSAndroid Build Coastguard Worker 
22*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test hash table", "[hash_table]") {
23*387f9dfdSAndroid Build Coastguard Worker   const std::string BPF_PROGRAM = R"(
24*387f9dfdSAndroid Build Coastguard Worker     BPF_TABLE("hash", int, int, myhash, 1024);
25*387f9dfdSAndroid Build Coastguard Worker     BPF_TABLE("array", int, int, myarray, 1024);
26*387f9dfdSAndroid Build Coastguard Worker   )";
27*387f9dfdSAndroid Build Coastguard Worker 
28*387f9dfdSAndroid Build Coastguard Worker   ebpf::BPF bpf;
29*387f9dfdSAndroid Build Coastguard Worker   ebpf::StatusTuple res(0);
30*387f9dfdSAndroid Build Coastguard Worker   res = bpf.init(BPF_PROGRAM);
31*387f9dfdSAndroid Build Coastguard Worker   REQUIRE(res.ok());
32*387f9dfdSAndroid Build Coastguard Worker 
33*387f9dfdSAndroid Build Coastguard Worker   ebpf::BPFHashTable<int, int> t = bpf.get_hash_table<int, int>("myhash");
34*387f9dfdSAndroid Build Coastguard Worker 
35*387f9dfdSAndroid Build Coastguard Worker   SECTION("bad table type") {
36*387f9dfdSAndroid Build Coastguard Worker     // try to get table of wrong type
__anon99f2c8330102()37*387f9dfdSAndroid Build Coastguard Worker     auto f1 = [&](){
38*387f9dfdSAndroid Build Coastguard Worker       bpf.get_hash_table<int, int>("myarray");
39*387f9dfdSAndroid Build Coastguard Worker     };
40*387f9dfdSAndroid Build Coastguard Worker 
41*387f9dfdSAndroid Build Coastguard Worker     REQUIRE_THROWS(f1());
42*387f9dfdSAndroid Build Coastguard Worker   }
43*387f9dfdSAndroid Build Coastguard Worker 
44*387f9dfdSAndroid Build Coastguard Worker   SECTION("standard methods") {
45*387f9dfdSAndroid Build Coastguard Worker     int k, v1, v2;
46*387f9dfdSAndroid Build Coastguard Worker     k = 1;
47*387f9dfdSAndroid Build Coastguard Worker     v1 = 42;
48*387f9dfdSAndroid Build Coastguard Worker     // create new element
49*387f9dfdSAndroid Build Coastguard Worker     res = t.update_value(k, v1);
50*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(res.ok());
51*387f9dfdSAndroid Build Coastguard Worker     res = t.get_value(k, v2);
52*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(res.ok());
53*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(v2 == 42);
54*387f9dfdSAndroid Build Coastguard Worker 
55*387f9dfdSAndroid Build Coastguard Worker     // update existing element
56*387f9dfdSAndroid Build Coastguard Worker     v1 = 69;
57*387f9dfdSAndroid Build Coastguard Worker     res = t.update_value(k, v1);
58*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(res.ok());
59*387f9dfdSAndroid Build Coastguard Worker     res = t.get_value(k, v2);
60*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(res.ok());
61*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(v2 == 69);
62*387f9dfdSAndroid Build Coastguard Worker 
63*387f9dfdSAndroid Build Coastguard Worker     // remove existing element
64*387f9dfdSAndroid Build Coastguard Worker     res = t.remove_value(k);
65*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(res.ok());
66*387f9dfdSAndroid Build Coastguard Worker 
67*387f9dfdSAndroid Build Coastguard Worker     // remove non existing element
68*387f9dfdSAndroid Build Coastguard Worker     res = t.remove_value(k);
69*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(!res.ok());
70*387f9dfdSAndroid Build Coastguard Worker 
71*387f9dfdSAndroid Build Coastguard Worker     // get non existing element
72*387f9dfdSAndroid Build Coastguard Worker     res = t.get_value(k, v2);
73*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(!res.ok());
74*387f9dfdSAndroid Build Coastguard Worker   }
75*387f9dfdSAndroid Build Coastguard Worker 
76*387f9dfdSAndroid Build Coastguard Worker   SECTION("walk table") {
77*387f9dfdSAndroid Build Coastguard Worker     for (int i = 1; i <= 10; i++) {
78*387f9dfdSAndroid Build Coastguard Worker       res = t.update_value(i * 3, i);
79*387f9dfdSAndroid Build Coastguard Worker       REQUIRE(res.ok());
80*387f9dfdSAndroid Build Coastguard Worker     }
81*387f9dfdSAndroid Build Coastguard Worker     auto offline = t.get_table_offline();
82*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(offline.size() == 10);
83*387f9dfdSAndroid Build Coastguard Worker     for (const auto &pair : offline) {
84*387f9dfdSAndroid Build Coastguard Worker       REQUIRE(pair.first % 3 == 0);
85*387f9dfdSAndroid Build Coastguard Worker       REQUIRE(pair.first / 3 == pair.second);
86*387f9dfdSAndroid Build Coastguard Worker     }
87*387f9dfdSAndroid Build Coastguard Worker 
88*387f9dfdSAndroid Build Coastguard Worker     // clear table
89*387f9dfdSAndroid Build Coastguard Worker     t.clear_table_non_atomic();
90*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(t.get_table_offline().size() == 0);
91*387f9dfdSAndroid Build Coastguard Worker   }
92*387f9dfdSAndroid Build Coastguard Worker }
93*387f9dfdSAndroid Build Coastguard Worker 
94*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0)
95*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("percpu hash table", "[percpu_hash_table]") {
96*387f9dfdSAndroid Build Coastguard Worker   const std::string BPF_PROGRAM = R"(
97*387f9dfdSAndroid Build Coastguard Worker     BPF_PERCPU_HASH(myhash, int, u64, 128);
98*387f9dfdSAndroid Build Coastguard Worker     BPF_PERCPU_ARRAY(myarray, u64, 64);
99*387f9dfdSAndroid Build Coastguard Worker   )";
100*387f9dfdSAndroid Build Coastguard Worker 
101*387f9dfdSAndroid Build Coastguard Worker   ebpf::BPF bpf;
102*387f9dfdSAndroid Build Coastguard Worker   ebpf::StatusTuple res(0);
103*387f9dfdSAndroid Build Coastguard Worker   res = bpf.init(BPF_PROGRAM);
104*387f9dfdSAndroid Build Coastguard Worker   REQUIRE(res.ok());
105*387f9dfdSAndroid Build Coastguard Worker 
106*387f9dfdSAndroid Build Coastguard Worker   ebpf::BPFPercpuHashTable<int, uint64_t> t =
107*387f9dfdSAndroid Build Coastguard Worker     bpf.get_percpu_hash_table<int, uint64_t>("myhash");
108*387f9dfdSAndroid Build Coastguard Worker   size_t ncpus = ebpf::BPFTable::get_possible_cpu_count();
109*387f9dfdSAndroid Build Coastguard Worker 
110*387f9dfdSAndroid Build Coastguard Worker   SECTION("bad table type") {
111*387f9dfdSAndroid Build Coastguard Worker     // try to get table of wrong type
__anon99f2c8330202()112*387f9dfdSAndroid Build Coastguard Worker     auto f1 = [&](){
113*387f9dfdSAndroid Build Coastguard Worker       bpf.get_percpu_hash_table<int, uint64_t>("myarray");
114*387f9dfdSAndroid Build Coastguard Worker     };
115*387f9dfdSAndroid Build Coastguard Worker 
116*387f9dfdSAndroid Build Coastguard Worker     REQUIRE_THROWS(f1());
117*387f9dfdSAndroid Build Coastguard Worker   }
118*387f9dfdSAndroid Build Coastguard Worker 
119*387f9dfdSAndroid Build Coastguard Worker   SECTION("standard methods") {
120*387f9dfdSAndroid Build Coastguard Worker     int k;
121*387f9dfdSAndroid Build Coastguard Worker     std::vector<uint64_t> v1(ncpus);
122*387f9dfdSAndroid Build Coastguard Worker     std::vector<uint64_t> v2;
123*387f9dfdSAndroid Build Coastguard Worker 
124*387f9dfdSAndroid Build Coastguard Worker     for (size_t j = 0; j < ncpus; j++) {
125*387f9dfdSAndroid Build Coastguard Worker       v1[j] = 42 * j;
126*387f9dfdSAndroid Build Coastguard Worker     }
127*387f9dfdSAndroid Build Coastguard Worker 
128*387f9dfdSAndroid Build Coastguard Worker     k = 1;
129*387f9dfdSAndroid Build Coastguard Worker 
130*387f9dfdSAndroid Build Coastguard Worker     // create new element
131*387f9dfdSAndroid Build Coastguard Worker     res = t.update_value(k, v1);
132*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(res.ok());
133*387f9dfdSAndroid Build Coastguard Worker     res = t.get_value(k, v2);
134*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(res.ok());
135*387f9dfdSAndroid Build Coastguard Worker     for (size_t j = 0; j < ncpus; j++) {
136*387f9dfdSAndroid Build Coastguard Worker       REQUIRE(v2.at(j) == 42 * j);
137*387f9dfdSAndroid Build Coastguard Worker     }
138*387f9dfdSAndroid Build Coastguard Worker 
139*387f9dfdSAndroid Build Coastguard Worker     // update existing element
140*387f9dfdSAndroid Build Coastguard Worker     for (size_t j = 0; j < ncpus; j++) {
141*387f9dfdSAndroid Build Coastguard Worker       v1[j] = 69 * j;
142*387f9dfdSAndroid Build Coastguard Worker     }
143*387f9dfdSAndroid Build Coastguard Worker     res = t.update_value(k, v1);
144*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(res.ok());
145*387f9dfdSAndroid Build Coastguard Worker     res = t.get_value(k, v2);
146*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(res.ok());
147*387f9dfdSAndroid Build Coastguard Worker     for (size_t j = 0; j < ncpus; j++) {
148*387f9dfdSAndroid Build Coastguard Worker       REQUIRE(v2.at(j) == 69 * j);
149*387f9dfdSAndroid Build Coastguard Worker     }
150*387f9dfdSAndroid Build Coastguard Worker 
151*387f9dfdSAndroid Build Coastguard Worker     // remove existing element
152*387f9dfdSAndroid Build Coastguard Worker     res = t.remove_value(k);
153*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(res.ok());
154*387f9dfdSAndroid Build Coastguard Worker 
155*387f9dfdSAndroid Build Coastguard Worker     // remove non existing element
156*387f9dfdSAndroid Build Coastguard Worker     res = t.remove_value(k);
157*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(!res.ok());
158*387f9dfdSAndroid Build Coastguard Worker 
159*387f9dfdSAndroid Build Coastguard Worker     // get non existing element
160*387f9dfdSAndroid Build Coastguard Worker     res = t.get_value(k, v2);
161*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(!res.ok());
162*387f9dfdSAndroid Build Coastguard Worker   }
163*387f9dfdSAndroid Build Coastguard Worker 
164*387f9dfdSAndroid Build Coastguard Worker   SECTION("walk table") {
165*387f9dfdSAndroid Build Coastguard Worker     std::vector<uint64_t> v(ncpus);
166*387f9dfdSAndroid Build Coastguard Worker 
167*387f9dfdSAndroid Build Coastguard Worker     for (int k = 3; k <= 30; k+=3) {
168*387f9dfdSAndroid Build Coastguard Worker       for (size_t cpu = 0; cpu < ncpus; cpu++) {
169*387f9dfdSAndroid Build Coastguard Worker         v[cpu] = k * cpu;
170*387f9dfdSAndroid Build Coastguard Worker       }
171*387f9dfdSAndroid Build Coastguard Worker       res = t.update_value(k, v);
172*387f9dfdSAndroid Build Coastguard Worker       REQUIRE(res.ok());
173*387f9dfdSAndroid Build Coastguard Worker     }
174*387f9dfdSAndroid Build Coastguard Worker 
175*387f9dfdSAndroid Build Coastguard Worker     // get whole table
176*387f9dfdSAndroid Build Coastguard Worker     auto offline = t.get_table_offline();
177*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(offline.size() == 10);
178*387f9dfdSAndroid Build Coastguard Worker     for (int i = 0; i < 10; i++) {
179*387f9dfdSAndroid Build Coastguard Worker       // check the key
180*387f9dfdSAndroid Build Coastguard Worker       REQUIRE(offline.at(i).first % 3 == 0);
181*387f9dfdSAndroid Build Coastguard Worker 
182*387f9dfdSAndroid Build Coastguard Worker       // check value
183*387f9dfdSAndroid Build Coastguard Worker       for (size_t cpu = 0; cpu < ncpus; cpu++) {
184*387f9dfdSAndroid Build Coastguard Worker         REQUIRE(offline.at(i).second.at(cpu) == cpu * offline.at(i).first);
185*387f9dfdSAndroid Build Coastguard Worker       }
186*387f9dfdSAndroid Build Coastguard Worker     }
187*387f9dfdSAndroid Build Coastguard Worker 
188*387f9dfdSAndroid Build Coastguard Worker     // clear table
189*387f9dfdSAndroid Build Coastguard Worker     t.clear_table_non_atomic();
190*387f9dfdSAndroid Build Coastguard Worker     REQUIRE(t.get_table_offline().size() == 0);
191*387f9dfdSAndroid Build Coastguard Worker   }
192*387f9dfdSAndroid Build Coastguard Worker }
193*387f9dfdSAndroid Build Coastguard Worker #endif
194