Asterisk - The Open Source Telephony Project GIT-master-f36a736
Data Structures | Macros | Typedefs | Functions
stasis_test.h File Reference

Test infrastructure for dealing with Stasis. More...

#include "asterisk/lock.h"
#include "asterisk/stasis.h"
Include dependency graph for stasis_test.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  stasis_message_sink
 Structure that collects messages from a topic. More...
 

Macros

#define STASIS_SINK_DEFAULT_WAIT   5000
 

Typedefs

typedef int(* stasis_wait_cb) (struct stasis_message *msg, const void *data)
 

Functions

stasis_subscription_cb stasis_message_sink_cb (void)
 Topic callback to receive messages. More...
 
struct stasis_message_sinkstasis_message_sink_create (void)
 Create a message sink. More...
 
int stasis_message_sink_should_stay (struct stasis_message_sink *sink, int num_messages, int timeout_millis)
 Ensures that no new messages are received. More...
 
int stasis_message_sink_wait_for (struct stasis_message_sink *sink, int start, stasis_wait_cb cmp_cb, const void *data, int timeout_millis)
 Wait for a message that matches the given criteria. More...
 
int stasis_message_sink_wait_for_count (struct stasis_message_sink *sink, int num_messages, int timeout_millis)
 Wait for a sink's num_messages field to reach a certain level. More...
 
struct stasis_messagestasis_test_message_create (void)
 Creates a test message. More...
 
struct stasis_message_typestasis_test_message_type (void)
 Gets the type of messages created by stasis_test_message_create(). More...
 

Detailed Description

Test infrastructure for dealing with Stasis.

Author
David M. Lee, II dlee@.nosp@m.digi.nosp@m.um.co.nosp@m.m

This file contains some helpful utilities for testing Stasis related topics and messages. The stasis_message_sink is something you can subscribe to a topic which will receive all of the messages from the topic. This messages are accumulated in its messages field.

There are a set of wait functions (stasis_message_sink_wait_for_count(), stasis_message_sink_wait_for(), etc.) which will block waiting for conditions to be met in the stasis_message_sink.

Definition in file stasis_test.h.

Macro Definition Documentation

◆ STASIS_SINK_DEFAULT_WAIT

#define STASIS_SINK_DEFAULT_WAIT   5000

Definition at line 41 of file stasis_test.h.

Typedef Documentation

◆ stasis_wait_cb

typedef int(* stasis_wait_cb) (struct stasis_message *msg, const void *data)

Definition at line 95 of file stasis_test.h.

Function Documentation

◆ stasis_message_sink_cb()

stasis_subscription_cb stasis_message_sink_cb ( void  )

Topic callback to receive messages.

We return a function pointer instead of simply exposing the function because of the vagaries of dlopen(), RTLD_LAZY, and function pointers. See the comment on the implementation for details why.

Returns
Function pointer to stasis_message_sink's message handling function

Definition at line 143 of file res_stasis_test.c.

144{
145 return message_sink_cb;
146}
static void message_sink_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Implementation of the stasis_message_sink_cb() callback.

References message_sink_cb().

Referenced by AST_TEST_DEFINE().

◆ stasis_message_sink_create()

struct stasis_message_sink * stasis_message_sink_create ( void  )

Create a message sink.

This is an AO2 managed object, which you ao2_cleanup() when done. The destructor waits for an unsubscribe message to be received, to ensure the object isn't disposed of before the topic is finished.

Definition at line 79 of file res_stasis_test.c.

80{
82
83 sink = ao2_alloc(sizeof(*sink), stasis_message_sink_dtor);
84 if (!sink) {
85 return NULL;
86 }
87 ast_mutex_init(&sink->lock);
88 ast_cond_init(&sink->cond, NULL);
89 sink->max_messages = 4;
90 sink->messages =
91 ast_malloc(sizeof(*sink->messages) * sink->max_messages);
92 if (!sink->messages) {
93 return NULL;
94 }
95 ao2_ref(sink, +1);
96 return sink;
97}
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
static void stasis_message_sink_dtor(void *obj)
#define NULL
Definition: resample.c:96
Structure that collects messages from a topic.
Definition: stasis_test.h:44
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_alloc, ao2_cleanup, ao2_ref, ast_cond_init, ast_malloc, ast_mutex_init, NULL, RAII_VAR, and stasis_message_sink_dtor().

Referenced by AST_TEST_DEFINE().

◆ stasis_message_sink_should_stay()

int stasis_message_sink_should_stay ( struct stasis_message_sink sink,
int  num_messages,
int  timeout_millis 
)

Ensures that no new messages are received.

The optional timeout prevents complete deadlock in a test.

