// -*- c++ -*- //------------------------------------------------------------------------------ // logger_test.cpp //------------------------------------------------------------------------------ // $Id: logger_test.cpp,v 1.8 2006/07/20 02:30:56 vlg Exp $ //------------------------------------------------------------------------------ // Copyright (c) 2001,2004 by Vladislav Grinchenko // // Permission to use, copy, modify, and distribute this software // and its documentation for any purpose and without fee is hereby // granted, provided that the above copyright notice appear in all // copies. The author makes no representations about the suitability // of this software for any purpose. It is provided "as is" without // express or implied warranty. //------------------------------------------------------------------------------ // Date: Nov. 10, 2001 //------------------------------------------------------------------------------ #include #include // unlink(2), stat(2) #include // stat(2) #include // stat(2) #include #include using namespace std; #include "assa/Logger.h" #include "assa/Assure.h" using namespace ASSA; static void report_devnull_error (); struct mask { const char* m_name; unsigned long m_val; } groups [] = { { "TRACE", 0x00000001 }, { "APP", 0x00000002 }, { "USR1", 0x00000004 }, { "USR2", 0x00000008 }, { "USR3", 0x00000010 }, { "ALL_APPS", 0x0000001F }, { "ERROR", 0x00000020 }, { "PIDFLOCK", 0x00000040 }, { "CMDLINEOPTS", 0x00000080 }, { "SEM", 0x00000100 }, { "SIGHAND", 0x00000200 }, { "REACT", 0x00000400 }, { "REACTTRACE", 0x00000800 }, { "SOCK", 0x00001000 }, { "SOCKTRACE", 0x00002000 }, { "XDRBUF", 0x00004000 }, { "XDRBUFTRACE", 0x00008000 }, { "STRMBUF", 0x00010000 }, { "STRMBUFTRACE",0x00020000 }, { "FORK", 0x00040000 }, { "SIGACT", 0x00080000 }, { "PIPE", 0x00100000 }, { "CHARINBUF", 0x00200000 }, { "RES2", 0x00400000 }, { "RES3", 0x00800000 }, { "RES4", 0x01000000 }, { "RES5", 0x02000000 }, { "RES6", 0x04000000 }, { "RES7", 0x08000000 }, { "RES8", 0x10000000 }, { "RES9", 0x20000000 }, { "RES10", 0x40000000 }, { "ALL_LIB", 0x7FFFFFF0 }, { "ALL", 0x7FFFFFFF }, { "NONE", 0x00000000 }, { NULL, 0 } }; void foo3 (void) { trace ("foo3"); DL((ALL,"End of calling chain\n")); } void foo2 (void) { trace ("foo2"); DL((ALL,"Setting timezone to GMT - Notice time change\n")); Log::set_gmt_timezone (); DL((ALL,"Calling foo3\n")); foo3(); } void foo (void) { trace ("foo"); DL((ALL,"Calling foo2\n")); foo2(); } void test_msg_limit () { trace("test_msg_limit"); register char c; const size_t size = Logger_Impl::LOGGER_MAXLINE+3; char buf [size]; char* c_ptr = buf; ::memset (buf, 0, size); buf [size - 1] = '\n'; while (true) { if (*c_ptr != '\n') *c_ptr++ = '0'; else break; if (*c_ptr != '\n') *c_ptr++ = '1'; else break; if (*c_ptr != '\n') *c_ptr++ = '2'; else break; if (*c_ptr != '\n') *c_ptr++ = '3'; else break; if (*c_ptr != '\n') *c_ptr++ = '4'; else break; if (*c_ptr != '\n') *c_ptr++ = '5'; else break; if (*c_ptr != '\n') *c_ptr++ = '6'; else break; if (*c_ptr != '\n') *c_ptr++ = '7'; else break; if (*c_ptr != '\n') *c_ptr++ = '8'; else break; if (*c_ptr != '\n') *c_ptr++ = '9'; else break; } DL((ALL,"%s\n", buf)); DL((ALL,"This message should appear on a separate line.\n")); MemDump md (buf, size); DL((ALL,"The same message as hex dump (%d bytes):\n", (md.getMemDump () == NULL ? -1 : strlen (md.getMemDump ())))); DL((ALL,"%s\n", md.getMemDump ())); DL((ALL,"This message should appear on a separate line.\n")); } void gee (void) { trace("gee"); DL((ALL,"Message of the day: Love my life!\n")); errno = 20; EL((ASSA::ASSAERR,"This is an errno=20 message\n")); } int main () { int ret; const char* logname = "logger_test.log"; const char* msg_limit = "logger_test_msg_limit.log"; ::unlink (logname); ::unlink (msg_limit); if ((ret = Log::open_log_file (logname, ALL, 1000000)) < 0) { cerr << logname << ": failed to open(): ret: " << ret << ", errno = " << errno << " \"" << strerror(errno) << "\"" << endl; return 1; } DL((ALL,"I'm %d years old\n", 38)); DL((ALL,"I've waited hours for this\n")); DL((ALL,"I've made myself so sick\n")); DL((ALL,"I wish I'd stayed asleep today\n")); DL((ALL,"I never thought that this day would end\n")); DL((ALL,"I never thought that tonight could ever be\n")); DL((ALL,"This close to me\n")); /** Premature termination */ // Log::log_close (); // return (0); gee (); Log::enable_timestamp (); DL((ALL,"This message should appear with a timestamp\n")); DL((ALL,"Testing the function call stepping\n")); foo (); DL((ALL,"Switching to LogStdError\n")); Log::log_close (); Log::open_log_stdout (); DL((ALL,"*** This is expected on stdout ***\n")); DL((ALL," Strange attraction spreads its wings\n")); DL((ALL," It varies but the smallest things\n")); DL((ALL," You never know how anything will change\n")); DL((ALL," And alters but the smallest things\n")); DL((ALL," You never know how anything will fade...\n")); const char* logname_masks = "logger_test_masks.log"; unlink (logname_masks); // Testing LogMask::Group masks processing DL((ALL,"*** Testing mask processing ***\n")); Logger& log= *Logger::get_instance (); log.disable_all_groups (); DL((ALL,"All groups disabled - you should not see this message!\n")); unsigned int i = 0; while (groups [i].m_name != NULL) { log.enable_group (Group (groups [i].m_val)); DL((groups [i].m_val,"%s enabled\n", groups [i].m_name)); log.disable_group (Group (groups [i].m_val)); DL((groups [i].m_val,"%s disabled - error!\n", groups [i].m_name)); i++; } Log::log_close (); if ((ret = Log::open_log_file (logname_masks, 0x7fff0001, 1000000)) < 0) { cerr << logname << ": failed to open(): ret: " << ret << ", errno = " << errno << " \"" << strerror(errno) << "\"" << endl; return 1; } DL((ALL,"Testing some popular masks...\n")); DL((ALL,"You should seen no error messages.\n")); i = 1; while (!strcmp (groups[i].m_name, "APP")) { DL((groups [i].m_val,"%s disabled - error!\n", groups [i].m_name)); i++; } while (groups[i].m_name != NULL) { DL((groups [i].m_val,"%s enabled\n", groups [i].m_name)); i++; } Log::log_close (); if (Log::open_log_file (msg_limit, ASSA::ALL, 1000000) < 0) { return -1; } DL((ALL,"Testing message limit (256 characters)...\n")); test_msg_limit (); Log::log_close (); /** Test /dev/null bug. In the buggy version, if logging file name is "/dev/null", the library would replace it with a regular file when file size limit is reached. */ const char devnull [] = "/dev/null"; if (Log::open_log_file (devnull, ASSA::ALL, 1000000) < 0) { return -1; } struct stat fst; for (int i = 0; i < 1000000; i++) { // force backup file creation DL((ALL,"assa!\n")); } if (::stat (devnull, &fst) < 0 || !S_ISCHR (fst.st_mode)) { report_devnull_error (); return -1; } return 0; } void report_devnull_error () { std::cerr << "Error: FileLogger might have replaced your\n" " /dev/null with a regular file. To restore:\n" " # rm -f /dev/null\n" " # mknod -m 0666 /dev/null c 1 3\n"; }