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

randombit / botan / 14837041228

05 May 2025 01:00PM UTC coverage: 91.309% (+0.1%) from 91.2%
14837041228

push

github

web-flow
Merge pull request #4851 from randombit/jack/fix-simd-4x32

Fix SIMD_4X32 tests

96201 of 105358 relevant lines covered (91.31%)

12878359.91 hits per line

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

74.76
/src/tests/runner/test_runner.cpp
1
/*
2
* (C) 2017 Jack Lloyd
3
* (C) 2022 René Meusel, Rohde & Schwarz Cybersecurity
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include "../tests.h"
9

10
#include "test_runner.h"
11
#include "test_stdout_reporter.h"
12
#include "test_xml_reporter.h"
13

14
#include <botan/version.h>
15
#include <botan/internal/loadstor.h>
16

17
#if defined(BOTAN_HAS_CPUID)
18
   #include <botan/internal/cpuid.h>
19
#endif
20

21
#if defined(BOTAN_HAS_THREAD_UTILS)
22
   #include <botan/internal/rwlock.h>
23
   #include <botan/internal/thread_pool.h>
24
#endif
25

26
#include <shared_mutex>
27

28
namespace Botan_Tests {
29

30
Test_Runner::Test_Runner(std::ostream& out) : m_output(out) {}
1✔
31

32
Test_Runner::~Test_Runner() = default;
1✔
33

34
bool Test_Runner::run(const Test_Options& opts) {
1✔
35
   if(!opts.no_stdout()) {
1✔
36
      m_reporters.emplace_back(std::make_unique<StdoutReporter>(opts, output()));
2✔
37
   }
38
   if(!opts.xml_results_dir().empty()) {
1✔
39
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
40
      m_reporters.emplace_back(std::make_unique<XmlReporter>(opts, opts.xml_results_dir()));
2✔
41
#else
42
      output() << "Generating test report files is not supported on this platform\n";
43
#endif
44
   }
45

46
   auto req = Botan_Tests::Test::filter_registered_tests(opts.requested_tests(), opts.skip_tests());
1✔
47

48
   // TODO: Test runner should not be aware of certain test's environmental requirements.
49
   if(opts.pkcs11_lib().empty()) {
1✔
50
      // do not run pkcs11 tests by default unless pkcs11-lib set
51
      for(auto iter = req.begin(); iter != req.end();) {
×
52
         if((*iter).find("pkcs11") != std::string::npos) {
×
53
            iter = req.erase(iter);
×
54
         } else {
55
            ++iter;
×
56
         }
57
      }
58
   }
59

60
   if(req.empty()) {
1✔
61
      throw Test_Error("No tests to run");
×
62
   }
63

64
   std::vector<uint8_t> seed = Botan::hex_decode(opts.drbg_seed());
1✔
65
   if(seed.empty()) {
1✔
66
      const uint64_t ts = Botan_Tests::Test::timestamp();
1✔
67
      seed.resize(8);
1✔
68
      Botan::store_be(ts, seed.data());
1✔
69
   }
70

71
   for(auto& reporter : m_reporters) {
3✔
72
#if defined(BOTAN_HAS_CPUID)
73
      const std::string cpuid = Botan::CPUID::to_string();
2✔
74
      if(!cpuid.empty()) {
2✔
75
         reporter->set_property("CPU flags", cpuid);
4✔
76
      }
77
#endif
78

79
      if(!opts.pkcs11_lib().empty()) {
2✔
80
         reporter->set_property("pkcs11 library", opts.pkcs11_lib());
4✔
81
      }
82

83
      if(!opts.provider().empty()) {
2✔
84
         reporter->set_property("provider", opts.provider());
×
85
      }
86

87
      reporter->set_property("drbg_seed", Botan::hex_encode(seed));
4✔
88
   }
2✔
89

90
   Botan_Tests::Test::set_test_options(opts);
1✔
91

92
   for(size_t i = 0; i != opts.test_runs(); ++i) {
2✔
93
      Botan_Tests::Test::set_test_rng_seed(seed, i);
1✔
94

95
      for(const auto& reporter : m_reporters) {
3✔
96
         reporter->next_test_run();
2✔
97
      }
98

99
      const bool passed =
1✔
100
         (opts.test_threads() == 1) ? run_tests(req) : run_tests_multithreaded(req, opts.test_threads());
1✔
101

102
      for(const auto& reporter : m_reporters) {
3✔
103
         reporter->render();
2✔
104
      }
105

106
      if(!passed) {
1✔
107
         return false;
108
      }
109
   }
110

111
   return true;
112
}
1✔
113

114
namespace {
115

116
std::vector<Test::Result> run_a_test(const std::string& test_name) {
404✔
117
   std::vector<Test::Result> results;
404✔
118

119
   try {
404✔
120
#if defined(BOTAN_HAS_CPUID) && defined(BOTAN_HAS_SIMD_4X32)
121
      if(test_name == "simd_4x32" && Botan::CPUID::has(Botan::CPUID::Feature::SIMD_4X32) == false) {
404✔
122
         results.push_back(Test::Result::Note(test_name, "SIMD 4x32 not available on this platform"));
×
123
         return results;
×
124
      }
125
#endif
126

127
      if(std::unique_ptr<Test> test = Test::get_test(test_name)) {
404✔
128
         std::vector<Test::Result> test_results = test->run();
404✔
129
         for(auto& result : test_results) {
50,056✔
130
            if(!result.code_location() && test->registration_location()) {
49,652✔
131
               // If a test result has no specific code location associated to it,
132
               // we fall back to the test case's registration location.
133
               result.set_code_location(test->registration_location().value());
49,652✔
134
            }
135
         }
136
         results.insert(results.end(), test_results.begin(), test_results.end());
404✔
137
      } else {
404✔
138
         results.push_back(Test::Result::Note(test_name, "Test missing or unavailable"));
×
139
      }
404✔
140
   } catch(std::exception& e) {
×
141
      results.push_back(Test::Result::Failure(test_name, e.what()));
×
142
   } catch(...) {
×
143
      results.push_back(Test::Result::Failure(test_name, "unknown exception"));
×
144
   }
×
145

146
   return results;
147
}
×
148

149
bool all_passed(const std::vector<Test::Result>& results) {
404✔
150
   return std::all_of(results.begin(), results.end(), [](const auto& r) { return r.tests_failed() == 0; });
12,809✔
151
}
152

153
}  // namespace
154

155
bool Test_Runner::run_tests_multithreaded(const std::vector<std::string>& tests_to_run, size_t test_threads) {
1✔
156
   // If 0 then we let thread pool select the count
157
   BOTAN_ASSERT_NOMSG(test_threads != 1);
1✔
158

159
#if !defined(BOTAN_HAS_THREAD_UTILS)
160
   output() << "Running tests in multiple threads not enabled in this build\n";
161
   return run_tests(tests_to_run);
162

163
#else
164
   Botan::Thread_Pool pool(test_threads);
1✔
165
   Botan::RWLock rwlock;
1✔
166

167
   std::vector<std::future<std::vector<Test::Result>>> fut_results;
1✔
168

169
   auto run_test_exclusive = [&](const std::string& test_name) {
22✔
170
      std::unique_lock lk(rwlock);
21✔
171
      return run_a_test(test_name);
21✔
172
   };
21✔
173

174
   auto run_test_shared = [&](const std::string& test_name) {
384✔
175
      std::shared_lock lk(rwlock);
383✔
176
      return run_a_test(test_name);
383✔
177
   };
383✔
178

179
   for(const auto& test_name : tests_to_run) {
405✔
180
      if(Test::test_needs_serialization(test_name)) {
404✔
181
         fut_results.push_back(pool.run(run_test_exclusive, test_name));
42✔
182
      } else {
183
         fut_results.push_back(pool.run(run_test_shared, test_name));
766✔
184
      }
185
   }
186

187
   bool passed = true;
188
   for(size_t i = 0; i != fut_results.size(); ++i) {
405✔
189
      for(auto& reporter : m_reporters) {
1,212✔
190
         reporter->waiting_for_next_results(tests_to_run[i]);
808✔
191
      }
192
      const auto results = fut_results[i].get();
404✔
193
      for(auto& reporter : m_reporters) {
1,212✔
194
         reporter->record(tests_to_run[i], results);
808✔
195
      }
196
      passed &= all_passed(results);
404✔
197
   }
404✔
198

199
   pool.shutdown();
1✔
200

201
   return passed;
1✔
202
#endif
203
}
2✔
204

205
bool Test_Runner::run_tests(const std::vector<std::string>& tests_to_run) {
×
206
   bool passed = true;
×
207
   for(const auto& test_name : tests_to_run) {
×
208
      for(auto& reporter : m_reporters) {
×
209
         reporter->waiting_for_next_results(test_name);
×
210
      }
211
      const auto results = run_a_test(test_name);
×
212

213
      for(auto& reporter : m_reporters) {
×
214
         reporter->record(test_name, results);
×
215
      }
216
      passed &= all_passed(results);
×
217
   }
×
218

219
   return passed;
×
220
}
221

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