aboutsummaryrefslogtreecommitdiffstats
path: root/src/tests/tests.h
blob: 14ec5a17b0769f74e3738f63e3c50b15199cab3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
* (C) 2014,2015 Jack Lloyd
* (C) 2015 Simon Warta (Kullo GmbH)
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#ifndef BOTAN_TESTS_H__
#define BOTAN_TESTS_H__

#include <botan/build.h>
#include <botan/rng.h>
#include <functional>
#include <istream>
#include <map>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>

Botan::RandomNumberGenerator& test_rng();

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);

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);

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);

size_t run_tests_in_dir(const std::string& dir, std::function<size_t (const std::string&)> fn);

// Run a list of tests
typedef std::function<size_t ()> test_fn;

size_t run_tests(const std::vector<std::pair<std::string, test_fn>>& tests);
void test_report(const std::string& name, size_t ran, size_t failed);

class Test_State
   {
   public:
      void started(const std::string& /*msg*/) { m_tests_run++; }

      void test_ran(const char* msg);

      void failure(const char* test, const std::string& what_failed)
         {
         std::cout << "FAIL " << test << " " << what_failed << "\n";
         m_tests_failed++;
         }

      size_t ran() const { return m_tests_run; }
      size_t failed() const { return m_tests_failed; }
   private:
      size_t m_tests_run = 0, m_tests_failed = 0;
   };

#define BOTAN_CONFIRM_NOTHROW(block) do {                              \
   try { block }                                                        \
   catch(std::exception& e) {                                           \
      _test.failure(BOTAN_CURRENT_FUNCTION, e.what());  \
   } } while(0)                                                         \

#define BOTAN_TEST(lhs, rhs, msg) do {                                     \
   _test.started(msg);                                                  \
   BOTAN_CONFIRM_NOTHROW({                                              \
      const auto lhs_val = lhs;                                         \
      const auto rhs_val = rhs;                                         \
      const bool cmp = lhs_val == rhs_val;                              \
      if(!cmp)                                                          \
         {                                                              \
         std::ostringstream fmt;                                        \
         fmt << "expr '" << #lhs << " == " << #rhs << "' false, "       \
             << "actually " << lhs_val << " " << rhs_val                \
             << " (" << msg << ")";                                     \
         _test.failure(BOTAN_CURRENT_FUNCTION, fmt.str()); \
         }                                                              \
      });                                                               \
   } while(0)

#define BOTAN_CONFIRM(expr, msg) do {                                     \
   _test.started(msg);                                                  \
   BOTAN_CONFIRM_NOTHROW({                                              \
      const bool expr_val = expr;                                         \
      if(!expr_val)                                                     \
         {                                                              \
         std::ostringstream fmt;                                        \
         fmt << "expr '" << #expr << " false (" << msg << ")";           \
         _test.failure(BOTAN_CURRENT_FUNCTION, fmt.str());              \
         }                                                              \
      });                                                               \
   } while(0)

#define BOTAN_TEST_CASE(name, descr, block) size_t test_ ## name() {     \
   Test_State _test;                                                    \
   BOTAN_CONFIRM_NOTHROW(block);                                           \
   test_report(descr, _test.ran(), _test.failed());                     \
   return _test.failed();                                   \
   }

//#define TEST(expr, msg) do { if(!(expr)) { ++fails; std::cout << msg; } while(0)

#define TEST_DATA_DIR     "src/tests/data"
#define TEST_DATA_DIR_PK  "src/tests/data/pubkey"
#define TEST_DATA_DIR_ECC "src/tests/data/ecc"

#define TEST_OUTDATA_DIR  "src/tests/outdata"

int test_main(int argc, char* argv[]);

// Tests using reader framework above
size_t test_block();
size_t test_stream();
size_t test_hash();
size_t test_mac();
size_t test_modes();
size_t test_rngs();
size_t test_pbkdf();
size_t test_kdf();
size_t test_aead();
size_t test_transform();

size_t test_rsa();
size_t test_rw();
size_t test_dsa();
size_t test_nr();
size_t test_dh();
size_t test_dlies();
size_t test_elgamal();
size_t test_ecc_pointmul();
size_t test_ecc_random();
size_t test_ecdsa();
size_t test_gost_3410();
size_t test_curve25519();
size_t test_mceliece();

// One off tests
size_t test_ocb();
size_t test_keywrap();
size_t test_bcrypt();
size_t test_passhash9();
size_t test_cryptobox();
size_t test_tss();
size_t test_rfc6979();

size_t test_pk_keygen();

size_t test_bigint();

size_t test_ecc_unit();
size_t test_ecc_randomized();
size_t test_ecdsa_unit();
size_t test_ecdh_unit();

size_t test_x509();
size_t test_cvc();

size_t test_tls();

size_t test_nist_x509();

size_t test_srp6();
size_t test_compression();

size_t test_fuzzer();

#define SKIP_TEST(testname) \
   size_t test_ ## testname() {                                    \
      std::cout << "Skipping tests: " << # testname  << std::endl; \
      return 0; \
   } \

/*
 * Warn if a test requires loading more modules than necessary to build
 * the lib. E.g.
 *    $ ./configure.py --no-autoload --enable-modules='ocb'
 *    $ make
 *    $ ./botan-test ocb
 * warns the user whereas 
 *    $ ./configure.py --no-autoload --enable-modules='ocb,aes'
 *    $ make
 *    $ ./botan-test ocb
 * runs the test.
 */
#define UNTESTED_WARNING(testname) \
   size_t test_ ## testname() {                                       \
      std::cout << "Skipping tests: " << # testname << std::endl;     \
      std::cout << "WARNING: " << # testname << " has been compiled " \
                << "but is not tested due to other missing modules."  \
                << std::endl; \
      return 0; \
   } \

#endif