summaryrefslogtreecommitdiff
path: root/tests/Service_Config_Test.cpp
blob: 3e7fb7c9bbfa956c619f5fa32d56af123da3ca05 (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
// $Id$

// ============================================================================
//
// = LIBRARY
//    tests
//
// = FILENAME
//    Service_Config_Test.cpp
//
// = DESCRIPTION
//      This is a simple test to make sure the Service_Configurator is
//      working correctly.
//
// = AUTHOR
//    David Levine
//
// ============================================================================

#include "test_config.h"
#include "ace/Object_Manager.h"
#include "ace/Service_Config.h"

#define VARIETIES 3

u_int error = 0;

// This should be a template class, with singleton instantiations.
// But to avoid having to deal with compilers that want template
// declarations in separate files, it's just a plain class.  The
// instance argument differentiates the "singleton" instances.
// It also demonstrates the use of the param arg to the cleanup ()
// function.
class Test_Singleton
{
public:
  static Test_Singleton *instance (u_short variety);
  static void cleanup (void *, void *);
private:
  u_short variety_;
  static u_short current_;

  Test_Singleton (u_short variety);
  ~Test_Singleton (void);

  friend class misspelled_verbase_friend_declaration_to_avoid_compiler_warning_with_private_ctor;
};

u_short Test_Singleton::current_ = 0;

Test_Singleton *
Test_Singleton::instance (u_short variety)
{
  static Test_Singleton *instances[VARIETIES] = { 0 };

  if (instances[variety] == 0)
    {
      ACE_NEW_RETURN (instances[variety], Test_Singleton (variety), 0);
    }

  ACE_Object_Manager::at_exit (instances[variety], cleanup, (void *) variety);

  return instances[variety];
}

void
Test_Singleton::cleanup (void *object, void *param)
{
  // We can't reliably use ACE_Log_Msg in a cleanup hook.  Yet.
  ACE_UNUSED_ARG (param);
  /* ACE_DEBUG ((LM_DEBUG, "cleanup %d\n", (u_short) param)); */

  delete (Test_Singleton *) object;
}

Test_Singleton::Test_Singleton (u_short variety)
  : variety_ (variety)
{
  if (variety_ != current_++)
    {
      ACE_DEBUG ((LM_ERROR, "ERROR: instance %u created out of order!\n",
                 variety_));
      ++error;
    }
}

// We can't reliably use ACE_Log_Msg in a destructor that is called by
// ACE_Object_Manager.  Yet.
Test_Singleton::~Test_Singleton (void)
{
  /* ACE_DEBUG ((LM_DEBUG, "Test_Singleton %u dtor\n", variety_)); */

  if (variety_ != --current_)
    {
      ACE_OS::fprintf (stderr, "ERROR: instance %u destroyed out of order!\n",
                       variety_);
      /* ACE_DEBUG ((LM_ERROR, "ERROR: instance %u destroyed out of order!\n",
                 variety_)); */
      ++error;
    }
}

static void
run_test (int argc, char *argv[])
{
  // We need this scope to make sure that the destructor for the
  // ACE_Service_Config gets called.
  ACE_Service_Config daemon;

  daemon.open (argc, argv);

  ACE_Time_Value tv (argc > 1 ? atoi (argv[1]) : 2);

  ACE_ASSERT (ACE_Reactor::run_event_loop (tv) == 0);
}

int
main (int argc, char *argv[])
{
  ACE_START_TEST ("Service_Config_Test");

  for (u_int i = 0; i < VARIETIES; ++i)
    {
      Test_Singleton &s = *Test_Singleton::instance (i);

      if (&s == 0)
        {
          ACE_ERROR_RETURN ((LM_ERROR, "instance () allocate failed!\n"), 1);
        }
    }

  run_test (argc, argv);

  ACE_END_TEST;
  return error == 0 ? 0 : 1;
}