// $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" ACE_RCSID(tests, Service_Config_Test, "$Id$") static const u_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, ASYS_TEXT ("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, ASYS_TEXT ("Test_Singleton %u dtor\n"), variety_)); */ if (variety_ != --current_) { ACE_OS::fprintf (stderr, ASYS_TEXT ("ERROR: instance %u destroyed out of order!\n"), variety_); /* ACE_DEBUG ((LM_ERROR, ASYS_TEXT ("ERROR: instance %u destroyed out of order!\n"), variety_)); */ ++error; } } static void run_test (int argc, ASYS_TCHAR *argv[]) { // We need this scope to make sure that the destructor for the // gets called. ACE_Service_Config daemon; ACE_ASSERT (daemon.open (argc, argv) != -1 || errno == ENOENT); ACE_Time_Value tv (argc > 1 ? ACE_OS::atoi (argv[1]) : 2); ACE_ASSERT (ACE_Reactor::run_event_loop (tv) == 0); } int main (int argc, ASYS_TCHAR *argv[]) { ACE_START_TEST (ASYS_TEXT ("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, ASYS_TEXT ("instance () allocate failed!\n")), 1); } run_test (argc, argv); ACE_END_TEST; return error == 0 ? 0 : 1; }