1 /* Copyright (c) 2015, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15 #ifndef OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H 16 #define OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H 17 18 #include <stdint.h> 19 #include <stdio.h> 20 21 #include <string> 22 #include <map> 23 #include <set> 24 #include <vector> 25 26 27 // File-based test framework. 28 // 29 // This module provides a file-based test framework. The file format is based on 30 // that of OpenSSL upstream's evp_test and BoringSSL's aead_test. Each input 31 // file is a sequence of attributes, blocks, and blank lines. 32 // 33 // Each attribute has the form: 34 // 35 // Name = Value 36 // 37 // Either '=' or ':' may be used to delimit the name from the value. Both the 38 // name and value have leading and trailing spaces stripped. 39 // 40 // Blocks are delimited by lines beginning with three hyphens, "---". One such 41 // line begins a block and another ends it. Blocks are intended as a convenient 42 // way to embed PEM data and include their delimiters. 43 // 44 // Outside a block, lines beginning with # are ignored. 45 // 46 // A test is a sequence of one or more attributes followed by a block or blank 47 // line. Blank lines are otherwise ignored. For tests that process multiple 48 // kinds of test cases, the first attribute is parsed out as the test's type and 49 // parameter. Otherwise, attributes are unordered. The first attribute is also 50 // included in the set of attributes, so tests which do not dispatch may ignore 51 // this mechanism. 52 // 53 // Functions in this module freely output to |stderr| on failure. Tests should 54 // also do so, and it is recommended they include the corresponding test's line 55 // number in any output. |PrintLine| does this automatically. 56 // 57 // Each attribute in a test must be consumed. When a test completes, if any 58 // attributes haven't been processed, the framework reports an error. 59 60 61 class FileTest { 62 public: 63 explicit FileTest(const char *path); 64 ~FileTest(); 65 66 // is_open returns true if the file was successfully opened. is_open()67 bool is_open() const { return file_ != nullptr; } 68 69 enum ReadResult { 70 kReadSuccess, 71 kReadEOF, 72 kReadError, 73 }; 74 75 // ReadNext reads the next test from the file. It returns |kReadSuccess| if 76 // successfully reading a test and |kReadEOF| at the end of the file. On 77 // error or if the previous test had unconsumed attributes, it returns 78 // |kReadError|. 79 ReadResult ReadNext(); 80 81 // PrintLine is a variant of printf which prepends the line number and appends 82 // a trailing newline. 83 void PrintLine(const char *format, ...) 84 #ifdef __GNUC__ 85 __attribute__((__format__(__printf__, 2, 3))) 86 #endif 87 ; 88 start_line()89 unsigned start_line() const { return start_line_; } 90 91 // GetType returns the name of the first attribute of the current test. 92 const std::string &GetType(); 93 // GetParameter returns the value of the first attribute of the current test. 94 const std::string &GetParameter(); 95 // GetBlock returns the optional block of the current test, or the empty 96 // if there was no block. 97 const std::string &GetBlock(); 98 99 // HasAttribute returns true if the current test has an attribute named |key|. 100 bool HasAttribute(const std::string &key); 101 102 // GetAttribute looks up the attribute with key |key|. It sets |*out_value| to 103 // the value and returns true if it exists and returns false with an error to 104 // |stderr| otherwise. 105 bool GetAttribute(std::string *out_value, const std::string &key); 106 107 // GetAttributeOrDie looks up the attribute with key |key| and aborts if it is 108 // missing. It only be used after a |HasAttribute| call. 109 const std::string &GetAttributeOrDie(const std::string &key); 110 111 // GetBytes looks up the attribute with key |key| and decodes it as a byte 112 // string. On success, it writes the result to |*out| and returns 113 // true. Otherwise it returns false with an error to |stderr|. The value may 114 // be either a hexadecimal string or a quoted ASCII string. It returns true on 115 // success and returns false with an error to |stderr| on failure. 116 bool GetBytes(std::vector<uint8_t> *out, const std::string &key); 117 118 // ExpectBytesEqual returns true if |expected| and |actual| are equal. 119 // Otherwise, it returns false and prints a message to |stderr|. 120 bool ExpectBytesEqual(const uint8_t *expected, size_t expected_len, 121 const uint8_t *actual, size_t actual_len); 122 123 private: 124 void ClearTest(); 125 void OnKeyUsed(const std::string &key); 126 127 FILE *file_ = nullptr; 128 // line_ is the number of lines read. 129 unsigned line_ = 0; 130 131 // start_line_ is the line number of the first attribute of the test. 132 unsigned start_line_ = 0; 133 // type_ is the name of the first attribute of the test. 134 std::string type_; 135 // parameter_ is the value of the first attribute. 136 std::string parameter_; 137 // attributes_ contains all attributes in the test, including the first. 138 std::map<std::string, std::string> attributes_; 139 // block_, if non-empty, is the test's optional trailing block. 140 std::string block_; 141 142 // unused_attributes_ is the set of attributes that have been queried. 143 std::set<std::string> unused_attributes_; 144 // used_block_ is true if the block has been queried. 145 bool used_block_ = false; 146 147 FileTest(const FileTest&) = delete; 148 FileTest &operator=(const FileTest&) = delete; 149 }; 150 151 // FileTestMain runs a file-based test out of |path| and returns an exit code 152 // suitable to return out of |main|. |run_test| should return true on pass and 153 // false on failure. FileTestMain also implements common handling of the 'Error' 154 // attribute. A test with that attribute is expected to fail. The value of the 155 // attribute is the reason string of the expected OpenSSL error code. 156 // 157 // Tests are guaranteed to run serially and may affect global state if need be. 158 // It is legal to use "tests" which, for example, import a private key into a 159 // list of keys. This may be used to initialize a shared set of keys for many 160 // tests. However, if one test fails, the framework will continue to run 161 // subsequent tests. 162 int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg, 163 const char *path); 164 165 166 #endif /* OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H */ 167