1 /* LOG unit tests 2 3 This example code is in the Public Domain (or CC0 licensed, at your option.) 4 5 Unless required by applicable law or agreed to in writing, this 6 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 7 CONDITIONS OF ANY KIND, either express or implied. 8 */ 9 #define CATCH_CONFIG_MAIN 10 #include <cstdio> 11 #include <regex> 12 #include <iostream> 13 #include "esp_log.h" 14 15 #include "catch.hpp" 16 17 using namespace std; 18 19 static const char *TEST_TAG = "test"; 20 21 class BasicLogFixture { 22 public: 23 static const size_t BUFFER_SIZE = 4096; 24 BasicLogFixture(esp_log_level_t log_level=ESP_LOG_VERBOSE)25 BasicLogFixture(esp_log_level_t log_level = ESP_LOG_VERBOSE) 26 { 27 std::memset(print_buffer, 0, BUFFER_SIZE); 28 esp_log_level_set("*", log_level); 29 } 30 ~BasicLogFixture()31 virtual ~BasicLogFixture() 32 { 33 esp_log_level_set("*", ESP_LOG_INFO); 34 } 35 get_print_buffer_string() const36 string get_print_buffer_string() const 37 { 38 return string(print_buffer); 39 } 40 reset_buffer()41 void reset_buffer() 42 { 43 std::memset(print_buffer, 0, BUFFER_SIZE); 44 additional_reset(); 45 } 46 47 protected: 48 char print_buffer [BUFFER_SIZE]; 49 additional_reset()50 virtual void additional_reset() { } 51 }; 52 53 struct PrintFixture : BasicLogFixture { PrintFixturePrintFixture54 PrintFixture(esp_log_level_t log_level = ESP_LOG_VERBOSE) : BasicLogFixture(log_level) 55 { 56 if (instance != nullptr) { 57 throw exception(); 58 } 59 60 instance = this; 61 62 old_vprintf = esp_log_set_vprintf(print_callback); 63 } 64 ~PrintFixturePrintFixture65 virtual ~PrintFixture() 66 { 67 esp_log_set_vprintf(old_vprintf); 68 instance = nullptr; 69 } 70 71 private: print_callbackPrintFixture72 static int print_callback(const char *format, va_list args) 73 { 74 return instance->print_to_buffer(format, args); 75 } 76 print_to_bufferPrintFixture77 int print_to_buffer(const char *format, va_list args) 78 { 79 int ret = vsnprintf(print_buffer, BUFFER_SIZE, format, args); 80 return ret; 81 } 82 83 static PrintFixture *instance; 84 85 vprintf_like_t old_vprintf; 86 }; 87 88 struct PutcFixture : BasicLogFixture { PutcFixturePutcFixture89 PutcFixture(esp_log_level_t log_level = ESP_LOG_VERBOSE) : BasicLogFixture(log_level), counter(0) 90 { 91 if (instance != nullptr) { 92 throw exception(); 93 } 94 95 esp_rom_install_channel_putc(0, putc_callback); 96 97 instance = this; 98 } 99 ~PutcFixturePutcFixture100 ~PutcFixture() 101 { 102 esp_rom_install_uart_printf(); 103 instance = nullptr; 104 } 105 additional_resetPutcFixture106 void additional_reset() override 107 { 108 counter = 0; 109 } 110 111 size_t counter; 112 113 private: putc_callbackPutcFixture114 static void putc_callback(char c) 115 { 116 return instance->putc_to_buffer(c); 117 } 118 putc_to_bufferPutcFixture119 void putc_to_buffer(char c) 120 { 121 print_buffer[counter++] = c; 122 } 123 124 static PutcFixture *instance; 125 }; 126 127 PrintFixture *PrintFixture::instance = nullptr; 128 PutcFixture *PutcFixture::instance = nullptr; 129 130 TEST_CASE("verbose log level") 131 { 132 PrintFixture fix(ESP_LOG_VERBOSE); 133 const std::regex test_print("V \\([0-9]*\\) test: verbose", std::regex::ECMAScript); 134 135 ESP_LOGV(TEST_TAG, "verbose"); 136 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 137 } 138 139 TEST_CASE("debug log level") 140 { 141 PrintFixture fix(ESP_LOG_DEBUG); 142 const std::regex test_print("D \\([0-9]*\\) test: debug", std::regex::ECMAScript); 143 144 ESP_LOGD(TEST_TAG, "debug"); 145 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 146 } 147 148 TEST_CASE("info log level") 149 { 150 PrintFixture fix(ESP_LOG_INFO); 151 const std::regex test_print("I \\([0-9]*\\) test: info", std::regex::ECMAScript); 152 153 ESP_LOGI(TEST_TAG, "info"); 154 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 155 } 156 157 TEST_CASE("warn log level") 158 { 159 PrintFixture fix(ESP_LOG_WARN); 160 const std::regex test_print("W \\([0-9]*\\) test: warn", std::regex::ECMAScript); 161 162 ESP_LOGW(TEST_TAG, "warn"); 163 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 164 } 165 166 TEST_CASE("error log level") 167 { 168 PrintFixture fix(ESP_LOG_ERROR); 169 const std::regex test_print("E \\([0-9]*\\) test: error", std::regex::ECMAScript); 170 171 ESP_LOGE(TEST_TAG, "error"); 172 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 173 } 174 175 TEST_CASE("changing log level") 176 { 177 PrintFixture fix(ESP_LOG_INFO); 178 const std::regex test_print("I \\([0-9]*\\) test: must indeed be printed", std::regex::ECMAScript); 179 180 ESP_LOGI(TEST_TAG, "must indeed be printed"); 181 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 182 183 fix.reset_buffer(); 184 esp_log_level_set(TEST_TAG, ESP_LOG_WARN); 185 186 ESP_LOGI(TEST_TAG, "must not be printed"); 187 CHECK(fix.get_print_buffer_string().size() == 0); 188 189 fix.reset_buffer(); 190 esp_log_level_set(TEST_TAG, ESP_LOG_INFO); 191 192 ESP_LOGI(TEST_TAG, "must indeed be printed"); 193 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 194 } 195 196 TEST_CASE("log buffer") 197 { 198 PrintFixture fix(ESP_LOG_INFO); 199 const uint8_t buffer[] = { 200 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 201 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 202 }; 203 ESP_LOG_BUFFER_HEX(TEST_TAG, buffer, sizeof(buffer)); 204 const std::regex buffer_regex("I \\([0-9]*\\) test: 01 02 03 04 05 06 07 08 11 12 13 14 15 16 17 18", std::regex::ECMAScript); 205 CHECK(regex_search(fix.get_print_buffer_string(), buffer_regex)); 206 } 207 208 TEST_CASE("rom printf") 209 { 210 PutcFixture fix; 211 int printed_chars = esp_rom_printf("info"); 212 213 CHECK(printed_chars == 4); 214 CHECK(fix.get_print_buffer_string() == "info"); 215 } 216 217 TEST_CASE("early verbose log level") 218 { 219 PutcFixture fix; 220 const std::regex test_print("V \\([0-9]*\\) test: verbose", std::regex::ECMAScript); 221 222 ESP_EARLY_LOGV(TEST_TAG, "verbose"); 223 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 224 } 225 226 TEST_CASE("early debug log level") 227 { 228 PutcFixture fix; 229 const std::regex test_print("D \\([0-9]*\\) test: debug", std::regex::ECMAScript); 230 231 ESP_EARLY_LOGD(TEST_TAG, "debug"); 232 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 233 } 234 235 TEST_CASE("early info log level") 236 { 237 PutcFixture fix; 238 const std::regex test_print("I \\([0-9]*\\) test: info", std::regex::ECMAScript); 239 240 ESP_EARLY_LOGI(TEST_TAG, "info"); 241 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 242 } 243 244 TEST_CASE("early warn log level") 245 { 246 PutcFixture fix; 247 const std::regex test_print("W \\([0-9]*\\) test: warn", std::regex::ECMAScript); 248 249 ESP_EARLY_LOGW(TEST_TAG, "warn"); 250 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 251 } 252 253 TEST_CASE("early error log level") 254 { 255 PutcFixture fix; 256 const std::regex test_print("E \\([0-9]*\\) test: error", std::regex::ECMAScript); 257 258 ESP_EARLY_LOGE(TEST_TAG, "error"); 259 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 260 } 261 262 TEST_CASE("changing early log level") 263 { 264 PutcFixture fix(ESP_LOG_INFO); 265 const std::regex test_print("I \\([0-9]*\\) test: must indeed be printed", std::regex::ECMAScript); 266 267 ESP_EARLY_LOGI(TEST_TAG, "must indeed be printed"); 268 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 269 270 fix.reset_buffer(); 271 esp_log_level_set("*", ESP_LOG_WARN); 272 273 ESP_EARLY_LOGI(TEST_TAG, "must not be printed"); 274 CHECK(fix.get_print_buffer_string().size() == 0); 275 276 fix.reset_buffer(); 277 esp_log_level_set("*", ESP_LOG_INFO); 278 279 ESP_EARLY_LOGI(TEST_TAG, "must indeed be printed"); 280 CHECK(regex_search(fix.get_print_buffer_string(), test_print) == true); 281 } 282