KleidiAI Coverage Report


Directory: ./
File: test/common/cache.hpp
Date: 2025-10-20 13:18:31
Coverage Exec Excl Total
Lines: 100.0% 23 0 23
Functions: 100.0% 11 0 11
Branches: 63.2% 12 0 19

Line Branch Exec Source
1 //
2 // SPDX-FileCopyrightText: Copyright 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
3 //
4 // SPDX-License-Identifier: Apache-2.0
5 //
6
7 #include <tuple>
8 #include <unordered_map>
9
10 namespace kai::test {
11
12 namespace impl {
13 /// Naive combination of two hash values
14 3729 constexpr size_t hash_combine(size_t lhs, size_t rhs) noexcept {
15 3729 return lhs ^ (rhs << 3);
16 }
17
18 /// Tuple hash recursive case, combines hash of Ith hash with Ith - 1 hash.
19 /// Defaults to last element in tuple
20 template <typename Tuple, std::size_t Index = std::tuple_size<Tuple>::value - 1>
21 struct TupleHash {
22 3729 static size_t combine(const Tuple& tuple) noexcept {
23 using EType = std::tuple_element_t<Index, Tuple>;
24 3729 return hash_combine(
25
3/6
✓ Branch 0 taken 1243 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1243 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1243 times.
✗ Branch 5 not taken.
3729 std::hash<EType>{}(std::get<Index>(tuple)), // hash of current element
26 3729 TupleHash<Tuple, Index - 1>::combine(tuple) // hash of previous elements
27 );
28 }
29 };
30
31 /// TupleHash base case, returns hash of first value
32 template <typename Tuple>
33 struct TupleHash<Tuple, 0> {
34 1243 static size_t combine(const Tuple& tuple) noexcept {
35 using EType = std::tuple_element_t<0, Tuple>;
36
1/2
✓ Branch 0 taken 1243 times.
✗ Branch 1 not taken.
1243 return std::hash<EType>{}(std::get<0>(tuple));
37 }
38 };
39 } // namespace impl
40
41 struct TupleHash {
42 template <typename... Args>
43 1243 std::size_t operator()(const std::tuple<Args...>& tuple) const noexcept {
44 1243 return impl::TupleHash<std::tuple<Args...>>::combine(tuple);
45 }
46 };
47
48 /// Cached reference cache
49 ///
50 /// The user need to specialize and implement the private `generate_reference()` function, which
51 /// will then be used by the cache mechanism to generate cached reference data
52 ///
53 /// template <>
54 /// CacheData ReferenceGenerator<YourTestID, YourTestData>::generate_reference(const YourTestID& k) {
55 /// ...
56 /// }
57 ///
58 /// And then use the `getV()` helper function to retrieve test reference data
59 ///
60 /// const auto& test_data = getV<YourTestID, YourTestData>(test_id);
61 ///
62 /// Notice that current implementation can be quite memory intensive, but the positive tradeoff
63 /// is its ease of use
64 template <typename K, typename V>
65 struct ReferenceGenerator final {
66 1232 static ReferenceGenerator& getRG() {
67
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1231 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1232 static ReferenceGenerator rg;
68 1232 return rg;
69 }
70
71 1232 const V& get_test_reference(const K& test_id) {
72
4/5
✓ Branch 0 taken 1221 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1221 times.
✓ Branch 4 taken 11 times.
2453 if (const auto itr = m_data.find(test_id); itr != end(m_data)) {
73 1221 return itr->second;
74 }
75
76
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 return m_data[test_id] = generate_reference(test_id);
77 1232 }
78
79 private:
80 2 ReferenceGenerator() = default;
81
82 std::unordered_map<K, V, TupleHash> m_data;
83
84 V generate_reference(const K& test_id);
85 };
86
87 /// Main accessor function for retrieving reference test values from test identifier.
88 ///
89 /// This can also be used as a shim between test data creation and usage
90 template <typename K, typename V, typename RG = ReferenceGenerator<K, V>>
91 1232 inline const V& getV(const K& k) {
92 1232 auto& rg = ReferenceGenerator<K, V>::getRG();
93 2464 return rg.get_test_reference(k);
94 1232 }
95
96 }; // namespace kai::test
97