• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 13212092742

08 Feb 2025 12:33AM UTC coverage: 91.658% (-0.004%) from 91.662%
13212092742

push

github

web-flow
Merge pull request #4642 from randombit/jack/target-info-header

Add internal target_info.h header

94839 of 103471 relevant lines covered (91.66%)

11295178.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.71
/src/tests/test_os_utils.cpp
1
/*
2
* Testing operating system specific wrapper code
3
* (C) 2017 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include "tests.h"
9

10
#if defined(BOTAN_HAS_OS_UTILS)
11
   #include <botan/internal/os_utils.h>
12
   #include <botan/internal/target_info.h>
13
#endif
14

15
namespace Botan_Tests {
16

17
#if defined(BOTAN_HAS_OS_UTILS)
18

19
namespace {
20

21
/*
22
uint32_t get_process_id();
23
uint64_t get_cpu_cycle_counter();
24
uint64_t get_system_timestamp_ns();
25
size_t get_memory_locking_limit();
26
void* allocate_locked_pages(size_t length);
27
void free_locked_pages(void* ptr, size_t length);
28
int run_cpu_instruction_probe(std::function<int ()> probe_fn);
29
*/
30

31
class OS_Utils_Tests final : public Test {
×
32
   public:
33
      std::vector<Test::Result> run() override {
1✔
34
         std::vector<Test::Result> results;
1✔
35

36
         results.push_back(test_get_process_id());
2✔
37
         results.push_back(test_get_cpu_cycle_counter());
2✔
38
         results.push_back(test_get_high_resolution_clock());
2✔
39
         results.push_back(test_get_cpu_numbers());
2✔
40
         results.push_back(test_get_system_timestamp());
2✔
41
         results.push_back(test_memory_locking());
2✔
42
         results.push_back(test_cpu_instruction_probe());
2✔
43

44
         return results;
1✔
45
      }
×
46

47
   private:
48
      static Test::Result test_get_process_id() {
1✔
49
         Test::Result result("OS::get_process_id");
1✔
50

51
         uint32_t pid1 = Botan::OS::get_process_id();
1✔
52
         uint32_t pid2 = Botan::OS::get_process_id();
1✔
53

54
         result.test_eq("PID same across calls", static_cast<size_t>(pid1), static_cast<size_t>(pid2));
1✔
55

56
   #if defined(BOTAN_TARGET_OS_IS_LLVM) || defined(BOTAN_TARGET_OS_IS_NONE)
57
         result.test_eq("PID is expected to be zero on this platform", pid1, size_t(0));
58
   #else
59
         result.test_ne("PID is non-zero on systems with processes", pid1, 0);
1✔
60
   #endif
61

62
         return result;
1✔
63
      }
×
64

65
      static Test::Result test_get_cpu_cycle_counter() {
1✔
66
         const size_t max_trials = 1024;
1✔
67
         const size_t max_repeats = 32;
1✔
68

69
         Test::Result result("OS::get_cpu_cycle_counter");
1✔
70

71
         const uint64_t proc_ts1 = Botan::OS::get_cpu_cycle_counter();
1✔
72

73
         if(proc_ts1 == 0) {
1✔
74
            const uint64_t proc_ts2 = Botan::OS::get_cpu_cycle_counter();
×
75
            result.test_is_eq("Disabled processor timestamp stays at zero", proc_ts1, proc_ts2);
×
76
            return result;
×
77
         }
78

79
         size_t counts = 0;
80
         while(counts < max_trials && (Botan::OS::get_cpu_cycle_counter() == proc_ts1)) {
1✔
81
            ++counts;
×
82
         }
83

84
         result.test_lt("CPU cycle counter eventually changes value", counts, max_repeats);
1✔
85

86
         return result;
1✔
87
      }
×
88

89
      static Test::Result test_get_high_resolution_clock() {
1✔
90
         const size_t max_trials = 1024;
1✔
91
         const size_t max_repeats = 128;
1✔
92

93
         Test::Result result("OS::get_high_resolution_clock");
1✔
94

95
         // TODO better tests
96
         const uint64_t hr_ts1 = Botan::OS::get_high_resolution_clock();
1✔
97
         result.confirm("high resolution timestamp value is never zero", hr_ts1 != 0);
2✔
98

99
         size_t counts = 0;
1✔
100
         while(counts < max_trials && (Botan::OS::get_high_resolution_clock() == hr_ts1)) {
1✔
101
            ++counts;
×
102
         }
103

104
         result.test_lt("high resolution clock eventually changes value", counts, max_repeats);
1✔
105

106
         return result;
1✔
107
      }
×
108

109
      static Test::Result test_get_cpu_numbers() {
1✔
110
         Test::Result result("OS::get_cpu_available");
1✔
111

112
         const size_t ta = Botan::OS::get_cpu_available();
1✔
113

114
         result.test_gte("get_cpu_available is at least 1", ta, 1);
1✔
115

116
         return result;
1✔
117
      }
×
118

119
      static Test::Result test_get_system_timestamp() {
1✔
120
         // TODO better tests
121
         Test::Result result("OS::get_system_timestamp_ns");
1✔
122

123
         uint64_t sys_ts1 = Botan::OS::get_system_timestamp_ns();
1✔
124
         result.confirm("System timestamp value is never zero", sys_ts1 != 0);
2✔
125

126
         // do something that consumes a little time
127
         Botan::OS::get_process_id();
1✔
128

129
         uint64_t sys_ts2 = Botan::OS::get_system_timestamp_ns();
1✔
130

131
         result.confirm("System time moves forward", sys_ts1 <= sys_ts2);
2✔
132

133
         return result;
1✔
134
      }
×
135

136
      static Test::Result test_memory_locking() {
1✔
137
         Test::Result result("OS memory locked pages");
1✔
138

139
         // TODO any tests...
140

141
         return result;
1✔
142
      }
143

144
      static Test::Result test_cpu_instruction_probe() {
1✔
145
         Test::Result result("OS::run_cpu_instruction_probe");
1✔
146

147
         // OS::run_cpu_instruction_probe only implemented for Unix signals or Windows SEH
148

149
         std::function<int()> ok_fn = []() noexcept -> int { return 5; };
1✔
150
         const int run_rc = Botan::OS::run_cpu_instruction_probe(ok_fn);
1✔
151

152
         if(run_rc == -3) {
1✔
153
            result.test_note("run_cpu_instruction_probe not implemented on this platform");
×
154
            return {result};
×
155
         }
156

157
         result.confirm("Correct result returned by working probe fn", run_rc == 5);
2✔
158

159
         std::function<int()> crash_probe;
1✔
160

161
   #if defined(BOTAN_USE_GCC_INLINE_ASM)
162

163
      #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
164
         crash_probe = []() noexcept -> int {
3✔
165
            asm volatile("ud2");
1✔
166
            return 3;
×
167
         };
1✔
168

169
      #elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
170
         //ARM: asm volatile (".word 0xf7f0a000\n");
171
         // illegal instruction in both ARM and Thumb modes
172
         crash_probe = []() noexcept -> int {
173
            asm volatile(".word 0xe7f0def0\n");
174
            return 3;
175
         };
176

177
      #else
178
               /*
179
         PPC: "The instruction with primary opcode 0, when the instruction does not consist
180
         entirely of binary zeros"
181
         Others ?
182
         */
183
      #endif
184

185
   #endif
186

187
         if(crash_probe) {
1✔
188
            const int crash_rc = Botan::OS::run_cpu_instruction_probe(crash_probe);
1✔
189
            result.confirm("Result for function executing undefined opcode", crash_rc < 0);
2✔
190
         }
191

192
         return result;
1✔
193
      }
2✔
194
};
195

196
BOTAN_REGISTER_TEST("utils", "os_utils", OS_Utils_Tests);
197

198
}  // namespace
199

200
#endif
201

202
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc