⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 labview_test_controller.cpp

📁 最新的版本ACE-5.6.8,刚从外文网上搬下,与大家分享.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        }
    }
  else
    {
      this->reply ("Unrecognized command\n");
      return -1;
    }
  return 0;
}

int
Peer::reply (const char *msg)
{
  int len = (int)strlen (msg);    // size_t -> int
  return send (this->handle_, msg, len, 0) > 0 ? 0 : -1;
}

Test::~Test ()
{
  this->cleanup ();
}

int
Test::run (void)
{
  this->running_ = true;
  try
    {
      this->status_ = (this->entry_) (this->argc_, this->argv_);
    }
  catch (...)
    {
      // Try to note this exception then save the log file before bailing out.
      DWORD bl;
      char msg[256];
      sprintf (msg, "Exception in %s caught by labview_test_controller\n",
               this->name_);
      WriteFile (logf, msg, (DWORD)strlen(msg), &bl, 0);
      FlushFileBuffers (logf);
      CloseHandle (logf);
      throw;
    }
  this->running_ = false;
  // It's possible to cleanup() here; however, that would introduce a race
  // with start() following beginthreadex(). So do all the cleanup on user
  // action - either getting status, waiting, killing, or running another
  // test. Or, terminating the connection.
  return 0;
}

const char *
Test::start (const char *name)
{
  if (this->running_)
    return "Already running\n";

  const char *msg = 0;

  // Reset test status to not inadvertantly report a previous test.
  this->status_ = -1;
  this->cleanup ();     // Resets cmdline_, argc_, argv_

  // The command line is part-way through being tokenized by strtok(). It
  // left off after the program name. Anything remaining are the command
  // line arguments for the program. Pick off whatever is there, copy it
  // to the cmdline_ array and fill in argc_/argv_ for the eventual run.
  strcpy (this->name_, name);
  this->argv_[0] = this->name_;
  this->argc_ = 1;
  size_t cmdchars = 0;
  for (char *token = strtok (0, "\t \n\r");
       token != 0 && (cmdchars + strlen (token) + 1) < CMDLINE_LEN;
       token = strtok (0, "\t \n\r"))
    {
      // We have a new token and it will fit in cmdline_. Copy it to the
      // next spot in cmdline_, add it to argv_/argc_ then update cmdchars
      // to account for the copied-in token and its nul terminator.
      strcpy (&this->cmdline_[cmdchars], token);
      this->argv_[this->argc_] = &this->cmdline_[cmdchars];
      ++this->argc_;
      cmdchars += (strlen (token) + 1);
    }
  char libspec[1024];
  sprintf (libspec, "%s.dll", name);
  if ((this->dll_handle_ = LoadLibrary (libspec)) == NULL)
    return format_errmsg (GetLastError (), libspec);

  this->entry_ = (TEST_FUNC) GetProcAddress (this->dll_handle_, "main");
  if (this->entry_ == NULL)
    {
      msg = format_errmsg (GetLastError (), "main");
      this->cleanup ();
      return msg;
    }
  else
    {
      unsigned int thread_id; /* unused */
      uintptr_t h = _beginthreadex (0,             // security
                                    1024 * 1024,   // stack size
                                    run_test,      // entrypoint
                                    (void *)this,  // arglist
                                    0,             // initflag
                                    &thread_id);   // thread ID
      this->thr_handle_ = (HANDLE) h;
      if (h == 0)         // Test thread may have access to thr_handle_
        {
          msg = format_errmsg (GetLastError (), "spawn");
          this->cleanup ();
          return msg;
        }
    }
  return 0;
}

bool
Test::status (int *exit_status)
{
  if (this->running_)
    return false;   // still running

  *exit_status = this->status_;
  this->cleanup ();
  return true;
}

int
Test::wait (void)
{
  WaitForSingleObject (this->thr_handle_, INFINITE);
  if (!this->running_)
    this->cleanup ();
  return this->status_;
}

void
Test::kill (void)
{
  TerminateThread (this->thr_handle_, -1);
  this->cleanup ();
  this->running_ = false;
  this->status_  = -1;
}

// Clean up remnants of a test run.
void
Test::cleanup (void)
{
  if (this->dll_handle_ != NULL)
    {
      FreeLibrary (this->dll_handle_);
      this->dll_handle_ = NULL;
    }
  if (this->thr_handle_ != 0)
    {
      CloseHandle (this->thr_handle_);
      this->thr_handle_ = 0;
    }
  this->entry_   = 0;
  this->argc_ = 0;
  for (int i = 0; i < ARGV_SIZE; ++i)
    this->argv_[i] = 0;
  memset (this->cmdline_, 0, CMDLINE_LEN);
}

static unsigned int __stdcall
test_control (void * /* param */)
{
  // cd to ace dir?? (can this be an env variable?)

  // redirect stdout/stderr to a file
  logf = CreateFile (LogName,
                     FILE_ALL_ACCESS,
                     FILE_SHARE_READ,
                     0,                  // security
                     OPEN_ALWAYS,        // Don't crush a previous one
                     FILE_ATTRIBUTE_NORMAL,
                     0);
  if (logf == INVALID_HANDLE_VALUE)
    perror (LogName);
  else
    {
      SetFilePointer (logf, 0, 0, FILE_END);   // Append new content
      SetStdHandle (STD_OUTPUT_HANDLE, logf);
      SetStdHandle (STD_ERROR_HANDLE, logf);
    }

  WORD want;
  WSADATA offer;
  want = MAKEWORD (2, 2);
  if (0 != WSAStartup (want, &offer))
    {
      perror ("WSAStartup");
      CloseHandle (logf);
      return WSAGetLastError ();
    }

  // listen on port 8888 (can I set an env variable for this?)
  SOCKET acceptor = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  sockaddr_in listen_addr;
  memset (&listen_addr, 0, sizeof (listen_addr));
  listen_addr.sin_family = AF_INET;
  listen_addr.sin_addr.s_addr = INADDR_ANY;
  listen_addr.sin_port = htons (8888);
  if (SOCKET_ERROR == bind (acceptor,
                            (struct sockaddr *)&listen_addr,
                            sizeof (listen_addr)))
    {
      perror ("bind");
    }
  else
    {
      listen (acceptor, 10);
      SOCKET peer;
      while ((peer = accept (acceptor, 0, 0)) != INVALID_SOCKET)
        {
          Peer *p = new Peer (peer);
          if (p == 0)
            {
              perror ("Out of memory");
              closesocket (peer);
              peer = INVALID_SOCKET;
              continue;
            }
          if (0 == _beginthreadex (0,            // security
                                   64 * 1024,    // stack size
                                   peer_svc,     // entrypoint
                                   (void *)p,    // param
                                   0,            // creation flags
                                   0))           // ptr to thread id
            {
              perror ("beginthreadex peer");
              closesocket (peer);
              delete p;
            }
          p = 0;
          peer = INVALID_SOCKET;
        }
      perror ("accept");
    }

  closesocket (acceptor);
  WSACleanup ();
  return 0;
}

// Entrypoint for thread that's spawned to run a peer's session. Direct
// control to the peer class.
static unsigned int __stdcall
peer_svc (void *peer_p)
{
  Peer *p = (Peer *)peer_p;
  DWORD status = p->svc ();
  delete p;
  return status;
}

// Entrypoint for the thread spawned to run a test. The thread arg is the
// Test * - call back to the test's run() method; return the test exit code
// as the thread's return value.
static unsigned int __stdcall
run_test (void *test_p)
{
  Test *t = (Test *)test_p;
  return t->run ();
}

// Format a Windows system or Winsock error message given an error code.
static const char *
format_errmsg (unsigned int errcode, const char *prefix)
{
  static const size_t errmsgsize = 1024;
  static char errmsg[errmsgsize];

  sprintf (errmsg, "%s: ", prefix);
  size_t len = strlen (errmsg);
  char *next = &errmsg[len];
  size_t max_fmt = errmsgsize - len;
  if (0 != FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
                          FORMAT_MESSAGE_IGNORE_INSERTS,
                          0,
                          errcode,
                          0,                 // Use default language
                          next,
                          (DWORD)max_fmt,
                          0))
    {
      strcat (errmsg, "\n");
      return errmsg;
    }

  errno = errcode;
  char *msg = _strerror (prefix);
  sprintf (errmsg, "err %d: %s", errcode, msg);
  return errmsg;
}

#ifdef TEST_RUNNER_EXPORTS
#define TEST_RUNNER_API __declspec(dllexport)
#else
#define TEST_RUNNER_API __declspec(dllimport)
#endif

__declspec(dllexport) int test_entry(void)
{
  return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -