summaryrefslogtreecommitdiff
path: root/ACE/tests/Logging_Strategy_Test.cpp
blob: 2a53c83606ff6da4545b2dbcc00ee2eb44170cd3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
// $Id$

//==========================================================================
//
// = LIBRARY
//    tests
//
// = FILENAME
//    Logging_Strategy_Test.cpp
//
// = DESCRIPTION
//     This program tests the <ACE_Logging_Strategy> class in various
//     ways and also illustrates many of the features of the
//     <ACE_Log_Msg>.  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 <oribeiro@inescporto.pt>
//
//==========================================================================

#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) && \
   !defined (__hpux))
#include "ace/Logging_Strategy.h"
#endif

#include "ace/Auto_Ptr.cpp"
#include "ace/Get_Opt.h"
#include "ace/OS_NS_time.h"

ACE_RCSID(tests, Logging_Strategy_Test, "$Id$")

// 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 (__BORLANDC__)
  static ACE_TCHAR decorated_func_name[10*1024];
  ACE_OS::sprintf (decorated_func_name,
                   ACE_TEXT ("_%s"),
                   func_name);
  return decorated_func_name;
#else
  return func_name;
#endif /* __BORLANDC__ */
}

// 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 (void)
{
  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 (void)
{
  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::sprintf (backup_ct,
                         ACE_TEXT ("%s"),
                         file_name);
      else
        ACE_OS::sprintf (backup_ct,
                         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;
  int result;

  // Get data associated with "file_name":
  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));

#if defined (ACE_HAS_WINCE)
      time_t tm = buf.st_mtime.sec();

      ACE_DEBUG ((LM_DEBUG,
                  ACE_TEXT ("      Time modified : %s\n"),
                  ACE_OS::ctime (&tm)));
#else
      ACE_DEBUG ((LM_DEBUG,
                  ACE_TEXT ("      Time modified : %s\n"),
                  ACE_OS::ctime (&buf.st_mtime)));
#endif  // ACE_HAS_WINCE
    }

#if defined (ACE_HAS_WINCE)
  return buf.st_mtime.sec();
#else
  return buf.st_mtime;
#endif  // ACE_HAS_WINCE
}

// analyse the file order
static void
order (void)
{
  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::sprintf (backup_1,
                       ACE_TEXT ("%s.%d"),
                       file_name,
                       1);
      ACE_OS::sprintf (backup_2,
                       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 (void)
{
  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("-> removing existent files...\n")));

  int error = 0;
  int test;
  int i = 0;
  ACE_TCHAR backup[MAXPATHLEN+1];

  do
    {
      i++;
      ACE_OS::sprintf (backup,
                       ACE_TEXT ("%s.%d"),
                       file_name,
                       i);
      test = ACE_OS::unlink (backup);
      if (test != 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 ());
          ACE_DEBUG ((LM_DEBUG,
                      ACE_TEXT ("Interval time (s): %d\n"),
                      interval_time));
          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]<file_name>")
              ACE_TEXT ("[-i]<sample_interval> ")
              ACE_TEXT ("[-m]<max_size> [-f]<msg_flags> ")
              ACE_TEXT ("[-n]<num_files> [-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 ("-slog/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) || \
   defined (__hpux))

  // Platform support DLLs, and not configured to link statically
  ACE_TCHAR arg_str[250];
  ACE_OS::sprintf (arg_str,
                   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;
  char ls_argc = argc - 1;
  ACE_Auto_Basic_Ptr<ACE_TCHAR *> ls_argv (new ACE_TCHAR *[ls_argc]);

  for (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 || __hpux) */

  // 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;
}