summaryrefslogtreecommitdiff
path: root/tests/SOCK_Connector_Test.cpp
blob: 090bf3a792188e69b2f14fd9dd63e78eb3237549 (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
// $Id$

// ============================================================================
//
// = LIBRARY
//    tests
//
// = FILENAME
//    SOCK_Connector_Test.cpp
//
// = DESCRIPTION
//     This is a test of ACE_SOCK_Connector, focusing on failure cases more
//     than on success cases.
//
// = AUTHOR
//    Steve Huston
//
// ============================================================================

#include "ace/OS.h"
#include "ace/INET_Addr.h"
#include "ace/SOCK_Connector.h"
#include "ace/SOCK_Stream.h"
#include "test_config.h"

// The original problem this program tested for was incorrectly saying
// a non-blocking connect completed successfully when it didn't.  The
// test doesn't always work when done to localhost
// (platform-dependant) so we look around for another host - any other
// one will do.

static void
find_another_host (ASYS_TCHAR other_host[])
{
  ACE_OS::strcpy (other_host, ACE_DEFAULT_SERVER_HOST); // If all else fails

#if !defined (ACE_LACKS_GETHOSTENT)
  // These gethost-type things don't work everywhere.
  struct hostent *h;
  struct utsname un;

  ACE_OS::uname (&un);

  h = ACE_OS::gethostbyname (un.nodename);

  // Use me if can't find another
  ACE_OS::strcpy (other_host, ASYS_WIDE_STRING (h->h_name));

  // @@ We really need to add wrappers for these hostent methods.
  sethostent (1);

  while ((h = gethostent ()) != NULL)
    {
      if (ACE_OS::strcmp (h->h_name, ACE_DEFAULT_SERVER_HOST) == 0)
        continue;
      // AIX just _has_ to be different
      if (ACE_OS::strcmp (h->h_name, "loopback") == 0)
        continue;

      // If not me
      if (ACE_OS::strcmp (h->h_name, other_host) != 0 &&
          ACE_OS::strcmp (h->h_name, un.nodename) != 0   )
        {
          ACE_OS::strcpy (other_host, h->h_name);
          break;
        }
    }

  endhostent ();
#endif /* ! ACE_LACKS_GETHOSTENT */
}

static int
fail_no_listener_nonblocking (void)
{
  ASYS_TCHAR test_host[MAXHOSTNAMELEN];
  int status;
  ACE_INET_Addr nobody_home;
  ACE_SOCK_Connector con;
  ACE_SOCK_Stream sock;
  ACE_Time_Value nonblock (0, 0);

  find_another_host (test_host);
  ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("Testing to host %s\n"), test_host));
  nobody_home.set ((u_short) 42000, test_host);
  status = con.connect (sock, nobody_home, &nonblock);

  // Need a port that will fail.
  ACE_ASSERT (status == -1);

  // On some systems, a failed connect to localhost will return
  // ECONNREFUSED or ENETUNREACH directly, instead of
  // EWOULDBLOCK. That is also fine.

  if (errno == EWOULDBLOCK || errno == ECONNREFUSED || errno == ENETUNREACH)
    {
      if (sock.get_handle () != ACE_INVALID_HANDLE)
        status = con.complete (sock);

      if (status != -1)
        {
          ACE_DEBUG ((LM_DEBUG,
                      ASYS_TEXT ("Connect which should fail didn't\n")));
          status = -1;
        }
      else
        {
          ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("%p\n"), ASYS_TEXT ("Proper fail")));
          status = 0;
        }
    }
  else
    {
      ACE_DEBUG ((LM_DEBUG,
                  ASYS_TEXT ("Test not executed fully; expected EWOULDBLOCK, %p\n"),
                  ASYS_TEXT ("not")));
      status = -1;
    }

  // Just in case.
  sock.close ();

  return status;
}

int
main (int, ASYS_TCHAR *[])
{
  ACE_START_TEST (ASYS_TEXT ("SOCK_Connector_Test"));

  int status = 0;

  if (fail_no_listener_nonblocking () == -1)
    status = 1;

  ACE_END_TEST;
  return status;
}