//============================================================================= /** * @file Logging_Strategy_Test.cpp * * This program tests the class in various * ways and also illustrates many of the features of the * . The test works as follows: * -Load the inserted arguments; * -Remove existent log_files with the file_name specified by the * user; * -Generate 1000 messages to create the DEBUG statements to be * stored in the files; * -Counts the created log_files and if it was specified a maximum * number of log_files, compare and verify if they are the same. * -Verify the order of the files with the order argument. * * When Dlls are used, we utilize the dynamic service * configuration mechanism to activate the logging strategy. This * is not a must though, and you may activate the logging strategy * as described in the non-DLL section below under DLL * environments as well. * * @author Orlando Ribeiro */ //============================================================================= #include "test_config.h" #include "ace/OS_NS_stdio.h" #include "ace/OS_NS_string.h" #include "ace/OS_NS_unistd.h" #include "ace/OS_NS_sys_stat.h" #include "ace/Auto_Ptr.h" #include "ace/Service_Config.h" #include "ace/Reactor.h" #include "ace/Thread_Manager.h" #if defined (ACE_AS_STATIC_LIBS) || \ (!defined (ACE_WIN32) && !defined (ACE_HAS_SVR4_DYNAMIC_LINKING)) #include "ace/Logging_Strategy.h" #endif #include "ace/Auto_Ptr.cpp" #include "ace/Get_Opt.h" #include "ace/OS_NS_time.h" // Considering UNIX OS to be default. On Win32 platforms, the symbols // are got form the .exe as one cant have .exe and .dll for the same // .cpp. Also, on Win32 platforms one cant use the .obj to obtain // symbols dynamically at runtime. #if defined (ACE_WIN32) # define OBJ_SUFFIX ACE_TEXT (".exe") # define OBJ_PREFIX ACE_TEXT ("") #else # define OBJ_SUFFIX ACE_DLL_SUFFIX # define OBJ_PREFIX "./" ACE_DLL_PREFIX #endif /*ACE_WIN32*/ ACE_TCHAR const * cdecl_decoration (ACE_TCHAR const *func_name) { #if defined(ACE_NEEDS_DL_UNDERSCORE) static ACE_TCHAR decorated_func_name[10*1024]; ACE_OS::snprintf (decorated_func_name, 10*1024, ACE_TEXT ("_%s"), func_name); return decorated_func_name; #else return func_name; #endif /* ACE_NEEDS_DL_UNDERSCORE */ } // Global variables. static ACE_TCHAR *file_name = 0; static int max_size_files = 0; static int max_num_files = 0; static int interval_time = 0; static bool order_state = false; static int num_files = 0; static bool wipeout_logfile = false; // This adapter function runs the Reactor's event loop in a separate // thread of control. static void * run_reactor (void *) { ACE_Reactor::instance ()->owner (ACE_Thread_Manager::instance ()->thr_self ()); ACE_Reactor::instance ()->run_reactor_event_loop (); return 0; } // Initiate the cycle of messages. static void print_till_death () { ACE_DEBUG ((LM_DEBUG, "\n-> start generating messages...\n")); for (int i = 0; i < 1000; i++) { if (i % 50 == 0) ACE_OS::sleep (1); if (i == 0) ACE_DEBUG ((LM_DEBUG, " (%t) (%D) message\n")); else ACE_DEBUG ((LM_DEBUG, " (%t) %d message\n", i)); } if (ACE_Reactor::instance ()->end_reactor_event_loop () == -1) ACE_ERROR ((LM_ERROR, "Error ending reactor.\n")); ACE_DEBUG ((LM_DEBUG, "-< generating messages finished \n\n")); } // Count the generated files. static void count_files () { int i = 0; int error = 0; FILE *stream; ACE_TCHAR backup_ct[MAXPATHLEN+1]; ACE_DEBUG ((LM_DEBUG, "-> start counting...\n")); do { if (i == 0) ACE_OS::snprintf (backup_ct, MAXPATHLEN + 1, ACE_TEXT ("%s"), file_name); else ACE_OS::snprintf (backup_ct, MAXPATHLEN + 1, ACE_TEXT ("%s.%d"), file_name, i); stream = ACE_OS::fopen (backup_ct, ACE_TEXT ("r")); if (stream == 0) error = 1; else { i++; ACE_OS::fclose (stream); } } while (error != 1); num_files = i; if (max_num_files !=0) { if (max_num_files != num_files) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Creating files...Failed!") ACE_TEXT (" Input value=%d, Checked value=%d"), max_num_files, num_files)); else ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" Creating files...OK!") ACE_TEXT (" Input value=%d, Checked value=%d"), max_num_files, num_files)); } else ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" The number of files generated is: %d"), num_files)); ACE_DEBUG ((LM_DEBUG, "\n-< counting finished...\n")); } // get the file statistics static time_t get_statistics (ACE_TCHAR *f_name) { ACE_stat buf; // Get data associated with "file_name": int result = ACE_OS::stat (f_name, &buf); // Check if statistics are valid: if (result != 0) ACE_OS::perror (ACE_TEXT ("\nProblem getting information")); else { // Output some of the statistics: ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" File name : %s\n"), f_name)); ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" File size (B): %d\n"), buf.st_size)); ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" Time modified : %s\n"), ACE_OS::ctime (&buf.st_mtime))); } return buf.st_mtime; } // analyse the file order static void order () { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n-> start testing order...\n"))); if (num_files <= 2) { if (num_files == 1) get_statistics (file_name); ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" Ordering...OK! - ") ACE_TEXT (" Only %d file (s) was (were) generated"), num_files)); } else { time_t tm_bk_1, tm_bk_2; ACE_TCHAR backup_1[MAXPATHLEN+1]; ACE_TCHAR backup_2[MAXPATHLEN+1]; ACE_OS::snprintf (backup_1, MAXPATHLEN + 1, ACE_TEXT ("%s.%d"), file_name, 1); ACE_OS::snprintf (backup_2, MAXPATHLEN + 1, ACE_TEXT ("%s.%d"), file_name, num_files - 1); tm_bk_1 = get_statistics (backup_1); tm_bk_2 = get_statistics (backup_2); if (tm_bk_1 > tm_bk_2 && !order_state) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" %s (newest) ; %s (oldest)\n"), backup_1, backup_2)); ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" Ordering...OK!"))); } else { if (tm_bk_1 < tm_bk_2 && order_state) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" %s (newest);") ACE_TEXT ("%s (oldest)\n"), backup_2, backup_1)); ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" Ordering...OK!"))); } else ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" Ordering...FAILED!") ACE_TEXT ("- The files are disorderly"))); } } ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n-< testing order finished...\n\n"))); } // remove log_files static void remove_files () { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("-> removing existent files...\n"))); int error = 0; int i = 0; do { ++i; ACE_TCHAR backup[MAXPATHLEN+1]; ACE_OS::snprintf (backup, MAXPATHLEN + 1, ACE_TEXT ("%s.%d"), file_name, i); if (ACE_OS::unlink (backup) != 0) error = 1; } while (error != 1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("-< removing existing files...\n\n"))); } static int parse_args (int argc, ACE_TCHAR *argv[]) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Specifications:\n"))); ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("s:i:m:f:N:ow")); int c; while ((c = get_opt ()) != EOF) { switch (c) { case 's': file_name = get_opt.opt_arg (); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("File name: %s\n"), file_name)); break; case 'i': interval_time = ACE_OS::atoi (get_opt.opt_arg ()); //FUZZ: disable check_for_lack_ACE_OS ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Interval time (s): %d\n"), interval_time)); //FUZZ: enable check_for_lack_ACE_OS break; case 'm': max_size_files = ACE_OS::atoi (get_opt.opt_arg ()); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Maximum size (KB): %d\n"), max_size_files)); break; case 'f': ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Modes: %s\n"), get_opt.opt_arg ())); break; case 'N': max_num_files = ACE_OS::atoi (get_opt.opt_arg ()); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Maximum files number: %d\n"), max_num_files)); break; case 'o': ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Ordering files activated\n"))); order_state = true; break; case 'w': ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Wipeout logfile activated\n"))); wipeout_logfile = true; break; default: ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("usage: [-s]") ACE_TEXT ("[-i] ") ACE_TEXT ("[-m] [-f] ") ACE_TEXT ("[-n] [-o]\n") ACE_TEXT ("\t-s: Specify the name of the log files.\n") ACE_TEXT ("\t-i: Define the sample interval in secs.\n") ACE_TEXT ("\t-m: Define the max size for the log_files in KB.\n") ACE_TEXT ("\t-f: Indicates the Log_Msg flags.\n") ACE_TEXT ("\t-N: Define the maximum number of log_files.\n") ACE_TEXT ("\t-o: If activated puts the log_files ordered.\n"), ACE_TEXT ("\t-w: If activated cause the logfile to be wiped out,") ACE_TEXT (" both on startup and on reconfigure.\n")), -1); /* NOTREACHED */ break; } } ACE_UNUSED_ARG (wipeout_logfile); return 0; } int run_main (int argc, ACE_TCHAR *argv []) { ACE_START_TEST (ACE_TEXT ("Logging_Strategy_Test")); ACE_TCHAR *l_argv[4]; if (argc > 1) { if (parse_args (argc, argv) == -1) ACE_ERROR_RETURN ((LM_ERROR, "Invalid command-line parameters.\n"), 1); } else { l_argv[0] = (ACE_TCHAR *)ACE_TEXT ("Logging_Strategy_Test"); l_argv[1] = (ACE_TCHAR *) ACE_TEXT ("-s") ACE_DEFAULT_TEST_DIR ACE_TEXT ("log/Logging_Strategy_Test") ACE_LOG_FILE_EXT_NAME; l_argv[2] = (ACE_TCHAR *) ACE_TEXT ("-o"); l_argv[3] = 0; if (parse_args (3, l_argv) == -1) ACE_ERROR_RETURN ((LM_ERROR, "Invalid command-line parameters.\n"), 1); argv = l_argv; argc = 3; } // Remove existing files. remove_files (); // This is necessary only if the provided logfile name is the same // as the default name. If so, nothing will be written as the // previous ofstream is closed only at the end (ACE_END_TEST) ACE_CLOSE_TEST_LOG; // When Dlls are used, we utilize the dynamic service configuration // mechanism to activate the logging strategy. This is not a must // though, and you may activate the logging strategy as described in // the non-DLL section below under DLL environments as well. #if !defined (ACE_AS_STATIC_LIBS) && (defined (ACE_WIN32) || defined (ACE_HAS_SVR4_DYNAMIC_LINKING)) // Platform support DLLs, and not configured to link statically ACE_TCHAR arg_str[250]; ACE_OS::snprintf (arg_str, 250, ACE_TEXT ("dynamic Logger Service_Object ") ACE_TEXT ("*ACE:_make_ACE_Logging_Strategy()") ACE_TEXT ("\"")); for (int i = 1; i < argc; i++) { ACE_OS::strcat (arg_str, argv[i]); ACE_OS::strcat (arg_str, ACE_TEXT (" ")); } ACE_OS::strcat (arg_str, ACE_TEXT ("\"")); if (ACE_Service_Config::process_directive (arg_str) == -1) ACE_ERROR_RETURN ((LM_ERROR, "Error opening _make_ACE_Log_Strategy.\n"), 1); #else // Platform doesn't support DLLs, or configured to link // statically ACE_Logging_Strategy logging_strategy; unsigned char ls_argc = argc - 1; ACE_Auto_Basic_Ptr ls_argv (new ACE_TCHAR *[ls_argc]); for (unsigned char c = 0; c < ls_argc; c++) (ls_argv.get ())[c] = argv[c+1]; if (logging_strategy.init (ls_argc, ls_argv.get ()) == -1) ACE_ERROR_RETURN ((LM_ERROR, "Error initializing the ACE_Logging_Strategy.\n"), 1); #endif /* !ACE_AS_STATIC_LIBS && (ACE_WIN32 ACE_HAS_SVR4_DYNAMIC_LINKING) */ // launch a new Thread if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (run_reactor)) == -1) ACE_ERROR_RETURN ((LM_ERROR, "Spawning Reactor.\n"), 1); // Function to print the message print_till_death (); // Counts the generated files count_files (); // Get the file order order (); // Wait for the thread to exit before we exit. ACE_Thread_Manager::instance ()->wait (); ACE_END_TEST; return 0; }