diff options
Diffstat (limited to 'checks/check.cpp')
-rw-r--r-- | checks/check.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/checks/check.cpp b/checks/check.cpp new file mode 100644 index 000000000..81bb92220 --- /dev/null +++ b/checks/check.cpp @@ -0,0 +1,262 @@ +/* + * Test Driver for Botan + * + * This file is in the public domain + */ + +#include <vector> +#include <string> + +#include <iostream> +#include <cstdlib> +#include <cstring> +#include <exception> + +#include <botan/botan.h> +#include <botan/mp_types.h> + +/* Flag to use engine(s) for PK operations, if available */ +#define USE_ENGINES 0 + +using namespace Botan_types; + +/* Not on by default as many compilers (including egcs and gcc 2.95.x) + * do not have the C++ <limits> header. + * + * At *some* point all OSes will have a reasonably recent GCC, but right now + * GCC 2.95.x is the most recent compiler for a number of systems, including + * OpenBSD, QNX, and BeOS. + * + */ +//#define TEST_TYPES + +#if defined(TEST_TYPES) + #include <limits> +#endif + +const std::string VALIDATION_FILE = "checks/validate.dat"; +const std::string BIGINT_VALIDATION_FILE = "checks/mp_valid.dat"; +const std::string PK_VALIDATION_FILE = "checks/pk_valid.dat"; +const std::string EXPECTED_FAIL_FILE = "checks/fail.dat"; + +void benchmark(const std::string&, bool html, double seconds); +void bench_pk(const std::string&, bool html, double seconds); +u32bit bench_algo(const std::string&); +int validate(); +void print_help(double); + +int main(int argc, char* argv[]) + { + try { + +#if 0 + // Make sure we can repeatedly init/shutdown without problems + for(u32bit j = 0; j != 3; j++) + { + Botan::Init::initialize(); + Botan::Init::deinitialize(); + } +#endif + + std::string init_flags = ""; + if(USE_ENGINES) + init_flags += " use_engines"; + + Botan::LibraryInitializer init(init_flags); + bool html = false; // default to text output + double seconds = 1.5; + + std::vector<std::string> args; + for(int j = 1; j != argc; j++) + args.push_back(argv[j]); + + if(!args.size()) { print_help(seconds); return 2; } + + for(u32bit j = 0; j != args.size(); j++) + { + if(args[j] == "--help") { print_help(seconds); return 1; } + if(args[j] == "--html") html = true; + if(args[j] == "--bench-algo") + { + if(j != args.size() - 1) + { + u32bit found = bench_algo(args[j+1]); + if(!found) // maybe it's a PK algorithm + bench_pk(args[j+1], false, seconds); + } + else + { + std::cout << "Option --bench-algo needs an argument\n"; + return 2; + } + } + if(args[j] == "--seconds") + { + if(j != args.size() - 1) // another arg remains + { + seconds = std::atof(args[j+1].c_str()); + // sanity check; we allow zero for testing porpoises + if((seconds < 0.1 || seconds > 30) && seconds != 0) + { + std::cout << "Invalid argument to --seconds\n"; + return 2; + } + } + else + { + std::cout << "Option --seconds needs an argument\n"; + return 2; + } + } + } + + for(u32bit j = 0; j != args.size(); j++) + { + if(args[j] == "--validate") return validate(); + if(args[j] == "--benchmark") benchmark("All", html, seconds); + if(args[j] == "--bench-all") benchmark("All", html, seconds); + if(args[j] == "--bench-block") + benchmark("Block Cipher", html, seconds); + if(args[j] == "--bench-mode") + benchmark("Cipher Mode", html, seconds); + if(args[j] == "--bench-stream") + benchmark("Stream Cipher", html, seconds); + if(args[j] == "--bench-hash") benchmark("Hash", html, seconds); + if(args[j] == "--bench-mac") benchmark("MAC", html, seconds); + if(args[j] == "--bench-rng") benchmark("RNG", html, seconds); + if(args[j] == "--bench-pk") bench_pk("All", html, seconds); + } + } + catch(Botan::Exception& e) + { + std::cout << "Exception caught:\n " << e.what() << std::endl; + return 1; + } + catch(std::exception& e) + { + std::cout << "Standard library exception caught:\n " + << e.what() << std::endl; + return 1; + } + catch(...) + { + std::cout << "Unknown exception caught." << std::endl; + return 1; + } + + return 0; + } + +void print_help(double seconds) + { + std::cout << Botan::version_string() << " test driver" << std::endl + << "Usage:\n" + << " --validate: Check test vectors\n" + << " --benchmark: Benchmark everything\n" + << " --bench-{block,mode,stream,hash,mac,rng,pk}:\n" + << " Benchmark only algorithms of a particular type\n" + << " --html: Produce HTML output for benchmarks\n" + << " --seconds n: Benchmark for n seconds (default is " + << seconds << ")\n" + << " --help: Print this message\n"; + } + +int validate() + { + void test_types(); + u32bit do_validation_tests(const std::string&, bool = true); + u32bit do_bigint_tests(const std::string&); + u32bit do_pk_validation_tests(const std::string&); + + std::cout << "Beginning validation tests..." << std::endl; + + test_types(); + u32bit errors = 0; + try { + errors += do_validation_tests(VALIDATION_FILE); + errors += do_validation_tests(EXPECTED_FAIL_FILE, false); + errors += do_bigint_tests(BIGINT_VALIDATION_FILE); + errors += do_pk_validation_tests(PK_VALIDATION_FILE); + } + catch(Botan::Exception& e) + { + std::cout << "Exception caught: " << e.what() << std::endl; + return 1; + } + catch(std::exception& e) + { + std::cout << "Standard library exception caught: " + << e.what() << std::endl; + return 1; + } + catch(...) + { + std::cout << "Unknown exception caught." << std::endl; + return 1; + } + + if(errors) + { + std::cout << errors << " test" << ((errors == 1) ? "" : "s") + << " failed." << std::endl; + return 1; + } + + std::cout << "All tests passed!" << std::endl; + return 0; + } + +#if defined(TEST_TYPES) +template<typename T> +bool test(const char* type, u32bit digits, bool is_signed) + { + bool passed = true; + if(std::numeric_limits<T>::is_specialized == false) + { + std::cout << "WARNING: Could not check parameters of " << type + << " in std::numeric_limits" << std::endl; + return true; + } + + if(std::numeric_limits<T>::digits != digits && digits != 0) + { + std::cout << "ERROR: numeric_limits<" << type << ">::digits != " + << digits << std::endl; + passed = false; + } + if(std::numeric_limits<T>::is_signed != is_signed) + { + std::cout << "ERROR: numeric_limits<" << type << ">::is_signed != " + << std::boolalpha << is_signed << std::endl; + passed = false; + } + if(std::numeric_limits<T>::is_integer == false) + { + std::cout << "ERROR: numeric_limits<" << type + << ">::is_integer == false " << std::endl; + passed = false; + } + return passed; + } +#endif + +void test_types() + { + bool passed = true; + +#if defined(TEST_TYPES) + passed = passed && test<byte >("byte", 8, false); + passed = passed && test<u16bit>("u16bit", 16, false); + passed = passed && test<u32bit>("u32bit", 32, false); + passed = passed && test<u64bit>("u64bit", 64, false); + passed = passed && test<s32bit>("s32bit", 31, true); + passed = passed && test<Botan::word>("word", 0, false); +#endif + + if(!passed) + { + std::cout << "Important settings in types.h are wrong. Please fix " + "and recompile." << std::endl; + std::exit(1); + } + } |