Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / ACE / tests / Service_Config_Test.cpp
blob859d7d33cb2d5b92f1e07306160a923fb16f29de
1 // -*- C++ -*-
3 //=============================================================================
4 /**
5 * @file Service_Config_Test.cpp
7 * This is a simple test to make sure the ACE Service Configurator
8 * framework is working correctly.
10 * @author David Levine <levine@cs.wustl.edu>
11 * @author Ossama Othman <ossama@uci.edu>
13 //=============================================================================
15 #include "test_config.h"
16 #include "ace/OS_NS_stdio.h"
17 #include "ace/OS_NS_errno.h"
18 #include "ace/OS_NS_Thread.h"
19 #include "ace/Log_Msg.h"
20 #include "ace/Object_Manager.h"
21 #include "ace/Service_Config.h"
22 #include "ace/Service_Object.h"
23 #include "ace/Service_Repository.h"
24 #include "ace/Service_Types.h"
25 #include "ace/Reactor.h"
26 #include "ace/Thread_Manager.h"
27 #include "ace/ARGV.h"
29 static const u_int VARIETIES = 3;
31 static u_int error = 0;
33 class MyRepository : public ACE_Service_Repository
35 public:
36 array_type& array ()
38 return service_array_;
42 /**
43 * @class Test_Singleton
45 * @brief Test the Singleton
47 * This should be a template class, with singleton instantiations.
48 * But to avoid having to deal with compilers that want template
49 * declarations in separate files, it's just a plain class. The
50 * instance argument differentiates the "singleton" instances. It
51 * also demonstrates the use of the param arg to the cleanup ()
52 * function.
54 class Test_Singleton
56 public:
57 static Test_Singleton *instance (u_short variety);
58 ~Test_Singleton ();
60 private:
61 u_short variety_;
62 static u_short current_;
64 Test_Singleton (u_short variety);
66 friend class misspelled_verbase_friend_declaration_to_avoid_compiler_warning_with_private_ctor;
69 u_short Test_Singleton::current_ = 0;
71 extern "C" void
72 test_singleton_cleanup (void *object, void *)
74 // We can't reliably use ACE_Log_Msg in a cleanup hook. Yet.
75 /* ACE_DEBUG ((LM_DEBUG, "cleanup %d\n", (u_short) param)); */
77 delete (Test_Singleton *) object;
80 Test_Singleton *
81 Test_Singleton::instance (u_short variety)
83 static Test_Singleton *instances[VARIETIES] = { 0 };
85 if (instances[variety] == 0)
87 ACE_NEW_RETURN (instances[variety],
88 Test_Singleton (variety),
89 0);
92 ACE_Object_Manager::at_exit (instances[variety],
93 test_singleton_cleanup,
94 reinterpret_cast<void *> (static_cast<size_t> (variety)),
95 "Test_Singleton");
96 return instances[variety];
99 Test_Singleton::Test_Singleton (u_short variety)
100 : variety_ (variety)
102 if (variety_ != current_++)
104 ACE_DEBUG ((LM_ERROR,
105 ACE_TEXT ("ERROR: instance %u created out of order!\n"),
106 variety_));
107 ++error;
111 // We can't reliably use ACE_Log_Msg in a destructor that is called by
112 // ACE_Object_Manager. Yet.
114 Test_Singleton::~Test_Singleton ()
116 /* ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Test_Singleton %u dtor\n"), variety_)); */
118 if (variety_ != --current_)
120 ACE_OS::fprintf (stderr,
121 ACE_TEXT ("ERROR: instance %u destroyed out of order!\n"),
122 variety_);
123 /* ACE_DEBUG ((LM_ERROR, ACE_TEXT ("ERROR: instance %u destroyed out of order!\n"),
124 variety_)); */
125 ++error;
129 void
130 testFailedServiceInit (int, ACE_TCHAR *[])
132 static const ACE_TCHAR *refuse_svc =
133 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
134 ACE_TEXT ("dynamic Refuses_Svc Service_Object * ")
135 ACE_TEXT (" Service_Config_DLL:_make_Refuses_Init() \"\"")
136 #else
137 ACE_TEXT ("<dynamic id=\"Refuses_Svc\" type=\"Service_Object\">")
138 ACE_TEXT (" <initializer init=\"_make_Refuses_Init\" path=\"Service_Config_DLL\" params=\"\"/>")
139 ACE_TEXT ("</dynamic>")
140 #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
143 int error_count = 0;
144 if ((error_count = ACE_Service_Config::process_directive (refuse_svc)) != 1)
146 ++error;
147 ACE_ERROR ((LM_ERROR,
148 ACE_TEXT ("Failed init test should have returned 1; ")
149 ACE_TEXT ("returned %d instead\n"),
150 error_count));
153 // Try to find the service; it should not be there.
154 ACE_Service_Type const *svcp = 0;
155 if (-1 != ACE_Service_Repository::instance ()->find (ACE_TEXT ("Refuses_Svc"),
156 &svcp))
158 ++error;
159 ACE_ERROR ((LM_ERROR,
160 ACE_TEXT ("Found service repo entry for Refuses_Svc\n")));
161 ACE_Service_Type_Impl const *svc_impl = svcp->type ();
162 ACE_TCHAR msg[1024];
163 ACE_TCHAR *msgp = msg;
164 if (svc_impl->info (&msgp, sizeof (msg) / sizeof (ACE_TCHAR)) > 0)
165 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Refuses_Svc said: %s\n"), msg));
167 else
168 ACE_DEBUG ((LM_DEBUG,
169 ACE_TEXT ("Repo reports no Refuses_Svc; correct.\n")));
173 void
174 testLoadingServiceConfFileAndProcessNo (int argc, ACE_TCHAR *argv[])
176 u_int error0 = error;
177 ACE_ARGV new_argv;
179 ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Starting testLoadingServiceConfFileAndProcessNo\n")));
181 #if defined (ACE_USES_WCHAR)
182 // When using full Unicode support, use the version of the Service
183 // Configurator file appropriate to the platform.
184 // For example, Windows Unicode uses UTF-16.
186 // iconv(1) found on Linux, for example, can
187 // be used to convert between encodings.
189 // Byte ordering is also an issue, so we should be
190 // generating this file on-the-fly from the UTF-8 encoded
191 // file by using functions like iconv(1) or iconv(3).
192 # if defined (ACE_WIN32)
193 const ACE_TCHAR svc_conf[] =
194 ACE_TEXT ("Service_Config_Test.UTF-16")
195 ACE_TEXT (ACE_DEFAULT_SVC_CONF_EXT);
196 # else
197 const ACE_TCHAR svc_conf[] =
198 ACE_TEXT ("Service_Config_Test.WCHAR_T")
199 ACE_TEXT (ACE_DEFAULT_SVC_CONF_EXT);
200 # endif /* ACE_WIN32 */
201 #else
202 // ASCII (UTF-8) encoded Service Configurator file.
203 const ACE_TCHAR svc_conf[] =
204 ACE_TEXT ("Service_Config_Test")
205 ACE_TEXT (ACE_DEFAULT_SVC_CONF_EXT);
206 #endif /* ACE_USES_WCHAR */
208 ACE_TCHAR pid_file_name [MAXPATHLEN];
209 #if defined (TEST_DIR)
210 ACE_OS::strcpy (pid_file_name, TEST_DIR);
211 ACE_OS::strcat (pid_file_name, ACE_DIRECTORY_SEPARATOR_STR);
212 ACE_OS::strcat (pid_file_name, ACE_TEXT ("Service_Config_Test.pid"));
213 #else
214 ACE_OS::strcpy (pid_file_name, ACE_TEXT ("Service_Config_Test.pid"));
215 #endif
216 ACE_TCHAR svc_conf_file_name [MAXPATHLEN];
217 #if defined (TEST_DIR)
218 ACE_OS::strcpy (svc_conf_file_name, TEST_DIR);
219 ACE_OS::strcat (svc_conf_file_name, ACE_DIRECTORY_SEPARATOR_STR);
220 ACE_OS::strcat (svc_conf_file_name, svc_conf);
221 #else
222 ACE_OS::strcpy (svc_conf_file_name, svc_conf);
223 #endif
225 // Process the Service Configurator directives in this test's Making
226 // sure we have more than one option with an argument, to capture
227 // any errors caused by "reshuffling" of the options.
228 if (new_argv.add (argv) == -1
229 || new_argv.add (ACE_TEXT ("-d")) == -1
230 || new_argv.add (ACE_TEXT ("-k")) == -1
231 || new_argv.add (ACE_TEXT ("xxx")) == -1
232 || new_argv.add (ACE_TEXT ("-p")) == -1
233 || new_argv.add (pid_file_name) == -1
234 || new_argv.add (ACE_TEXT ("-f")) == -1
235 || new_argv.add (svc_conf_file_name) == -1)
237 ACE_ERROR ((LM_ERROR,
238 ACE_TEXT ("line %l %p\n"),
239 ACE_TEXT ("new_argv.add")));
240 ++error;
243 // We need this scope to make sure that the destructor for the
244 // <ACE_Service_Config> gets called.
245 ACE_Service_Config daemon;
247 ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Starting daemon using %s\n"), new_argv.buf ()));
249 if (daemon.open (new_argv.argc (), new_argv.argv ()) == -1 &&
250 errno != ENOENT)
252 ACE_ERROR ((LM_ERROR,
253 ACE_TEXT ("line %l %p\n"),
254 ACE_TEXT ("daemon.open")));
255 ++error;
258 ACE_Time_Value tv (argc > 1 ? ACE_OS::atoi (argv[1]) : 2);
260 if (ACE_Reactor::instance()->run_reactor_event_loop (tv) == -1)
262 ++error;
263 ACE_ERROR ((LM_ERROR,
264 ACE_TEXT ("line %l %p\n"),
265 ACE_TEXT ("run_reactor_event_loop")));
268 // Wait for all threads to complete.
269 ACE_Thread_Manager::instance ()->wait ();
271 if (error == error0)
272 ACE_DEBUG ((LM_DEBUG, ACE_TEXT("testLoadingServiceConfFileAndProcessNo completed successfully\n")));
273 else
274 ACE_ERROR ((LM_ERROR, ACE_TEXT("testLoadingServiceConfFileAndProcessNo test failed\n")));
278 void
279 testLoadingServiceConfFile (int argc, ACE_TCHAR *argv[])
281 ACE_ARGV new_argv;
283 #if defined (ACE_USES_WCHAR)
284 // When using full Unicode support, use the version of the Service
285 // Configurator file appropriate to the platform.
286 // For example, Windows Unicode uses UTF-16.
288 // iconv(1) found on Linux, for example, can
289 // be used to convert between encodings.
291 // Byte ordering is also an issue, so we should be
292 // generating this file on-the-fly from the UTF-8 encoded
293 // file by using functions like iconv(1) or iconv(3).
294 # if defined (ACE_WIN32)
295 const ACE_TCHAR svc_conf[] =
296 ACE_TEXT ("Service_Config_Test.UTF-16")
297 ACE_TEXT (ACE_DEFAULT_SVC_CONF_EXT);
298 # else
299 const ACE_TCHAR svc_conf[] =
300 ACE_TEXT ("Service_Config_Test.WCHAR_T")
301 ACE_TEXT (ACE_DEFAULT_SVC_CONF_EXT);
302 # endif /* ACE_WIN32 */
303 #else
304 // ASCII (UTF-8) encoded Service Configurator file.
305 const ACE_TCHAR svc_conf[] =
306 ACE_TEXT ("Service_Config_Test")
307 ACE_TEXT (ACE_DEFAULT_SVC_CONF_EXT);
308 #endif /* ACE_USES_WCHAR */
310 // Process the Service Configurator directives in this test's
311 if (new_argv.add (argv) == -1
312 || new_argv.add (ACE_TEXT ("-f")) == -1
313 || new_argv.add (svc_conf) == -1)
315 ACE_ERROR ((LM_ERROR,
316 ACE_TEXT ("line %l %p\n"),
317 ACE_TEXT ("new_argv.add")));
318 ++error;
321 // We need this scope to make sure that the destructor for the
322 // <ACE_Service_Config> gets called.
323 ACE_Service_Config daemon;
325 if (daemon.open (new_argv.argc (), new_argv.argv ()) == -1)
327 if (errno == ENOENT)
328 ACE_DEBUG ((LM_WARNING,
329 ACE_TEXT ("ACE_Service_Config::open: %p\n"),
330 svc_conf));
331 else
332 ACE_ERROR ((LM_ERROR,
333 ACE_TEXT ("ACE_Service_Config::open: %p\n"),
334 ACE_TEXT ("error")));
337 ACE_Time_Value tv (argc > 1 ? ACE_OS::atoi (argv[1]) : 2);
339 if (ACE_Reactor::instance()->run_reactor_event_loop (tv) == -1)
341 ++error;
342 ACE_ERROR ((LM_ERROR,
343 ACE_TEXT ("line %l %p\n"),
344 ACE_TEXT ("run_reactor_event_loop")));
347 // Wait for all threads to complete.
348 ACE_Thread_Manager::instance ()->wait ();
352 // Loading and unloading the ACE logger service should not smash singletons.
353 void
354 testUnloadingACELoggingStrategy (int, ACE_TCHAR *[])
356 static const ACE_TCHAR *load_logger =
357 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
358 ACE_TEXT ("dynamic Logger Service_Object * ")
359 ACE_TEXT (" ACE:_make_ACE_Logging_Strategy() \"\"")
360 #else
361 ACE_TEXT ("<dynamic id=\"Logger\" type=\"Service_Object\">")
362 ACE_TEXT (" <initializer init=\"_make_ACE_Logging_Strategy\" ")
363 ACE_TEXT (" path=\"ACE\" params=\"\"/>")
364 ACE_TEXT ("</dynamic>")
365 #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
368 static const ACE_TCHAR *unload_logger =
369 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
370 ACE_TEXT ("remove Logger")
371 #else
372 ACE_TEXT ("<remove id=\"Logger\" />");
373 #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
376 ACE_Reactor *r1 = ACE_Reactor::instance();
378 // Ensure no errors are logged while searching for a valid ACE lib name;
379 // these skew the scoreboard results.
380 u_long mask = ACE_LOG_MSG->priority_mask (ACE_Log_Msg::PROCESS);
381 ACE_LOG_MSG->priority_mask (mask & ~LM_ERROR, ACE_Log_Msg::PROCESS);
382 ACE_DEBUG ((LM_DEBUG, "Was %x, now %x\n", mask, mask & ~LM_ERROR));
383 int error_count = ACE_Service_Config::process_directive (load_logger);
384 ACE_LOG_MSG->priority_mask (mask);
385 if (error_count != 0)
387 ++error;
388 ACE_ERROR ((LM_ERROR,
389 ACE_TEXT ("Load ACE Logger should have returned 0; ")
390 ACE_TEXT ("returned %d instead\n"),
391 error_count));
393 ACE_Service_Config::process_directive (unload_logger);
395 ACE_Reactor *r2 = ACE_Reactor::instance ();
396 if (r1 != r2)
397 ACE_ERROR ((LM_ERROR, ACE_TEXT ("Reactor before %@, after %@\n"), r1, r2));
401 // @brief The size of a repository is unlimited and can be exceeded
402 void
403 testLimits (int , ACE_TCHAR *[])
405 static const ACE_TCHAR *svc_desc1 =
406 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
407 ACE_TEXT ("dynamic Test_Object_1_More Service_Object * ")
408 ACE_TEXT (" Service_Config_DLL:_make_Service_Config_DLL() \"Test_Object_1_More\"")
409 #else
410 ACE_TEXT ("<dynamic id=\"Test_Object_1_More\" type=\"Service_Object\">")
411 ACE_TEXT (" <initializer init=\"_make_Service_Config_DLL\" path=\"Service_Config_DLL\" params=\"Test_Object_1_More\"/>")
412 ACE_TEXT ("</dynamic>")
413 #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
416 static const ACE_TCHAR *svc_desc2 =
417 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
418 ACE_TEXT ("dynamic Test_Object_2_More Service_Object * ")
419 ACE_TEXT (" Service_Config_DLL:_make_Service_Config_DLL() \"Test_Object_2_More\"")
420 #else
421 ACE_TEXT ("<dynamic id=\"Test_Object_2_More\" type=\"Service_Object\">")
422 ACE_TEXT (" <initializer init=\"_make_Service_Config_DLL\" path=\"Service_Config_DLL\" params=\"Test_Object_2_More\"/>")
423 ACE_TEXT ("</dynamic>")
424 #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
427 u_int error0 = error;
429 // Ensure enough room for one in a own, the repository can extend
430 ACE_Service_Gestalt one (1, true);
432 // Add two.
433 // We cant simply rely on the fact that insertion fails, because it
434 // is typical to have no easy way of getting detailed error
435 // information from a parser.
436 one.process_directive (svc_desc1);
437 one.process_directive (svc_desc2);
439 if (-1 == one.find (ACE_TEXT ("Test_Object_1_More"), 0, 0))
441 ++error;
442 ACE_ERROR ((LM_ERROR, ACE_TEXT("Expected to have registered the first service\n")));
445 if (-1 == one.find (ACE_TEXT ("Test_Object_2_More"), 0, 0))
447 ++error;
448 ACE_ERROR ((LM_ERROR, ACE_TEXT("Expected to have registered the second service\n")));
452 ACE_GUARD (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, one.current_service_repository ()->lock ());
454 ACE_Service_Repository_Iterator sri (*one.current_service_repository (), 0);
456 size_t index = 0;
457 for (const ACE_Service_Type *sr;
458 sri.next (sr) != 0;
459 sri.advance ())
461 if (index == 0 && ACE_OS::strcmp (sr->name(), ACE_TEXT ("Test_Object_1_More")) != 0)
463 ++error;
464 ACE_ERROR ((LM_ERROR, ACE_TEXT("Service 1 is wrong\n")));
466 if (index == 1 && ACE_OS::strcmp (sr->name(), ACE_TEXT ("Test_Object_2_More")) != 0)
468 ++error;
469 ACE_ERROR ((LM_ERROR, ACE_TEXT("Service 2 is wrong\n")));
471 ++index;
475 // Test close
476 one.current_service_repository ()->close();
478 if (one.current_service_repository ()->current_size () != 0)
480 ++error;
481 ACE_ERROR ((LM_ERROR, ACE_TEXT("Size of repository should be 0\n")));
484 if (error == error0)
485 ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Limits test completed successfully\n")));
486 else
487 ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Limits test failed\n")));
490 void
491 testrepository (int, ACE_TCHAR *[])
493 MyRepository repository;
494 ACE_DLL handle;
495 ACE_Service_Type s0 (ACE_TEXT ("0"), 0, handle, false);
496 ACE_Service_Type s1 (ACE_TEXT ("1"), 0, handle, false);
497 ACE_Service_Type s2 (ACE_TEXT ("2"), 0, handle, false);
498 ACE_Service_Type s3 (ACE_TEXT ("3"), 0, handle, false);
499 ACE_Service_Type* result = 0;
500 repository.insert (&s0);
501 if (repository.current_size () != 1)
503 ++error;
504 ACE_ERROR ((LM_ERROR,
505 ACE_TEXT ("Repository was wrong size %d\n"),
506 repository.current_size ()));
508 repository.insert (&s1);
509 if (repository.current_size () != 2)
511 ++error;
512 ACE_ERROR ((LM_ERROR,
513 ACE_TEXT ("Repository was wrong size %d\n"),
514 repository.current_size ()));
516 repository.insert (&s2);
517 if (repository.current_size () != 3)
519 ++error;
520 ACE_ERROR ((LM_ERROR,
521 ACE_TEXT ("Repository was wrong size %d\n"),
522 repository.current_size ()));
524 if (repository.remove (ACE_TEXT ("1"), &result) != 0)
526 ++error;
527 ACE_ERROR ((LM_ERROR,
528 ACE_TEXT ("Remove failed\n")));
530 if (repository.current_size () != 3)
532 ++error;
533 ACE_ERROR ((LM_ERROR,
534 ACE_TEXT ("Repository was wrong size %d\n"),
535 repository.current_size ()));
537 if (repository.array ()[1] != 0)
539 ++error;
540 ACE_ERROR ((LM_ERROR,
541 ACE_TEXT ("Element 1 not zero\n"),
542 repository.current_size ()));
544 repository.insert (&s3);
545 if (repository.current_size () != 4)
547 ++error;
548 ACE_ERROR ((LM_ERROR,
549 ACE_TEXT ("Repository was wrong size %d\n"),
550 repository.current_size ()));
552 repository.remove (ACE_TEXT ("0"), &result);
553 if (repository.remove (ACE_TEXT ("1"), &result) != -1)
555 ++error;
556 ACE_ERROR ((LM_ERROR,
557 ACE_TEXT ("Double remove didn't return -1\n")));
559 repository.remove (ACE_TEXT ("2"), &result);
560 repository.remove (ACE_TEXT ("3"), &result);
561 if (repository.current_size () != 4)
563 ++error;
564 ACE_ERROR ((LM_ERROR,
565 ACE_TEXT ("Repository was wrong size %d\n"),
566 repository.current_size ()));
568 repository.close ();
569 if (repository.current_size () != 0)
571 ++error;
572 ACE_ERROR ((LM_ERROR,
573 ACE_TEXT ("Repository was wrong size %d\n"),
574 repository.current_size ()));
578 // @brief ??
579 void
580 testOrderlyInstantiation (int , ACE_TCHAR *[])
582 for (u_int i = 0; i < VARIETIES; ++i)
584 Test_Singleton *s = Test_Singleton::instance (i);
586 if (s == 0)
588 ++error;
589 ACE_ERROR ((LM_ERROR,
590 ACE_TEXT ("instance () allocate failed!\n")));
595 // This test verifies that services loaded by a normal ACE startup can be
596 // located from a thread spawned outside of ACE's control.
598 // To do this, we need a native thread entry and, thus, it needs special care
599 // for each platform type. Feel free to add more platforms as needed here and
600 // in main() where the test is called.
601 #if defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_PTHREADS)
602 # if defined (ACE_HAS_WTHREADS)
603 extern "C" unsigned int __stdcall
604 # else
605 extern "C" ACE_THR_FUNC_RETURN
606 # endif
607 nonacethreadentry (void *args)
609 ACE_Log_Msg::inherit_hook (0, *(ACE_OS_Log_Msg_Attributes *)args);
611 if (ACE_Service_Config::instance()->find(ACE_TEXT("Test_Object_1_Thr")) != 0)
613 ACE_ERROR ((LM_ERROR,
614 ACE_TEXT ("In thr %t cannot find Test_Object_1_Thr ")
615 ACE_TEXT ("via ACE_Service_Config\n")));
616 ++error;
618 else
619 ACE_DEBUG ((LM_DEBUG,
620 ACE_TEXT ("In thr %t, located Test_Object_1_Thr ")
621 ACE_TEXT ("via ACE_Service_Config\n")));
623 if (0 != ACE_Service_Repository::instance()->find
624 (ACE_TEXT("Test_Object_1_Thr")))
626 ACE_ERROR ((LM_ERROR,
627 ACE_TEXT ("In thr %t cannot find Test_Object_1_Thr ")
628 ACE_TEXT ("via ACE_Service_Repository\n")));
629 ++error;
631 else
632 ACE_DEBUG ((LM_DEBUG,
633 ACE_TEXT ("In thr %t, located Test_Object_1_Thr ")
634 ACE_TEXT ("via ACE_Service_Repository\n")));
636 return 0;
639 void
640 testNonACEThread ()
642 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Beginning non-ACE thread lookup test\n")));
644 static const ACE_TCHAR *svc_desc =
645 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
646 ACE_TEXT ("dynamic Test_Object_1_Thr Service_Object * ")
647 ACE_TEXT (" Service_Config_DLL:_make_Service_Config_DLL() \"Test_Object_1_Thr\"")
648 #else
649 ACE_TEXT ("<dynamic id=\"Test_Object_1_Thr\" type=\"Service_Object\">")
650 ACE_TEXT (" <initializer init=\"_make_Service_Config_DLL\" path=\"Service_Config_DLL\" params=\"Test_Object_1_Thr\"/>")
651 ACE_TEXT ("</dynamic>")
652 #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
655 static const ACE_TCHAR *svc_remove =
656 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
657 ACE_TEXT ("remove Test_Object_1_Thr")
658 #else
659 ACE_TEXT ("<remove id=\"Test_Object_1_Thr\"/>")
660 ACE_TEXT ("</remove>")
661 #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
664 if (-1 == ACE_Service_Config::process_directive (svc_desc))
666 ACE_ERROR ((LM_ERROR,
667 ACE_TEXT ("%p\n"),
668 ACE_TEXT ("Error loading service")));
669 ++error;
670 return;
673 // Allow the spawned thread to contribute to the logging output.
674 ACE_OS_Log_Msg_Attributes log_msg_attrs;
675 ACE_Log_Msg::init_hook (log_msg_attrs);
677 u_int errors_before = error;
679 #if defined (ACE_HAS_WTHREADS)
680 HANDLE thr_h = (HANDLE)_beginthreadex (0,
682 &nonacethreadentry,
683 &log_msg_attrs,
686 if (thr_h == 0)
688 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("_beginthreadex")));
689 ++error;
691 else
693 WaitForSingleObject (thr_h, INFINITE);
694 CloseHandle (thr_h);
696 #elif defined (ACE_HAS_PTHREADS)
697 pthread_t thr_id;
698 int status = pthread_create (&thr_id, 0, nonacethreadentry, &log_msg_attrs);
699 if (status != 0)
701 errno = status;
702 ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("pthread_create")));
703 ++error;
705 else
707 pthread_join (thr_id, 0);
709 #endif
711 if (error != errors_before) // The test failed; see if we can still see it
713 if (0 != ACE_Service_Config::instance()->find (ACE_TEXT ("Test_Object_1_Thr")))
715 ACE_ERROR ((LM_ERROR,
716 ACE_TEXT ("Main thr %t cannot find Test_Object_1_Thr\n")));
717 ++error;
719 else
720 ACE_DEBUG ((LM_DEBUG,
721 ACE_TEXT ("Main thr %t DOES find Test_Object_1_Thr\n")));
724 if (-1 == ACE_Service_Config::process_directive (svc_remove))
726 ACE_ERROR ((LM_ERROR,
727 ACE_TEXT ("%p\n"),
728 ACE_TEXT ("Error removing service")));
729 ++error;
731 else
733 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Non-ACE thread lookup test completed\n")));
736 #endif /* ACE_HAS_WTHREADS || ACE_HAS_PTHREADS */
739 run_main (int argc, ACE_TCHAR *argv[])
741 ACE_START_TEST (ACE_TEXT ("Service_Config_Test"));
743 testOrderlyInstantiation (argc, argv);
744 testFailedServiceInit (argc, argv);
745 testLoadingServiceConfFile (argc, argv);
746 testLoadingServiceConfFileAndProcessNo (argc, argv);
747 testUnloadingACELoggingStrategy (argc, argv);
748 testLimits (argc, argv);
749 testrepository (argc, argv);
750 #if defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_PTHREADS)
751 unsigned int n_threads = 64;
752 #if defined (ACE_DEFAULT_THREAD_KEYS)
753 n_threads = 2 * ACE_DEFAULT_THREAD_KEYS;
754 #endif
755 // Test with a large amount of threads to determine whether
756 // TSS works correctly with non ACE threads
757 for (unsigned int i = 0 ; i < n_threads; i++)
759 testNonACEThread();
761 #endif
763 ACE_END_TEST;
764 return error;