summaryrefslogtreecommitdiff
path: root/TAO/tests/Queued_Message_Test/Queued_Message_Test.cpp
blob: 077d93b459682c1ca95b7de10f5e53bca9c266c2 (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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// ============================================================================
/**
 * @brief Unit test for the TAO_Queued_Message class
 *
 * $Id$
 *
 * @author Carlos O'Ryan <coryan@uci.edu>
 */
// ============================================================================

#include "tao/Asynch_Queued_Message.h"
#include "tao/ORB_Core.h"
#include "ace/Log_Msg.h"
#include "ace/Message_Block.h"
#include "ace/ACE.h"
#include "ace/OS_NS_stdio.h"
#include "ace/OS_NS_time.h"
#include "ace/OS_NS_stdlib.h"

ACE_RCSID (tests,
           Queued_Message_Test,
           "$Id$")

/// Max number of bytes on each message block
const size_t max_block_length = 256;

static TAO_Queued_Message *
create_new_message (void)
{
  // First create a message block
  size_t block_size =
    64 + ACE_OS::rand () % (max_block_length - 64);
  ACE_Message_Block mb (block_size);
  mb.wr_ptr (block_size);

  return new TAO_Asynch_Queued_Message (&mb, TAO_ORB_Core_instance (),
                                        0, 1);
}

/// Add a new message at the tail of the queue.
static void push_back_message (TAO_Queued_Message *&head,
                               TAO_Queued_Message *&tail)
{
  TAO_Queued_Message *msg = create_new_message ();
  msg->push_back (head, tail);
}

/// Add a new message at the head of the queue.
static void push_front_message (TAO_Queued_Message *&head,
                                TAO_Queued_Message *&tail)
{
  TAO_Queued_Message *msg = create_new_message ();
  msg->push_front (head, tail);
}

/// Remove the message at the head of the queue, and simulate the
/// behavior of the I/O subsystem when processing such messages.
static void del_message (TAO_Queued_Message *&head,
                         TAO_Queued_Message *&tail)
{
  // ACE_DEBUG ((LM_DEBUG, "Removing message\n"));
  TAO_Queued_Message *current = head;
  current->remove_from_list (head, tail);

  // Simulate message writing: each message is 'sent' using
  // multiple write() calls, in this simulation, we call the
  // bytes_transferred() method until all messages are removed.

  size_t total_length = current->message_length ();
  while (total_length > 0)
    {
      // select how many bytes we want to 'send' in this iteration.
      size_t t = ACE_OS::rand () % 256 + 1;

      if (t > total_length)
        t = total_length;

      current->bytes_transferred (t);
      total_length -= t;
    }
  if (!current->all_data_sent ())
    {
      ACE_ERROR ((LM_DEBUG,
                  "ERROR: inconsistent state in Queued_Message\n"));
      ACE_OS::exit (1);
    }
  current->destroy ();
}

int
main (int, char *[])
{

  // Initialize a random seed to get better coverage.
  // @@ The random seed and default values should be configurable
  // using command line options.

  ACE_hrtime_t current_hrtime = ACE_OS::gethrtime ();
#if defined(ACE_HRTIME_T_IS_BASIC_TYPE)
  ACE_UINT32 seed = current_hrtime;
#else
  ACE_UINT32 seed =
    ACE_CU64_TO_CU32(current_hrtime);
#endif
  ACE_OS::srand (seed);

  ACE_DEBUG ((LM_DEBUG, "Running test SEED = %d\n", seed));

  TAO_Queued_Message *head = 0;
  TAO_Queued_Message *tail = 0;

  int add_count = 0;
  int del_count = 0;

  const int iterations = 100;
  int i;

  for (i = 0; i != iterations; ++i)
    {
      push_back_message (head, tail);
      add_count++;

      if (ACE_OS::rand () % 100 > 90)
        {
          // every so often remove a message also.
          if (head != 0)
            {
              del_message (head, tail);
              del_count++;
            }
        }
    }

  // second phase, change the probabilities of removing a message.
  for (i = 0; i != iterations; ++i)
    {
      if (ACE_OS::rand () % 100 > 90)
        {
          push_back_message (head, tail); add_count++;
        }
      if (ACE_OS::rand () % 100 > 90)
        {
          push_front_message (head, tail); add_count++;
        }
      if (head != 0)
        {
          del_message (head, tail);
          del_count++;
        }
    }

  // Go through a phase where all messages are removed.
  while (head != 0)
    {
      del_message (head, tail);
      del_count++;
    }

  if (tail != 0)
    {
      ACE_ERROR_RETURN ((LM_ERROR,
                         "ERROR: inconsistent state in message queue\n"),
                        1);
    }

  if (add_count != del_count)
    {
      ACE_ERROR_RETURN ((LM_ERROR,
                         "ERROR: mismatched (%d != %d) add and del counts\n",
                         add_count, del_count),
                        1);
    }


  return 0;
}