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

randombit / botan / 20700111013

04 Jan 2026 10:31PM UTC coverage: 90.422% (+0.001%) from 90.421%
20700111013

Pull #5209

github

web-flow
Merge 91140933f into cf0e68e34
Pull Request #5209: Improve support for running tests on Emscripten

101647 of 112414 relevant lines covered (90.42%)

12865807.81 hits per line

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

81.93
/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 {
1✔
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
         const uint32_t pid1 = Botan::OS::get_process_id();
1✔
52
         const 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
         // We can easily test progression; however, testing precision is trickier.
91
         // On very fast machines with very low clock resolution (like the web platform offers),
92
         // it may be necessary to make the call quite a few times to notice any change.
93
         constexpr auto max_trials = 32768;
1✔
94

95
         Test::Result result("OS::get_high_resolution_clock");
1✔
96

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

101
         auto hr_ts2 = Botan::OS::get_high_resolution_clock();
1✔
102
         size_t trials = 0;
103
         while(trials < max_trials) {
1✔
104
            if(hr_ts1 < hr_ts2) {
1✔
105
               break;
106
            }
107

108
            ++trials;
×
109
            hr_ts2 = Botan::OS::get_high_resolution_clock();
×
110
         }
111

112
         result.confirm("high resolution clock eventually changes value", hr_ts1 < hr_ts2);
2✔
113

114
         return result;
1✔
115
      }
×
116

117
      static Test::Result test_get_cpu_numbers() {
1✔
118
         Test::Result result("OS::get_cpu_available");
1✔
119

120
         const size_t ta = Botan::OS::get_cpu_available();
1✔
121

122
         result.test_gte("get_cpu_available is at least 1", ta, 1);
1✔
123

124
         return result;
1✔
125
      }
×
126

127
      static Test::Result test_get_system_timestamp() {
1✔
128
         // TODO better tests
129
         Test::Result result("OS::get_system_timestamp_ns");
1✔
130

131
         const uint64_t sys_ts1 = Botan::OS::get_system_timestamp_ns();
1✔
132
         result.confirm("System timestamp value is never zero", sys_ts1 != 0);
2✔
133

134
         // do something that consumes a little time
135
         Botan::OS::get_process_id();
1✔
136

137
         const uint64_t sys_ts2 = Botan::OS::get_system_timestamp_ns();
1✔
138

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

141
         return result;
1✔
142
      }
×
143

144
      static Test::Result test_memory_locking() {
1✔
145
         Test::Result result("OS memory locked pages");
1✔
146

147
         // TODO any tests...
148

149
         return result;
1✔
150
      }
151

152
      static Test::Result test_cpu_instruction_probe() {
1✔
153
         Test::Result result("OS::run_cpu_instruction_probe");
1✔
154

155
         // OS::run_cpu_instruction_probe is only implemented on systems supporting Unix-style signals
156

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

160
         if(run_rc == -3) {
1✔
161
            result.test_note("run_cpu_instruction_probe not implemented on this platform");
×
162
            return {result};
×
163
         }
164

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

167
         std::function<int()> crash_probe;
1✔
168

169
   #if defined(BOTAN_USE_GCC_INLINE_ASM)
170

171
      #if defined(BOTAN_TARGET_ARCH_IS_X86_FAMILY)
172
         crash_probe = []() noexcept -> int {
3✔
173
            asm volatile("ud2");  // NOLINT(*-no-assembler)
1✔
174
            return 3;
×
175
         };
1✔
176

177
      #elif defined(BOTAN_TARGET_ARCH_IS_ARM_FAMILY)
178
         //ARM: asm volatile (".word 0xf7f0a000\n");
179
         // illegal instruction in both ARM and Thumb modes
180
         crash_probe = []() noexcept -> int {
181
            asm volatile(".word 0xe7f0def0\n");  // NOLINT(*-no-assembler)
182
            return 3;
183
         };
184

185
      #else
186
               /*
187
         PPC: "The instruction with primary opcode 0, when the instruction does not consist
188
         entirely of binary zeros"
189
         Others ?
190
         */
191
      #endif
192

193
   #endif
194

195
         if(crash_probe) {
1✔
196
            const int crash_rc = Botan::OS::run_cpu_instruction_probe(crash_probe);
1✔
197
            result.confirm("Result for function executing undefined opcode", crash_rc < 0);
2✔
198
         }
199

200
         return result;
1✔
201
      }
2✔
202
};
203

204
BOTAN_REGISTER_TEST("utils", "os_utils", OS_Utils_Tests);
205

206
}  // namespace
207

208
#endif
209

210
}  // 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