Parameters
sinkSink to wait on.
num_messagesexpecte sink->num_messages.
timeout_millisNumber of milliseconds to wait for.
Returns
Actual sink->num_messages value at return. If this is < num_messages, then the timeout expired.

Definition at line 170 of file res_stasis_test.c.

172{
173 struct timespec deadline = make_deadline(timeout_millis);
174
175 SCOPED_MUTEX(lock, &sink->lock);
176 while (sink->num_messages == num_messages) {
177 int r = ast_cond_timedwait(&sink->cond, &sink->lock, &deadline);
178
179 if (r == ETIMEDOUT) {
180 break;
181 }
182 if (r != 0) {
183 ast_log(LOG_ERROR, "Unexpected condition error: %s\n",
184 strerror(r));
185 break;
186 }
187 }
188 return sink->num_messages;
189}
ast_mutex_t lock
Definition: app_sla.c:331
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
Definition: lock.h:589
static struct timespec make_deadline(int timeout_millis)
ast_mutex_t lock
Definition: stasis_test.h:46

References ast_cond_timedwait, ast_log, stasis_message_sink::cond, lock, stasis_message_sink::lock, LOG_ERROR, make_deadline(), stasis_message_sink::num_messages, and SCOPED_MUTEX.

◆ stasis_message_sink_wait_for()

int stasis_message_sink_wait_for ( struct stasis_message_sink sink,
int  start,
stasis_wait_cb  cmp_cb,
const void *  data,
int  timeout_millis 
)

Wait for a message that matches the given criteria.

Parameters
sinkSink to wait on.
startIndex of message to start with.
cmp_cbcomparison function. This returns true (non-zero) on match and false (zero) on match.
data
timeout_millisNumber of milliseconds to wait.
Returns
Index of the matching message.
Negative for no match.

Definition at line 191 of file res_stasis_test.c.

193{
194 struct timespec deadline = make_deadline(timeout_millis);
195
196 SCOPED_MUTEX(lock, &sink->lock);
197
198 /* wait for the start */
199 while (sink->num_messages < start + 1) {
200 int r = ast_cond_timedwait(&sink->cond, &sink->lock, &deadline);
201
202 if (r == ETIMEDOUT) {
203 /* Timed out waiting for the start */
204 return -1;
205 }
206 if (r != 0) {
207 ast_log(LOG_ERROR, "Unexpected condition error: %s\n",
208 strerror(r));
209 return -2;
210 }
211 }
212
213
214 while (!cmp_cb(sink->messages[start], data)) {
215 ++start;
216
217 while (sink->num_messages < start + 1) {
218 int r = ast_cond_timedwait(&sink->cond,
219 &sink->lock, &deadline);
220
221 if (r == ETIMEDOUT) {
222 return -1;
223 }
224 if (r != 0) {
226 "Unexpected condition error: %s\n",
227 strerror(r));
228 return -2;
229 }
230 }
231 }
232
233 return start;
234}
struct stasis_message ** messages
Definition: stasis_test.h:57

References ast_cond_timedwait, ast_log, stasis_message_sink::cond, lock, stasis_message_sink::lock, LOG_ERROR, make_deadline(), stasis_message_sink::messages, stasis_message_sink::num_messages, and SCOPED_MUTEX.

Referenced by AST_TEST_DEFINE().

◆ stasis_message_sink_wait_for_count()

int stasis_message_sink_wait_for_count ( struct stasis_message_sink sink,
int  num_messages,
int  timeout_millis 
)

Wait for a sink's num_messages field to reach a certain level.

The optional timeout prevents complete deadlock in a test.

Parameters
sinkSink to wait on.
num_messagessink->num_messages value to wait for.
timeout_millisNumber of milliseconds to wait. -1 to wait forever.
Returns
Actual sink->num_messages value at return. If this is < num_messages, then the timeout expired.

Definition at line 149 of file res_stasis_test.c.

151{
152 struct timespec deadline = make_deadline(timeout_millis);
153
154 SCOPED_MUTEX(lock, &sink->lock);
155 while (sink->num_messages < num_messages) {
156 int r = ast_cond_timedwait(&sink->cond, &sink->lock, &deadline);
157
158 if (r == ETIMEDOUT) {
159 break;
160 }
161 if (r != 0) {
162 ast_log(LOG_ERROR, "Unexpected condition error: %s\n",
163 strerror(r));
164 break;
165 }
166 }
167 return sink->num_messages;
168}

References ast_cond_timedwait, ast_log, stasis_message_sink::cond, lock, stasis_message_sink::lock, LOG_ERROR, make_deadline(), stasis_message_sink::num_messages, and SCOPED_MUTEX.

Referenced by AST_TEST_DEFINE().