1 // A basic unit test that runs on a BMC (qemu or hardware) 2 3 #include <iostream> 4 #include <systemd/sd-journal.h> 5 #include <sstream> 6 #include <phosphor-logging/elog.hpp> 7 #include <phosphor-logging/log.hpp> 8 9 using namespace phosphor; 10 using namespace logging; 11 12 // validate the journal metadata equals the input value 13 int validate_journal(const char *i_entry, const char *i_value) 14 { 15 sd_journal *journal; 16 const void *data; 17 size_t l; 18 int rc; 19 bool validated = false; 20 21 rc = sd_journal_open(&journal, SD_JOURNAL_LOCAL_ONLY); 22 if (rc < 0) { 23 std::cerr << "Failed to open journal: " << strerror(-rc) << "\n"; 24 return 1; 25 } 26 rc = sd_journal_query_unique(journal, i_entry); 27 if (rc < 0) { 28 std::cerr << "Failed to query journal: " << strerror(-rc) << "\n"; 29 return 1; 30 } 31 SD_JOURNAL_FOREACH_UNIQUE(journal, data, l) 32 { 33 std::string journ_entry((const char*)data); 34 std::cout << journ_entry << "\n"; 35 if(journ_entry.find(i_value) != std::string::npos) 36 { 37 std::cout << "We found it!\n"; 38 validated = true; 39 break; 40 } 41 } 42 43 sd_journal_close(journal); 44 45 rc = (validated) ? 0 : 1; 46 if(rc) 47 { 48 std::cerr << "Failed to find " << i_entry << " with value " << i_value 49 <<" in journal!" << "\n"; 50 } 51 52 return rc; 53 } 54 55 int main() 56 { 57 // TEST 1 - Basic log 58 log<level::DEBUG>("Basic phosphor logging test"); 59 60 // TEST 2 - Log with metadata field 61 const char *file_name = "phosphor_logging_test.txt"; 62 int number = 0xFEFE; 63 log<level::DEBUG>("phosphor logging test with attribute", 64 entry("FILE_NAME_WITH_NUM_TEST=%s_%x", file_name, number)); 65 66 // Now read back and verify our data made it into the journal 67 int rc = validate_journal("FILE_NAME_WITH_NUM_TEST", 68 "phosphor_logging_test.txt_fefe"); 69 if(rc) 70 return(rc); 71 72 // TEST 3 - Create error log with 2 meta data fields (rvalue and lvalue) 73 number = 0x1234; 74 const char *test_string = "/tmp/test_string/"; 75 try 76 { 77 elog<example::xyz::openbmc_project::Example::Elog::Error::TestErrorOne>( 78 example::xyz::openbmc_project::Example::Elog::Error:: 79 TestErrorOne::ERRNUM(number), 80 example::xyz::openbmc_project::Example::Elog::Error:: 81 TestErrorOne::FILE_PATH(test_string), 82 example::xyz::openbmc_project::Example::Elog::Error:: 83 TestErrorOne::FILE_NAME("elog_test_3.txt"), 84 example::xyz::openbmc_project::Example::Elog::Error:: 85 TestErrorTwo::DEV_ADDR(0xDEADDEAD), 86 example::xyz::openbmc_project::Example::Elog::Error:: 87 TestErrorTwo::DEV_ID(100), 88 example::xyz::openbmc_project::Example::Elog::Error:: 89 TestErrorTwo::DEV_NAME("test case 3")); 90 } 91 catch (elogException<example::xyz::openbmc_project::Example::Elog::Error:: 92 TestErrorOne>& e) 93 { 94 std::cout << "elog exception caught: " << e.what() << std::endl; 95 } 96 97 // Reduce our error namespaces 98 using namespace example::xyz::openbmc_project::Example::Elog::Error; 99 100 // Now read back and verify our data made it into the journal 101 std::stringstream stream; 102 stream << std::hex << number; 103 rc = validate_journal(TestErrorOne::ERRNUM::str_short, 104 std::string(stream.str()).c_str()); 105 if(rc) 106 return(rc); 107 108 rc = validate_journal(TestErrorOne::FILE_PATH::str_short, 109 test_string); 110 if(rc) 111 return(rc); 112 113 rc = validate_journal(TestErrorOne::FILE_NAME::str_short, 114 "elog_test_3.txt"); 115 if(rc) 116 return(rc); 117 118 rc = validate_journal(TestErrorTwo::DEV_ADDR::str_short, 119 "0xDEADDEAD"); 120 if(rc) 121 return(rc); 122 123 rc = validate_journal(TestErrorTwo::DEV_ID::str_short, 124 "100"); 125 if(rc) 126 return(rc); 127 128 rc = validate_journal(TestErrorTwo::DEV_NAME::str_short, 129 "test case 3"); 130 if(rc) 131 return(rc); 132 133 // TEST 4 - Create error log with previous entry use 134 number = 0x9876; 135 try 136 { 137 elog<TestErrorOne>(TestErrorOne::ERRNUM(number), 138 prev_entry<TestErrorOne::FILE_PATH>(), 139 TestErrorOne::FILE_NAME("elog_test_4.txt"), 140 TestErrorTwo::DEV_ADDR(0xDEADDEAD), 141 TestErrorTwo::DEV_ID(100), 142 TestErrorTwo::DEV_NAME("test case 4")); 143 } 144 catch (elogExceptionBase& e) 145 { 146 std::cout << "elog exception caught: " << e.what() << std::endl; 147 } 148 149 // Now read back and verify our data made it into the journal 150 stream.str(""); 151 stream << std::hex << number; 152 rc = validate_journal(TestErrorOne::ERRNUM::str_short, 153 std::string(stream.str()).c_str()); 154 if(rc) 155 return(rc); 156 157 // This should just be equal to what we put in test 3 158 rc = validate_journal(TestErrorOne::FILE_PATH::str_short, 159 test_string); 160 if(rc) 161 return(rc); 162 163 rc = validate_journal(TestErrorOne::FILE_NAME::str_short, 164 "elog_test_4.txt"); 165 if(rc) 166 return(rc); 167 168 rc = validate_journal(TestErrorTwo::DEV_ADDR::str_short, 169 "0xDEADDEAD"); 170 if(rc) 171 return(rc); 172 173 rc = validate_journal(TestErrorTwo::DEV_ID::str_short, 174 "100"); 175 if(rc) 176 return(rc); 177 178 rc = validate_journal(TestErrorTwo::DEV_NAME::str_short, 179 "test case 4"); 180 if(rc) 181 return(rc); 182 183 // Compile fail tests 184 185 // Simple test to prove we fail to compile due to missing param 186 //elog<TestErrorOne>(TestErrorOne::ERRNUM(1), 187 // TestErrorOne::FILE_PATH("test")); 188 189 // Simple test to prove we fail to compile due to invalid param 190 //elog<TestErrorOne>(TestErrorOne::ERRNUM(1), 191 // TestErrorOne::FILE_PATH("test"), 192 // TestErrorOne::FILE_NAME(1)); 193 194 return 0; 195 } 196