aboutsummaryrefslogtreecommitdiffstats
path: root/src/tests/tests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/tests.cpp')
-rw-r--r--src/tests/tests.cpp884
1 files changed, 643 insertions, 241 deletions
diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp
index 61378b1a2..704ff36a8 100644
--- a/src/tests/tests.cpp
+++ b/src/tests/tests.cpp
@@ -5,324 +5,726 @@
*/
#include "tests.h"
-#include <iostream>
-#include <fstream>
-#include <botan/auto_rng.h>
+
+#include <sstream>
+#include <iomanip>
+#include <botan/hex.h>
#include <botan/internal/filesystem.h>
+#include <botan/internal/bit_ops.h>
-#define CATCH_CONFIG_RUNNER
-#define CATCH_CONFIG_CONSOLE_WIDTH 60
-#define CATCH_CONFIG_COLOUR_NONE
-#include "catchy/catch.hpp"
+namespace Botan_Tests {
-#if defined(BOTAN_HAS_SYSTEM_RNG)
- #include <botan/system_rng.h>
-#endif
+Test::Registration::Registration(const std::string& name, Test* test)
+ {
+ if(Test::global_registry().count(name) == 0)
+ {
+ Test::global_registry().insert(std::make_pair(name, std::unique_ptr<Test>(test)));
+ }
+ else
+ {
+ throw std::runtime_error("Duplicate registration of test '" + name + "'");
+ }
+ }
-using namespace Botan;
+void Test::Result::merge(const Result& other)
+ {
+ if(who() != other.who())
+ throw std::runtime_error("Merging tests from different sources");
-Botan::RandomNumberGenerator& test_rng()
+ m_ns_taken += other.m_ns_taken;
+ m_tests_passed += other.m_tests_passed;
+ m_fail_log.insert(m_fail_log.end(), other.m_fail_log.begin(), other.m_fail_log.end());
+ m_log.insert(m_log.end(), other.m_log.begin(), other.m_log.end());
+ }
+
+void Test::Result::test_note(const std::string& note)
{
-#if defined(BOTAN_HAS_SYSTEM_RNG)
- return Botan::system_rng();
-#else
- static Botan::AutoSeeded_RNG rng;
- return rng;
-#endif
+ if(note != "")
+ {
+ m_log.push_back(who() + " " + note);
+ }
}
-size_t run_tests_in_dir(const std::string& dir, std::function<size_t (const std::string&)> fn)
+void Test::Result::note_missing(const std::string& whatever)
{
- size_t fails = 0;
+ static std::set<std::string> s_already_seen;
- try
+ if(s_already_seen.count(whatever) == 0)
{
- auto files = get_files_recursive(dir);
+ test_note("Skipping tests due to missing " + whatever);
+ s_already_seen.insert(whatever);
+ }
+ }
- if (files.empty())
- std::cout << "Warning: No test files found in '" << dir << "'" << std::endl;
+bool Test::Result::test_throws(const std::string& what, std::function<void ()> fn)
+ {
+ try {
+ fn();
+ return test_failure(what + " failed to throw expected exception");
+ }
+ catch(std::exception& e)
+ {
+ return test_success(what + " threw exception " + e.what());
+ }
+ catch(...)
+ {
+ return test_success(what + " threw unknown exception");
+ }
+ }
- for(const auto file: files)
- fails += fn(file);
+bool Test::Result::test_success(const std::string& note)
+ {
+ if(Test::log_success())
+ {
+ test_note(note);
}
- catch(No_Filesystem_Access)
+ ++m_tests_passed;
+ return true;
+ }
+
+bool Test::Result::test_failure(const char* what, const char* error)
+ {
+ return test_failure(who() + " " + what + " with error " + error);
+ }
+
+void Test::Result::test_failure(const char* what, const uint8_t buf[], size_t buf_len)
+ {
+ test_failure(who() + ": " + what +
+ " buf len " + std::to_string(buf_len) +
+ " value " + Botan::hex_encode(buf, buf_len));
+ }
+
+bool Test::Result::test_failure(const std::string& err)
+ {
+ m_fail_log.push_back(err);
+ return false;
+ }
+
+bool Test::Result::test_ne(const char* what,
+ const uint8_t produced[], size_t produced_len,
+ const uint8_t expected[], size_t expected_len)
+ {
+ if(produced_len == expected_len && Botan::same_mem(produced, expected, expected_len))
+ return test_failure(who() + ":" + what + " produced matching");
+ return test_success();
+ }
+
+bool Test::Result::test_eq(const char* producer, const char* what,
+ const uint8_t produced[], size_t produced_size,
+ const uint8_t expected[], size_t expected_size)
+ {
+ if(produced_size == expected_size && Botan::same_mem(produced, expected, expected_size))
+ return test_success();
+
+ std::ostringstream err;
+
+ err << who();
+
+ if(producer)
{
- std::cout << "Warning: No filesystem access available to read test files in '" << dir << "'" << std::endl;
+ err << " producer '" << producer << "'";
}
- return fails;
+ err << " unexpected result";
+
+ if(what)
+ {
+ err << " for " << what;
+ }
+
+ if(produced_size != expected_size)
+ {
+ err << " produced " << produced_size << " bytes expected " << expected_size;
+ }
+
+ std::vector<uint8_t> xor_diff(std::min(produced_size, expected_size));
+ size_t bits_different = 0;
+
+ for(size_t i = 0; i != xor_diff.size(); ++i)
+ {
+ xor_diff[i] = produced[i] ^ expected[i];
+ bits_different += Botan::hamming_weight(xor_diff[i]);
+ }
+
+ err << "Produced: " << Botan::hex_encode(produced, produced_size) << "\n"
+ << "Expected: " << Botan::hex_encode(expected, expected_size);
+
+ if(bits_different > 0)
+ {
+ err << "\nXOR Diff: " << Botan::hex_encode(xor_diff)
+ << " (" << bits_different << " bits different)";
+ }
+
+ return test_failure(err.str());
+ }
+
+bool Test::Result::test_eq(const char* what, const std::string& produced, const std::string& expected)
+ {
+ return test_is_eq(what, produced, expected);
+ }
+
+bool Test::Result::test_eq(const char* what, const char* produced, const char* expected)
+ {
+ return test_is_eq(what, std::string(produced), std::string(expected));
}
-size_t run_tests(const std::vector<std::pair<std::string, test_fn>>& tests)
+bool Test::Result::test_eq(const char* what, size_t produced, size_t expected)
{
- size_t fails = 0;
+ return test_is_eq(what, produced, expected);
+ }
- for(const auto& row : tests)
+bool Test::Result::test_lt(const char* what, size_t produced, size_t expected)
+ {
+ if(produced >= expected)
{
- auto name = row.first;
- auto test = row.second;
- try
- {
- fails += test();
- }
- catch(std::exception& e)
- {
- std::cout << name << ": Exception escaped test: " << e.what() << std::endl;
- ++fails;
- }
- catch(...)
- {
- std::cout << name << ": Exception escaped test" << std::endl;
- ++fails;
- }
+ std::ostringstream err;
+ err << m_who;
+ if(what)
+ err << " " << what;
+ err << " unexpected result " << produced << " >= " << expected;
+ return test_failure(err.str());
}
- // Summary for test suite
- std::cout << "===============" << std::endl;
- test_report("Tests", 0, fails);
+ return test_success();
+ }
+
+bool Test::Result::test_gte(const char* what, size_t produced, size_t expected)
+ {
+ if(produced < expected)
+ {
+ std::ostringstream err;
+ err << m_who;
+ if(what)
+ err << " " << what;
+ err << " unexpected result " << produced << " < " << expected;
+ return test_failure(err.str());
+ }
- return fails;
+ return test_success();
}
-void test_report(const std::string& name, size_t ran, size_t failed)
+#if defined(BOTAN_HAS_BIGINT)
+bool Test::Result::test_eq(const char* what, const BigInt& produced, const BigInt& expected)
{
- std::cout << name;
+ return test_is_eq(what, produced, expected);
+ }
- if(ran > 0)
- std::cout << " " << ran << " tests";
+bool Test::Result::test_ne(const char* what, const BigInt& produced, const BigInt& expected)
+ {
+ if(produced != expected)
+ return test_success();
- if(failed)
- std::cout << " " << failed << " FAILs" << std::endl;
- else
- std::cout << " all ok" << std::endl;
+ std::ostringstream err;
+ err << who() << " " << what << " produced " << produced << " prohibited value";
+ return test_failure(err.str());
}
+#endif
-size_t run_tests_bb(std::istream& src,
- const std::string& name_key,
- const std::string& output_key,
- bool clear_between_cb,
- std::function<size_t (std::map<std::string, std::string>)> cb)
+#if defined(BOTAN_HAS_EC_CURVE_GFP)
+bool Test::Result::test_eq(const char* what, const Botan::PointGFp& a, const Botan::PointGFp& b)
{
- if(!src.good())
+ //return test_is_eq(what, a, b);
+ if(a == b)
+ return test_success();
+
+ std::ostringstream err;
+ err << who() << " " << what << " a=(" << a.get_affine_x() << "," << a.get_affine_y() << ")"
+ << " b=(" << b.get_affine_x() << "," << b.get_affine_y();
+ return test_failure(err.str());
+ }
+#endif
+
+bool Test::Result::test_eq(const char* what, bool produced, bool expected)
+ {
+ return test_is_eq(what, produced, expected);
+ }
+
+bool Test::Result::test_rc_ok(const char* what, int rc)
+ {
+ if(rc != 0)
{
- std::cout << "Could not open input file for " << name_key << std::endl;
- return 1;
+ std::ostringstream err;
+ err << m_who;
+ if(what)
+ err << " " << what;
+ err << " unexpectedly failed with error code " << rc;
+ return test_failure(err.str());
}
- std::map<std::string, std::string> vars;
- size_t test_fails = 0, algo_fail = 0;
- size_t test_count = 0, algo_count = 0;
+ return test_success();
+ }
- std::string fixed_name;
+bool Test::Result::test_rc_fail(const char* func, const char* why, int rc)
+ {
+ if(rc == 0)
+ {
+ std::ostringstream err;
+ err << m_who;
+ if(func)
+ err << " call to " << func << " unexpectedly succeeded";
+ if(why)
+ err << " expecting failure because " << why;
+ return test_failure(err.str());
+ }
- while(src.good())
+ return test_success();
+ }
+
+namespace {
+
+std::string format_time(uint64_t ns)
+ {
+ std::ostringstream o;
+
+ if(ns > 1000000000)
+ {
+ o << std::setprecision(2) << std::fixed << ns/1000000000.0 << " sec";
+ }
+ else
{
- std::string line;
- std::getline(src, line);
+ o << std::setprecision(2) << std::fixed << ns/1000000.0 << " msec";
+ }
- if(line == "")
- continue;
+ return o.str();
+ }
- if(line[0] == '#')
- continue;
+}
- if(line[0] == '[' && line[line.size()-1] == ']')
+std::string Test::Result::result_string() const
+ {
+ std::ostringstream report;
+ report << who() << " ran ";
+
+ if(tests_run() == 0)
+ {
+ report << "ZERO";
+ }
+ else
+ {
+ report << tests_run();
+ }
+ report << " tests";
+
+ if(m_ns_taken > 0)
+ {
+ report << " in " << format_time(m_ns_taken);
+ }
+
+ if(tests_failed())
+ {
+ report << " " << tests_failed() << " FAILED";
+ }
+ else
+ {
+ report << " all ok";
+ }
+
+ report << "\n";
+
+ for(size_t i = 0; i != m_fail_log.size(); ++i)
+ {
+ report << "Failure " << (i+1) << ": " << m_fail_log[i] << "\n";
+ }
+
+ if(m_fail_log.size() > 0 || tests_run() == 0)
+ {
+ for(size_t i = 0; i != m_log.size(); ++i)
{
- if(fixed_name != "")
- test_report(fixed_name, algo_count, algo_fail);
-
- test_count += algo_count;
- test_fails += algo_fail;
- algo_count = 0;
- algo_fail = 0;
- fixed_name = line.substr(1, line.size() - 2);
- vars[name_key] = fixed_name;
- continue;
+ report << "Note " << (i+1) << ": " << m_log[i] << "\n";
}
+ }
- const std::string key = line.substr(0, line.find_first_of(' '));
- const std::string val = line.substr(line.find_last_of(' ') + 1, std::string::npos);
+ return report.str();
+ }
- vars[key] = val;
+// static Test:: functions
+//static
+std::map<std::string, std::unique_ptr<Test>>& Test::global_registry()
+ {
+ static std::map<std::string, std::unique_ptr<Test>> g_test_registry;
+ return g_test_registry;
+ }
+
+namespace {
+
+template<typename K, typename V>
+std::set<K> map_keys_as_set(const std::map<K, V>& kv)
+ {
+ std::set<K> s;
+ for(auto&& i : kv)
+ {
+ s.insert(i.first);
+ }
+ return s;
+ }
+
+}
+
+//static
+uint64_t Test::timestamp()
+ {
+ auto now = std::chrono::high_resolution_clock::now().time_since_epoch();
+ return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
+ }
+
+//static
+std::set<std::string> Test::registered_tests()
+ {
+ return map_keys_as_set(Test::global_registry());
+ }
- if(key == name_key)
- fixed_name.clear();
+//static
+Test* Test::get_test(const std::string& test_name)
+ {
+ auto i = Test::global_registry().find(test_name);
+ if(i != Test::global_registry().end())
+ return i->second.get();
+ return nullptr;
+ }
- if(key == output_key)
+//static
+std::vector<Test::Result> Test::run_test(const std::string& test_name, bool fail_if_missing)
+ {
+ std::vector<Test::Result> results;
+
+ try
+ {
+ if(Test* test = get_test(test_name))
{
- //std::cout << vars[name_key] << " " << algo_count << std::endl;
- ++algo_count;
- try
- {
- const size_t fails = cb(vars);
+ std::vector<Test::Result> test_results = test->run();
+ results.insert(results.end(), test_results.begin(), test_results.end());
+ }
+ else
+ {
+ Test::Result result(test_name);
+ if(fail_if_missing)
+ result.test_failure("Test missing or unavailable");
+ else
+ result.test_note("Test missing or unavailable");
+ results.push_back(result);
+ }
+ }
+ catch(std::exception& e)
+ {
+ results.push_back(Test::Result::Failure(test_name, e.what()));
+ }
+ catch(...)
+ {
+ results.push_back(Test::Result::Failure(test_name, "unknown exception"));
+ }
- if(fails)
- {
- std::cout << vars[name_key] << " test " << algo_count << ": " << fails << " failure" << std::endl;
- algo_fail += fails;
- }
- }
- catch(std::exception& e)
- {
- std::cout << vars[name_key] << " test " << algo_count << " failed: " << e.what() << std::endl;
- ++algo_fail;
- }
+ return results;
+ }
- if(clear_between_cb)
- {
- vars.clear();
- vars[name_key] = fixed_name;
- }
+//static
+std::string Test::data_dir(const std::string& what)
+ {
+ return std::string(TEST_DATA_DIR) + "/" + what;
+ }
+
+//static
+std::string Test::data_file(const std::string& what)
+ {
+ return std::string(TEST_DATA_DIR) + "/" + what;
+ }
+
+// static member variables of Test
+Botan::RandomNumberGenerator* Test::m_test_rng = nullptr;
+size_t Test::m_soak_level = 0;
+bool Test::m_log_success = false;
+
+//static
+void Test::setup_tests(size_t soak, bool log_success, Botan::RandomNumberGenerator* rng)
+ {
+ m_soak_level = soak;
+ m_log_success = log_success;
+ m_test_rng = rng;
+ }
+
+//static
+size_t Test::soak_level()
+ {
+ return m_soak_level;
+ }
+
+//static
+bool Test::log_success()
+ {
+ return m_log_success;
+ }
+
+//static
+Botan::RandomNumberGenerator& Test::rng()
+ {
+ if(!m_test_rng)
+ throw std::runtime_error("Test RNG not initialized");
+ return *m_test_rng;
+ }
+
+std::string Test::random_password()
+ {
+ const size_t len = 1 + Test::rng().next_byte() % 32;
+ return Botan::hex_encode(Test::rng().random_vec(len));
+ }
+
+Text_Based_Test::Text_Based_Test(const std::string& data_dir,
+ const std::vector<std::string>& required_keys,
+ const std::vector<std::string>& optional_keys) :
+ m_data_dir(data_dir)
+ {
+ if(required_keys.empty())
+ throw std::runtime_error("Invalid test spec");
+
+ m_required_keys.insert(required_keys.begin(), required_keys.end());
+ m_optional_keys.insert(optional_keys.begin(), optional_keys.end());
+ m_output_key = required_keys.at(required_keys.size() - 1);
+ }
+
+Text_Based_Test::Text_Based_Test(const std::string& algo,
+ const std::string& data_dir,
+ const std::vector<std::string>& required_keys,
+ const std::vector<std::string>& optional_keys) :
+ m_algo(algo),
+ m_data_dir(data_dir)
+ {
+ if(required_keys.empty())
+ throw std::runtime_error("Invalid test spec");
+
+ m_required_keys.insert(required_keys.begin(), required_keys.end());
+ m_optional_keys.insert(optional_keys.begin(), optional_keys.end());
+ m_output_key = required_keys.at(required_keys.size() - 1);
+ }
+
+std::vector<uint8_t> Text_Based_Test::get_req_bin(const VarMap& vars,
+ const std::string& key) const
+ {
+ auto i = vars.find(key);
+ if(i == vars.end())
+ throw std::runtime_error("Test missing variable " + key);
+
+ try
+ {
+ return Botan::hex_decode(i->second);
+ }
+ catch(std::exception& e)
+ {
+ throw std::runtime_error("Test invalid hex input '" + i->second + "'" +
+ + " for key " + key);
}
}
- test_count += algo_count;
- test_fails += algo_fail;
+std::string Text_Based_Test::get_opt_str(const VarMap& vars,
+ const std::string& key, const std::string& def_value) const
- if(fixed_name != "" && (algo_count > 0 || algo_fail > 0))
- test_report(fixed_name, algo_count, algo_fail);
- else
- test_report(name_key, test_count, test_fails);
+ {
+ auto i = vars.find(key);
+ if(i == vars.end())
+ return def_value;
+ return i->second;
+ }
- return test_fails;
+size_t Text_Based_Test::get_req_sz(const VarMap& vars, const std::string& key) const
+ {
+ auto i = vars.find(key);
+ if(i == vars.end())
+ throw std::runtime_error("Test missing variable " + key);
+ return Botan::to_u32bit(i->second);
+ }
+
+size_t Text_Based_Test::get_opt_sz(const VarMap& vars, const std::string& key, const size_t def_value) const
+ {
+ auto i = vars.find(key);
+ if(i == vars.end())
+ return def_value;
+ return Botan::to_u32bit(i->second);
}
-size_t run_tests(const std::string& filename,
- const std::string& name_key,
- const std::string& output_key,
- bool clear_between_cb,
- std::function<std::string (std::map<std::string, std::string>)> cb)
+std::vector<uint8_t> Text_Based_Test::get_opt_bin(const VarMap& vars,
+ const std::string& key) const
{
- std::ifstream vec(filename);
+ auto i = vars.find(key);
+ if(i == vars.end())
+ return std::vector<uint8_t>();
- if(!vec)
+ try
+ {
+ return Botan::hex_decode(i->second);
+ }
+ catch(std::exception& e)
{
- std::cout << "Failure opening " << filename << std::endl;
- return 1;
+ throw std::runtime_error("Test invalid hex input '" + i->second + "'" +
+ + " for key " + key);
}
+ }
- return run_tests(vec, name_key, output_key, clear_between_cb, cb);
+std::string Text_Based_Test::get_req_str(const VarMap& vars, const std::string& key) const
+ {
+ auto i = vars.find(key);
+ if(i == vars.end())
+ throw std::runtime_error("Test missing variable " + key);
+ return i->second;
}
-size_t run_tests(std::istream& src,
- const std::string& name_key,
- const std::string& output_key,
- bool clear_between_cb,
- std::function<std::string (std::map<std::string, std::string>)> cb)
+#if defined(BOTAN_HAS_BIGINT)
+Botan::BigInt Text_Based_Test::get_req_bn(const VarMap& vars,
+ const std::string& key) const
{
- return run_tests_bb(src, name_key, output_key, clear_between_cb,
- [name_key,output_key,cb](std::map<std::string, std::string> vars)
- {
- const std::string got = cb(vars);
- if(got != vars[output_key])
- {
- std::cout << name_key << ' ' << vars[name_key] << " got " << got
- << " expected " << vars[output_key] << std::endl;
- return 1;
- }
- return 0;
- });
+ auto i = vars.find(key);
+ if(i == vars.end())
+ throw std::runtime_error("Test missing variable " + key);
+
+ try
+ {
+ return Botan::BigInt(i->second);
+ }
+ catch(std::exception& e)
+ {
+ throw std::runtime_error("Test invalid bigint input '" + i->second + "' for key " + key);
+ }
+ }
+#endif
+
+std::string Text_Based_Test::get_next_line()
+ {
+ while(true)
+ {
+ if(m_cur == nullptr || m_cur->good() == false)
+ {
+ if(m_srcs.empty())
+ {
+ if(m_first)
+ {
+ std::vector<std::string> fs = Botan::get_files_recursive(m_data_dir);
+
+ if(fs.empty() && m_data_dir.find(".vec") != std::string::npos)
+ {
+ m_srcs.push_back(m_data_dir);
+ }
+ else
+ {
+ m_srcs.assign(fs.begin(), fs.end());
+ }
+
+ m_first = false;
+ }
+ else
+ {
+ return ""; // done
+ }
+ }
+
+ m_cur.reset(new std::ifstream(m_srcs[0]));
+
+ if(!m_cur->good())
+ throw std::runtime_error("Could not open input file '" + m_srcs[0]);
+
+ m_srcs.pop_front();
+ }
+
+ while(m_cur->good())
+ {
+ std::string line;
+ std::getline(*m_cur, line);
+
+ if(line == "")
+ continue;
+
+ if(line[0] == '#')
+ continue;
+
+ return line;
+ }
+ }
}
namespace {
-int help(char* argv0)
+// strips leading and trailing but not internal whitespace
+std::string strip_ws(const std::string& in)
{
- std::cout << "Usage: " << argv0 << " [suite]" << std::endl;
- std::cout << "Suites: all (default), block, hash, bigint, rsa, ecdsa, ..." << std::endl;
- return 1;
+ const char* whitespace = " ";
+
+ const auto first_c = in.find_first_not_of(whitespace);
+ if(first_c == std::string::npos)
+ return "";
+
+ const auto last_c = in.find_last_not_of(whitespace);
+
+ return in.substr(first_c, last_c - first_c + 1);
}
-int test_catchy()
+}
+
+std::vector<Test::Result> Text_Based_Test::run()
{
- // drop arc and arv for now
- int catchy_result = Catch::Session().run();
- if (catchy_result != 0)
+ std::vector<Test::Result> results;
+
+ std::string who;
+ VarMap vars;
+ size_t test_cnt = 0;
+
+ while(true)
{
- std::exit(EXIT_FAILURE);
+ const std::string line = get_next_line();
+ if(line == "") // EOF
+ break;
+
+ if(line[0] == '[' && line[line.size()-1] == ']')
+ {
+ who = line.substr(1, line.size() - 2);
+ test_cnt = 0;
+ continue;
+ }
+
+ const std::string test_id = "test " + std::to_string(test_cnt);
+
+ auto equal_i = line.find_first_of('=');
+
+ if(equal_i == std::string::npos)
+ {
+ results.push_back(Test::Result::Failure(who, "invalid input '" + line + "'"));
+ continue;
+ }
+
+ std::string key = strip_ws(std::string(line.begin(), line.begin() + equal_i - 1));
+ std::string val = strip_ws(std::string(line.begin() + equal_i + 1, line.end()));
+
+ if(m_required_keys.count(key) == 0 && m_optional_keys.count(key) == 0)
+ results.push_back(Test::Result::Failure(who, test_id + " failed unknown key " + key));
+
+ vars[key] = val;
+
+ if(key == m_output_key)
+ {
+ try
+ {
+ ++test_cnt;
+
+ uint64_t start = Test::timestamp();
+ Test::Result result = run_one_test(who, vars);
+ result.set_ns_consumed(Test::timestamp() - start);
+
+ if(result.tests_failed())
+ result.test_note("Test #" + std::to_string(test_cnt) + " failed");
+ results.push_back(result);
+ }
+ catch(std::exception& e)
+ {
+ results.push_back(Test::Result::Failure(who, "test " + std::to_string(test_cnt) + " failed with exception '" + e.what() + "'"));
+ }
+
+ if(clear_between_callbacks())
+ {
+ vars.clear();
+ }
+ }
}
- return 0;
+
+ std::vector<Test::Result> final_tests = run_final_tests();
+ results.insert(results.end(), final_tests.begin(), final_tests.end());
+
+ return results;
}
}
-int main(int argc, char* argv[])
- {
- if(argc != 1 && argc != 2)
- return help(argv[0]);
-
- std::string target = "all";
-
- if(argc == 2)
- target = argv[1];
-
- if(target == "-h" || target == "--help" || target == "help")
- return help(argv[0]);
-
- std::vector<std::pair<std::string, test_fn>> tests;
-
-#define DEF_TEST(test) do { if(target == "all" || target == #test) \
- tests.push_back(std::make_pair(#test, test_ ## test)); \
- } while(0)
-
- // unittesting framework in sub-folder tests/catchy
- DEF_TEST(catchy);
-
- DEF_TEST(block);
- DEF_TEST(modes);
- DEF_TEST(aead);
- DEF_TEST(ocb);
-
- DEF_TEST(stream);
- DEF_TEST(hash);
- DEF_TEST(mac);
- DEF_TEST(pbkdf);
- DEF_TEST(kdf);
- DEF_TEST(keywrap);
- DEF_TEST(transform);
- DEF_TEST(rngs);
- DEF_TEST(passhash9);
- DEF_TEST(bcrypt);
- DEF_TEST(cryptobox);
- DEF_TEST(tss);
- DEF_TEST(rfc6979);
- DEF_TEST(srp6);
-
- DEF_TEST(bigint);
-
- DEF_TEST(rsa);
- DEF_TEST(rw);
- DEF_TEST(dsa);
- DEF_TEST(nr);
- DEF_TEST(dh);
- DEF_TEST(dlies);
- DEF_TEST(elgamal);
- DEF_TEST(ecc_pointmul);
- DEF_TEST(ecdsa);
- DEF_TEST(gost_3410);
- DEF_TEST(curve25519);
- DEF_TEST(gf2m);
- DEF_TEST(mceliece);
- DEF_TEST(mce);
-
- DEF_TEST(ecc_unit);
- DEF_TEST(ecc_randomized);
- DEF_TEST(ecdsa_unit);
- DEF_TEST(ecdh_unit);
- DEF_TEST(pk_keygen);
- DEF_TEST(cvc);
- DEF_TEST(x509);
- DEF_TEST(x509_x509test);
- DEF_TEST(nist_x509);
- DEF_TEST(tls);
- DEF_TEST(compression);
- DEF_TEST(fuzzer);
-
- if(tests.empty())
- {
- std::cout << "No tests selected by target '" << target << "'" << std::endl;
- return 1;
- }
-
- return run_tests(tests);
- }