summaryrefslogtreecommitdiff
path: root/tests/Service_Config_Test.cpp
blob: 0499881fbf705ba8d745fafccee5aa8b1c5fed32 (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
// $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"

static const int VARIETIES = 3;

static u_int error = 0;

class Test_Singleton
  // = TITLE
  //   Test the Singleton
  //
  // = DESCRIPTION
  //   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.
{
public:
  static Test_Singleton *instance (u_short variety);
  ~Test_Singleton (void);

private:
  u_short variety_;
  static u_short current_;

  Test_Singleton (u_short variety);

  friend class misspelled_verbase_friend_declaration_to_avoid_compiler_warning_with_private_ctor;
};

u_short Test_Singleton::current_ = 0;

extern "C" 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::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],
			       test_singleton_cleanup,
			       (void *) variety);
  return instances[variety];
}

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