1 // A basic unit test that runs on a BMC (qemu or hardware) 2 3 #include <getopt.h> 4 #include <iostream> 5 #include <systemd/sd-journal.h> 6 #include <sstream> 7 #include <phosphor-logging/elog.hpp> 8 #include <phosphor-logging/log.hpp> 9 10 using namespace phosphor; 11 using namespace logging; 12 13 const char *usage = "Usage: logging-test [OPTION] \n\n\ 14 Options: \n\ 15 [NONE] Default test case. \n\ 16 -h, --help Display this usage text. \n\ 17 -c, --commit <string> Commit desired error. \n\n\ 18 Valid errors to commit: \n\ 19 AutoTestSimple\n"; 20 21 // validate the journal metadata equals the input value 22 int validate_journal(const char *i_entry, const char *i_value) 23 { 24 sd_journal *journal; 25 const void *data; 26 size_t l; 27 int rc; 28 bool validated = false; 29 30 rc = sd_journal_open(&journal, SD_JOURNAL_LOCAL_ONLY); 31 if (rc < 0) { 32 std::cerr << "Failed to open journal: " << strerror(-rc) << "\n"; 33 return 1; 34 } 35 rc = sd_journal_query_unique(journal, i_entry); 36 if (rc < 0) { 37 std::cerr << "Failed to query journal: " << strerror(-rc) << "\n"; 38 return 1; 39 } 40 SD_JOURNAL_FOREACH_UNIQUE(journal, data, l) 41 { 42 std::string journ_entry((const char*)data); 43 std::cout << journ_entry << "\n"; 44 if(journ_entry.find(i_value) != std::string::npos) 45 { 46 std::cout << "We found it!\n"; 47 validated = true; 48 break; 49 } 50 } 51 52 sd_journal_close(journal); 53 54 rc = (validated) ? 0 : 1; 55 if(rc) 56 { 57 std::cerr << "Failed to find " << i_entry << " with value " << i_value 58 <<" in journal!" << "\n"; 59 } 60 61 return rc; 62 } 63 64 int elog_test() 65 { 66 // TEST 1 - Basic log 67 log<level::DEBUG>("Basic phosphor logging test"); 68 69 // TEST 2 - Log with metadata field 70 const char *file_name = "phosphor_logging_test.txt"; 71 int number = 0xFEFE; 72 log<level::DEBUG>("phosphor logging test with attribute", 73 entry("FILE_NAME_WITH_NUM_TEST=%s_%x", file_name, number)); 74 75 // Now read back and verify our data made it into the journal 76 int rc = validate_journal("FILE_NAME_WITH_NUM_TEST", 77 "phosphor_logging_test.txt_fefe"); 78 if(rc) 79 return(rc); 80 81 // TEST 3 - Create error log with 2 meta data fields (rvalue and lvalue) 82 number = 0x1234; 83 const char *test_string = "/tmp/test_string/"; 84 try 85 { 86 elog<example::xyz::openbmc_project::Example::Elog::TestErrorOne>( 87 example::xyz::openbmc_project::Example::Elog:: 88 TestErrorOne::ERRNUM(number), 89 example::xyz::openbmc_project::Example::Elog:: 90 TestErrorOne::FILE_PATH(test_string), 91 example::xyz::openbmc_project::Example::Elog:: 92 TestErrorOne::FILE_NAME("elog_test_3.txt"), 93 example::xyz::openbmc_project::Example::Elog:: 94 TestErrorTwo::DEV_ADDR(0xDEADDEAD), 95 example::xyz::openbmc_project::Example::Elog:: 96 TestErrorTwo::DEV_ID(100), 97 example::xyz::openbmc_project::Example::Elog:: 98 TestErrorTwo::DEV_NAME("test case 3")); 99 } 100 catch (elogException<example::xyz::openbmc_project::Example::Elog:: 101 TestErrorOne>& e) 102 { 103 std::cout << "elog exception caught: " << e.what() << std::endl; 104 } 105 106 // Reduce our error namespaces 107 using namespace example::xyz::openbmc_project::Example::Elog; 108 109 // Now read back and verify our data made it into the journal 110 std::stringstream stream; 111 stream << std::hex << number; 112 rc = validate_journal(TestErrorOne::ERRNUM::str_short, 113 std::string(stream.str()).c_str()); 114 if(rc) 115 return(rc); 116 117 rc = validate_journal(TestErrorOne::FILE_PATH::str_short, 118 test_string); 119 if(rc) 120 return(rc); 121 122 rc = validate_journal(TestErrorOne::FILE_NAME::str_short, 123 "elog_test_3.txt"); 124 if(rc) 125 return(rc); 126 127 rc = validate_journal(TestErrorTwo::DEV_ADDR::str_short, 128 "0xDEADDEAD"); 129 if(rc) 130 return(rc); 131 132 rc = validate_journal(TestErrorTwo::DEV_ID::str_short, 133 "100"); 134 if(rc) 135 return(rc); 136 137 rc = validate_journal(TestErrorTwo::DEV_NAME::str_short, 138 "test case 3"); 139 if(rc) 140 return(rc); 141 142 // TEST 4 - Create error log with previous entry use 143 number = 0x9876; 144 try 145 { 146 elog<TestErrorOne>(TestErrorOne::ERRNUM(number), 147 prev_entry<TestErrorOne::FILE_PATH>(), 148 TestErrorOne::FILE_NAME("elog_test_4.txt"), 149 TestErrorTwo::DEV_ADDR(0xDEADDEAD), 150 TestErrorTwo::DEV_ID(100), 151 TestErrorTwo::DEV_NAME("test case 4")); 152 } 153 catch (elogExceptionBase& e) 154 { 155 std::cout << "elog exception caught: " << e.what() << std::endl; 156 } 157 158 // Now read back and verify our data made it into the journal 159 stream.str(""); 160 stream << std::hex << number; 161 rc = validate_journal(TestErrorOne::ERRNUM::str_short, 162 std::string(stream.str()).c_str()); 163 if(rc) 164 return(rc); 165 166 // This should just be equal to what we put in test 3 167 rc = validate_journal(TestErrorOne::FILE_PATH::str_short, 168 test_string); 169 if(rc) 170 return(rc); 171 172 rc = validate_journal(TestErrorOne::FILE_NAME::str_short, 173 "elog_test_4.txt"); 174 if(rc) 175 return(rc); 176 177 rc = validate_journal(TestErrorTwo::DEV_ADDR::str_short, 178 "0xDEADDEAD"); 179 if(rc) 180 return(rc); 181 182 rc = validate_journal(TestErrorTwo::DEV_ID::str_short, 183 "100"); 184 if(rc) 185 return(rc); 186 187 rc = validate_journal(TestErrorTwo::DEV_NAME::str_short, 188 "test case 4"); 189 if(rc) 190 return(rc); 191 192 // Compile fail tests 193 194 // Simple test to prove we fail to compile due to missing param 195 //elog<TestErrorOne>(TestErrorOne::ERRNUM(1), 196 // TestErrorOne::FILE_PATH("test")); 197 198 // Simple test to prove we fail to compile due to invalid param 199 //elog<TestErrorOne>(TestErrorOne::ERRNUM(1), 200 // TestErrorOne::FILE_PATH("test"), 201 // TestErrorOne::FILE_NAME(1)); 202 203 return 0; 204 } 205 206 void commitError(const char *text) 207 { 208 if (strcmp(text, "AutoTestSimple") == 0) 209 { 210 try 211 { 212 elog<example::xyz::openbmc_project::Example::Elog:: 213 AutoTestSimple>( 214 example::xyz::openbmc_project::Example::Elog:: 215 AutoTestSimple::STRING("FOO")); 216 } 217 catch (elogException<example::xyz::openbmc_project::Example::Elog:: 218 AutoTestSimple>& e) 219 { 220 std::cout << "elog exception caught: " << e.what() << std::endl; 221 commit(e.name()); 222 } 223 } 224 225 return; 226 } 227 228 int main(int argc, char *argv[]) 229 { 230 char arg; 231 232 if (argc == 1) 233 return elog_test(); 234 235 static struct option long_options[] = 236 { 237 {"help", no_argument, 0, 'h'}, 238 {"commit", required_argument, 0, 'c'}, 239 {0, 0, 0, 0} 240 }; 241 int option_index = 0; 242 243 while((arg=getopt_long(argc,argv,"hc:",long_options,&option_index)) != -1) 244 { 245 switch (arg) 246 { 247 case 'c': 248 commitError(optarg); 249 return 0; 250 251 case 'h': 252 case '?': 253 std::cerr << usage; 254 return 1; 255 256 } 257 } 258 259 return 0; 260 261 } 262