#ifndef TAO_TESTCOMBINEDTHREADS_H
#define TAO_TESTCOMBINEDTHREADS_H

//============================================================================
/**
 *  @file TestCombinedThreads.h
 *
 *  TestCombinedThreads.h,v 1.1 2001/08/28 15:45:13 oci Exp
 *
 *  A small test framework library for VxWorks
 *
 *  @author Chad Elliott (elliott_c@ociweb.com)
 *
 */
//============================================================================

// *******************************************************************
// Include files.
// *******************************************************************

#include "ace/OS.h"
#include "ace/Auto_Ptr.h"

// *******************************************************************
// Typedefs, forward declarations and defines
// *******************************************************************

class ACE_CString;

typedef int (*TEST_MAIN_TYPE_FUNC)(int, char**);
#define TEST_MAIN_FUNC_DECLARE(X) int X(int argc, char** argv)
#ifndef FULL_PATH
# define FULL_PATH "."
#endif

// *******************************************************************
// Class declaration.
// *******************************************************************

/**
 * @class TAO_TestCombinedThreads
 *
 * @brief Test Framework for VxWorks
 *
 * This class provides run_test type functionality for VxWorks
 * modules.  This class is used by c++ files generated by the
 * perltest2cpp.pl and vxworks_modify.pl perl scripts.
 */

class TAO_TestCombinedThreads
{
public:
  /// func is a function that looks like main(int argc, char** argv).
  /// args are the arguments that will be passed to main, it must be NULL
  /// termintated.
  TAO_TestCombinedThreads (TEST_MAIN_TYPE_FUNC func,
                           char** args);
  TAO_TestCombinedThreads (const TAO_TestCombinedThreads& rhs);
  virtual ~TAO_TestCombinedThreads (void);

  TAO_TestCombinedThreads& operator= (const TAO_TestCombinedThreads& rhs);

  /// spawn a thread and call the main type function.
  /// if timeout is == 0, then do not provide a timeout value
  /// for any orb->run() calls that were hacked by the vxworks_modify.pl script
  virtual int            run (unsigned int timeout = 0);

  /// Wait for all threads
  /// if timeout is == 0, wait forever.
  int                    wait (unsigned int seconds = 0);

  /// Wait for the existance of the specified file for the givent amount
  /// of seconds
  static int             waitForFileTimed (const char* file,
                                           unsigned int seconds);

  /// Return the orb id associated with the current thread id
  static const char*     getORBId (void);

  /// Get the timeout value for the current thread id
  static ACE_Time_Value* getTimeout (void);

  /// Get a random port base between 0 and 32767
  static int             getRandomPortBase (void);

  /// Wait on the specified thread name
  static int             thr_join (ACE_thread_t thr_handle,
                                   ACE_thread_t *thr_id,
                                   void** status = 0);

  /// Wait on the specified thread handle
  static int             thr_join (ACE_hthread_t thr_handle,
                                   void** status = 0);

  /// Returns a random string based on the starting point
  static ACE_CString     getRandomString (const char* base);

protected:
  /// This constructor is functionaly the same as the
  /// public constructor.  It has an extra parameter which is
  /// used by the TestServices class.
  TAO_TestCombinedThreads (TEST_MAIN_TYPE_FUNC func,
                           char** args,
                           int namingServiceHack);

private:
  struct TestArgs
  {
    TEST_MAIN_TYPE_FUNC func_;
    int                 argc_;
    char**              argv_;
    ACE_Time_Value      timeout_;
  };

  /// Initialize the object
  void                   initialize (TEST_MAIN_TYPE_FUNC func = 0,
                                     char** args = 0);

  /// Copy an argv array
  int                    copyArgv (char** argv,
                                   char**& dest);

  /// Delete the copied arguments.
  void                   deleteArguments (char** args);

  /// Static function called by the thread manager
  static void*           spawned (void* args);

  /// Set the timeout for the current thread
  static void            setTimeout (ACE_Time_Value timeout);

  void                   addNamingServiceTimeout (unsigned int timeout);

  /// Associates the given orb id with the current thread id
  static void            associateORB (const char* orbId);
  /// Disassociates the current thread id with its associated orb id
  static void            disassociateORB (void);

  /// Allocate the ORB id map
  static void            allocateORBIdMap (void);
  /// Used by the object manager to delete the ORB id map
  static void            cleanORBIdMap (void* object, void* params);

  /// Allocate the time value map
  static void            allocateTimeMap (void);
  /// Used by the object manager to delete the time value map
  static void            cleanTimeMap (void* object, void* params);

  /// Delete the thread manager
  static void            destroyThreadManager (void* object, void* params);

  TestArgs                 testArgs_;
  auto_ptr<ACE_Time_Value> timeout_;
  int                      namingServiceHack_;
  char**                   args_;
};

#endif /* TAO_TESTCOMBINEDTHREADS_H */
