/* * Test Driver for Botan * * This file is in the public domain */ #include #include #include #include #include #include #include #include /* 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++ 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 #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 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 bool test(const char* type, u32bit digits, bool is_signed) { bool passed = true; if(std::numeric_limits::is_specialized == false) { std::cout << "WARNING: Could not check parameters of " << type << " in std::numeric_limits" << std::endl; return true; } if(std::numeric_limits::digits != digits && digits != 0) { std::cout << "ERROR: numeric_limits<" << type << ">::digits != " << digits << std::endl; passed = false; } if(std::numeric_limits::is_signed != is_signed) { std::cout << "ERROR: numeric_limits<" << type << ">::is_signed != " << std::boolalpha << is_signed << std::endl; passed = false; } if(std::numeric_limits::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", 8, false); passed = passed && test("u16bit", 16, false); passed = passed && test("u32bit", 32, false); passed = passed && test("u64bit", 64, false); passed = passed && test("s32bit", 31, true); passed = passed && test("word", 0, false); #endif if(!passed) { std::cout << "Important settings in types.h are wrong. Please fix " "and recompile." << std::endl; std::exit(1); } }