Asterisk - The Open Source Telephony Project  18.5.0
test_voicemail_api.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012, Matt Jordan
5  *
6  * Matt Jordan <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief Skeleton Test
22  *
23  * \author\verbatim Matt Jordan <[email protected]> \endverbatim
24  *
25  * Tests for the publicly exposed Voicemail API
26  * \ingroup tests
27  */
28 
29 /*** MODULEINFO
30  <depend>TEST_FRAMEWORK</depend>
31  <support_level>core</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 #include <sys/stat.h>
37 
38 #include "asterisk/utils.h"
39 #include "asterisk/module.h"
40 #include "asterisk/test.h"
41 #include "asterisk/paths.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/app.h"
44 #include "asterisk/format_cache.h"
45 
46 /*!
47  * \internal
48  * \brief Permissions to set on the voicemail directories we create
49  *
50  * \note taken from app_voicemail
51  */
52 #define VOICEMAIL_DIR_MODE 0777
53 
54 /*!
55  * \internal
56  * \brief Permissions to set on the voicemail files we create
57  *
58  * \note taken from app_voicemail
59  */
60 #define VOICEMAIL_FILE_MODE 0666
61 
62 /*!
63  * \internal
64  * \brief The number of mock snapshot objects we use for tests
65  */
66 #define TOTAL_SNAPSHOTS 4
67 
68 /*!
69  * \internal
70  * \brief Create and populate the mock message objects and create the
71  * envelope files on the file system
72  */
73 #define VM_API_TEST_SETUP do { \
74  if (!ast_vm_is_registered()) { \
75  ast_test_status_update(test, "No voicemail provider registered.\n"); \
76  return AST_TEST_FAIL; \
77  } else if (test_vm_api_test_setup()) { \
78  VM_API_TEST_CLEANUP; \
79  ast_test_status_update(test, "Failed to set up necessary mock objects for voicemail API test\n"); \
80  return AST_TEST_FAIL; \
81  } else { \
82  int i = 0; \
83  for (; i < TOTAL_SNAPSHOTS; i++) { \
84  ast_test_status_update(test, "Created message in %s/%s with ID %s\n", \
85  test_snapshots[i]->exten, test_snapshots[i]->folder_name, test_snapshots[i]->msg_id); \
86  } \
87 } } while (0)
88 
89 /*!
90  * \internal
91  * \brief Safely cleanup after a test run.
92  *
93  * \note This should be called both when a test fails and when it passes
94  */
95 #define VM_API_TEST_CLEANUP test_vm_api_test_teardown()
96 
97 /*!
98  * \internal
99  * \brief Safely cleanup a snapshot and a test run.
100  *
101  * \note It assumes that the mailbox snapshot object is test_mbox_snapshot
102  */
103 #define VM_API_SNAPSHOT_TEST_CLEANUP \
104  if (test_mbox_snapshot) { \
105  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot); \
106  } \
107  VM_API_TEST_CLEANUP; \
108 
109 /*!
110  * \internal
111  * \brief Verify the expected result from two string values obtained
112  * from a mailbox snapshot.
113  *
114  * \note It assumes the mailbox snapshot object is test_mbox_snapshot
115  */
116 #define VM_API_STRING_FIELD_VERIFY(expected, actual) do { \
117  if (strcmp((expected), (actual))) { \
118  ast_test_status_update(test, "Test failed for parameter %s: Expected [%s], Actual [%s]\n", #actual, expected, actual); \
119  VM_API_SNAPSHOT_TEST_CLEANUP; \
120  return AST_TEST_FAIL; \
121  } } while (0)
122 
123 /*!
124  * \internal
125  * \brief Verify the expected result from two integer values.
126  *
127  * \note It assumes the mailbox snapshot object is test_mbox_snapshot
128  */
129 #define VM_API_INT_VERIFY(expected, actual) do { \
130  if ((expected) != (actual)) { \
131  ast_test_status_update(test, "Test failed for parameter %s: Expected [%d], Actual [%d]\n", #actual, (int)expected, (int)actual); \
132  VM_API_SNAPSHOT_TEST_CLEANUP; \
133  return AST_TEST_FAIL; \
134  } } while (0)
135 
136 /*!
137  * \internal
138  * \brief Verify that a mailbox snapshot contains the expected message
139  * snapshot, in the correct position, with the expected values.
140  *
141  * \note It assumes the mailbox snapshot object is test_mbox_snapshot
142  */
143 #define VM_API_SNAPSHOT_MSG_VERIFY(expected, actual, expected_folder, expected_index) do { \
144  struct ast_vm_msg_snapshot *msg; \
145  int found = 0; \
146  int counter = 0; \
147  AST_LIST_TRAVERSE(&((actual)->snapshots[get_folder_by_name(expected_folder)]), msg, msg) { \
148  if (!(strcmp(msg->msg_id, (expected)->msg_id))) { \
149  ast_test_status_update(test, "Found message %s in snapshot\n", msg->msg_id); \
150  found = 1; \
151  if ((expected_index) != counter) { \
152  ast_test_status_update(test, "Expected message %s at index %d; Actual [%d]\n", \
153  (expected)->msg_id, (expected_index), counter); \
154  VM_API_SNAPSHOT_TEST_CLEANUP; \
155  return AST_TEST_FAIL; \
156  } \
157  VM_API_STRING_FIELD_VERIFY((expected)->callerid, msg->callerid); \
158  VM_API_STRING_FIELD_VERIFY((expected)->callerchan, msg->callerchan); \
159  VM_API_STRING_FIELD_VERIFY((expected)->exten, msg->exten); \
160  VM_API_STRING_FIELD_VERIFY((expected)->origdate, msg->origdate); \
161  VM_API_STRING_FIELD_VERIFY((expected)->origtime, msg->origtime); \
162  VM_API_STRING_FIELD_VERIFY((expected)->duration, msg->duration); \
163  VM_API_STRING_FIELD_VERIFY((expected)->folder_name, msg->folder_name); \
164  VM_API_STRING_FIELD_VERIFY((expected)->flag, msg->flag); \
165  VM_API_INT_VERIFY((expected)->msg_number, msg->msg_number); \
166  break; \
167  } \
168  ++counter; \
169  } \
170  if (!found) { \
171  ast_test_status_update(test, "Test failed for message snapshot %s: not found in mailbox snapshot\n", (expected)->msg_id); \
172  VM_API_SNAPSHOT_TEST_CLEANUP; \
173  return AST_TEST_FAIL; \
174 } } while (0)
175 
176 
177 /*!
178  * \internal
179  * \brief Create a message snapshot, failing the test if the snapshot could not be created.
180  *
181  * \note This requires having a snapshot named test_mbox_snapshot.
182  */
183 #define VM_API_SNAPSHOT_CREATE(mailbox, context, folder, desc, sort, old_and_inbox) do { \
184  if (!(test_mbox_snapshot = ast_vm_mailbox_snapshot_create( \
185  (mailbox), (context), (folder), (desc), (sort), (old_and_inbox)))) { \
186  ast_test_status_update(test, "Failed to create voicemail mailbox snapshot\n"); \
187  VM_API_TEST_CLEANUP; \
188  return AST_TEST_FAIL; \
189  } } while (0)
190 
191 /*!
192  * \internal
193  * \brief Create a message snapshot, failing the test if the snapshot could be created.
194  *
195  * \note This is used to test off nominal conditions.
196  * \note This requires having a snapshot named test_mbox_snapshot.
197  */
198 #define VM_API_SNAPSHOT_OFF_NOMINAL_TEST(mailbox, context, folder, desc, sort, old_and_inbox) do { \
199  if ((test_mbox_snapshot = ast_vm_mailbox_snapshot_create( \
200  (mailbox), (context), (folder), (desc), (sort), (old_and_inbox)))) { \
201  ast_test_status_update(test, "Created mailbox snapshot when none was expected\n"); \
202  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot); \
203  VM_API_TEST_CLEANUP; \
204  return AST_TEST_FAIL; \
205  } } while (0)
206 
207 /*!
208  * \internal
209  * \brief Move a voicemail message, failing the test if the message could not be moved
210  */
211 #define VM_API_MOVE_MESSAGE(mailbox, context, number_of_messages, source, message_numbers_in, dest) do { \
212  if (ast_vm_msg_move((mailbox), (context), (number_of_messages), (source), (message_numbers_in), (dest))) { \
213  ast_test_status_update(test, "Failed to move message %s@%s from %s to %s\n", \
214  (mailbox) ? (mailbox): "(NULL)", (context) ? (context) : "(NULL)", (source) ? (source) : "(NULL)", (dest) ? (dest) : "(NULL)"); \
215  VM_API_TEST_CLEANUP; \
216  return AST_TEST_FAIL; \
217  } } while (0)
218 
219 /*!
220  * \internal
221  * \brief Attempt to move a voicemail message, failing the test if the message could be moved
222  */
223 #define VM_API_MOVE_MESSAGE_OFF_NOMINAL(mailbox, context, number_of_messages, source, message_numbers_in, dest) do { \
224  if (!ast_vm_msg_move((mailbox), (context), (number_of_messages), (source), (message_numbers_in), (dest))) { \
225  ast_test_status_update(test, "Succeeded to move message %s@%s from %s to %s when we really shouldn't\n", \
226  (mailbox) ? (mailbox): "(NULL)", (context) ? (context) : "(NULL)", (source) ? (source) : "(NULL)", (dest) ? (dest) : "(NULL)"); \
227  VM_API_TEST_CLEANUP; \
228  return AST_TEST_FAIL; \
229  } } while (0)
230 
231 /*!
232  * \internal
233  * \brief Remove a message, failing the test if the method failed or if the message is still present.
234  */
235 #define VM_API_REMOVE_MESSAGE(mailbox, context, number_of_messages, folder, message_numbers_in) do { \
236  if (ast_vm_msg_remove((mailbox), (context), (number_of_messages), (folder), (message_numbers_in))) { \
237  ast_test_status_update(test, "Failed to remove message from mailbox %s@%s, folder %s", \
238  (mailbox) ? (mailbox): "(NULL)", (context) ? (context) : "(NULL)", (folder) ? (folder) : "(NULL)"); \
239  VM_API_TEST_CLEANUP; \
240  return AST_TEST_FAIL; \
241  } \
242  VM_API_SNAPSHOT_CREATE((mailbox), (context), (folder), 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0); \
243  VM_API_INT_VERIFY(0, test_mbox_snapshot->total_msg_num); \
244  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot); \
245 } while (0)
246 
247 /*!
248  * \internal
249  * \brief Remove a message, failing the test if the method succeeds
250  */
251 #define VM_API_REMOVE_MESSAGE_OFF_NOMINAL(mailbox, context, number_of_messages, folder, message_numbers_in) do { \
252  if (!ast_vm_msg_remove((mailbox), (context), (number_of_messages), (folder), (message_numbers_in))) { \
253  ast_test_status_update(test, "Succeeded in removing message from mailbox %s@%s, folder %s, when expected result was failure\n", \
254  (mailbox) ? (mailbox): "(NULL)", (context) ? (context) : "(NULL)", (folder) ? (folder) : "(NULL)"); \
255  VM_API_TEST_CLEANUP; \
256  return AST_TEST_FAIL; \
257  } } while (0)
258 
259 /*!
260  * \internal
261  * \brief Forward a message, failing the test if the message could not be forwarded
262  */
263 # define VM_API_FORWARD_MESSAGE(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, number_of_messages, message_numbers_in, delete_old) do { \
264  if (ast_vm_msg_forward((from_mailbox), (from_context), (from_folder), (to_mailbox), (to_context), (to_folder), (number_of_messages), (message_numbers_in), (delete_old))) { \
265  ast_test_status_update(test, "Failed to forward message from %s@%s [%s] to %s@%s [%s]\n", \
266  (from_mailbox) ? (from_mailbox) : "(NULL)", (from_context) ? (from_context) : "(NULL)", (from_folder) ? (from_folder) : "(NULL)", \
267  (to_mailbox) ? (to_mailbox) : "(NULL)", (to_context) ? (to_context) : "(NULL)", (to_folder) ? (to_folder) : "(NULL)"); \
268  VM_API_TEST_CLEANUP; \
269  return AST_TEST_FAIL; \
270  } } while (0)
271 
272 /*!
273  * \internal
274  * \brief Forward a message, failing the test if the message was successfully forwarded
275  */
276 #define VM_API_FORWARD_MESSAGE_OFF_NOMINAL(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, number_of_messages, message_numbers_in, delete_old) do { \
277  if (!ast_vm_msg_forward((from_mailbox), (from_context), (from_folder), (to_mailbox), (to_context), (to_folder), (number_of_messages), (message_numbers_in), (delete_old))) { \
278  ast_test_status_update(test, "Succeeded in forwarding message from %s@%s [%s] to %s@%s [%s] when expected result was fail\n", \
279  (from_mailbox) ? (from_mailbox) : "(NULL)", (from_context) ? (from_context) : "(NULL)", (from_folder) ? (from_folder) : "(NULL)", \
280  (to_mailbox) ? (to_mailbox) : "(NULL)", (to_context) ? (to_context) : "(NULL)", (to_folder) ? (to_folder) : "(NULL)"); \
281  VM_API_TEST_CLEANUP; \
282  return AST_TEST_FAIL; \
283  } } while (0)
284 
285 /*!
286  * \internal .
287  * \brief Playback a message on a channel or callback function .
288  * .
289  * \note The channel name must be test_channel.
290  * \note Fail the test if the message could not be played.
291  */
292 #define VM_API_PLAYBACK_MESSAGE(channel, mailbox, context, folder, message, callback_fn) do { \
293  if (ast_vm_msg_play((channel), (mailbox), (context), (folder), (message), (callback_fn))) { \
294  ast_test_status_update(test, "Failed nominal playback message test\n"); \
295  ast_hangup(test_channel); \
296  VM_API_TEST_CLEANUP; \
297  return AST_TEST_FAIL; \
298  } } while (0)
299 
300 /*!
301  * \internal
302  * \brief Playback a message on a channel or callback function.
303  *
304  * \note The channel name must be test_channel.
305  * \note Fail the test if the message is successfully played
306  */
307 #define VM_API_PLAYBACK_MESSAGE_OFF_NOMINAL(channel, mailbox, context, folder, message, callback_fn) do { \
308  if (!ast_vm_msg_play((channel), (mailbox), (context), (folder), (message), (callback_fn))) { \
309  ast_test_status_update(test, "Succeeded in playing back of message when expected result was to fail\n"); \
310  ast_hangup(test_channel); \
311  VM_API_TEST_CLEANUP; \
312  return AST_TEST_FAIL; \
313  } } while (0)
314 
315 
316 /*!
317  * \internal
318  * \brief Possible names of folders.
319  *
320  * \note Taken from app_voicemail
321  */
322 static const char * const mailbox_folders[] = {
323  "INBOX",
324  "Old",
325  "Work",
326  "Family",
327  "Friends",
328  "Cust1",
329  "Cust2",
330  "Cust3",
331  "Cust4",
332  "Cust5",
333  "Deleted",
334  "Urgent",
335 };
336 
337 /*!
338  * \internal
339  * \brief Message snapshots representing the messages that are used by the various tests
340  */
342 
343 /*!
344  * \internal
345  * \brief Tracks whether or not we entered into the message playback callback function
346  */
348 
349 /*!
350  * \internal
351  * \brief Get a folder index by its name
352  */
353 static int get_folder_by_name(const char *folder)
354 {
355  size_t i;
356 
357  for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) {
358  if (strcasecmp(folder, mailbox_folders[i]) == 0) {
359  return i;
360  }
361  }
362 
363  return -1;
364 }
365 
366 /*!
367  * \internal
368  * \brief Get a mock snapshot object
369  *
370  * \param context The mailbox context
371  * \param exten The mailbox extension
372  * \param callerid The caller ID of the person leaving the message
373  *
374  * \returns an ast_vm_msg_snapshot object on success
375  * \returns NULL on error
376  */
377 static struct ast_vm_msg_snapshot *test_vm_api_create_mock_snapshot(const char *context, const char *exten, const char *callerid)
378 {
379  char msg_id_hash[AST_MAX_CONTEXT + AST_MAX_EXTENSION + sizeof(callerid) + 1];
380  char msg_id_buf[256];
381  struct ast_vm_msg_snapshot *snapshot;
382 
383  snprintf(msg_id_hash, sizeof(msg_id_hash), "%s%s%s", exten, context, callerid);
384  snprintf(msg_id_buf, sizeof(msg_id_buf), "%ld-%d", (long)time(NULL), ast_str_hash(msg_id_hash));
385 
386  if ((snapshot = ast_calloc(1, sizeof(*snapshot)))) {
387  if (ast_string_field_init(snapshot, 128)) {
388  ast_free(snapshot);
389  return NULL;
390  }
391  ast_string_field_set(snapshot, msg_id, msg_id_buf);
392  ast_string_field_set(snapshot, exten, exten);
393  ast_string_field_set(snapshot, callerid, callerid);
394  }
395  return snapshot;
396 }
397 
398 /*!
399  * \internal
400  * \brief Destroy a mock snapshot object
401  */
403 {
404  if (snapshot) {
406  ast_free(snapshot);
407  }
408 }
409 
410 /*!
411  * \internal
412  * \brief Make a voicemail mailbox folder based on the values provided in a message snapshot
413  *
414  * \param snapshot The snapshot containing the information to create the folder from
415  *
416  * \returns 0 on success
417  * \returns 1 on failure
418  */
419 static int test_vm_api_create_voicemail_folder(const char *folder_path)
420 {
421  mode_t mode = VOICEMAIL_DIR_MODE;
422  int res;
423 
424  if ((res = ast_mkdir(folder_path, mode))) {
425  ast_log(AST_LOG_ERROR, "ast_mkdir '%s' failed: %s\n", folder_path, strerror(res));
426  return 1;
427  }
428  return 0;
429 }
430 
431 /*!
432  * \internal
433  * \brief Create the voicemail files specified by a snapshot
434  *
435  * \param context The context of the mailbox
436  * \param mailbox The actual mailbox
437  * \param snapshot The message snapshot object containing the relevant envelope data
438  *
439  * \note This will symbolic link the sound file 'beep.gsm' to act as the 'sound' portion of the voicemail.
440  * Certain actions in app_voicemail will fail if an actual sound file does not exist
441  *
442  * \returns 0 on success
443  * \returns 1 on any failure
444  */
445 static int test_vm_api_create_voicemail_files(const char *context, const char *mailbox, struct ast_vm_msg_snapshot *snapshot)
446 {
447  FILE *msg_file;
448  char folder_path[PATH_MAX];
449  char msg_path[PATH_MAX];
450  char snd_path[PATH_MAX];
451  char beep_path[PATH_MAX];
452 
453  /* Note that we create both the text and a dummy sound file here. Without
454  * the sound file, a number of the voicemail operations 'silently' fail, as it
455  * does not believe that an actual voicemail exists
456  */
457  snprintf(folder_path, sizeof(folder_path), "%s/voicemail/%s/%s/%s",
458  ast_config_AST_SPOOL_DIR, context, mailbox, snapshot->folder_name);
459  snprintf(msg_path, sizeof(msg_path), "%s/msg%04u.txt",
460  folder_path, snapshot->msg_number);
461  snprintf(snd_path, sizeof(snd_path), "%s/msg%04u.gsm",
462  folder_path, snapshot->msg_number);
463  snprintf(beep_path, sizeof(beep_path), "%s/sounds/en/beep.gsm", ast_config_AST_DATA_DIR);
464 
465  if (test_vm_api_create_voicemail_folder(folder_path)) {
466  return 1;
467  }
468 
469  if (ast_lock_path(folder_path) == AST_LOCK_FAILURE) {
470  ast_log(AST_LOG_ERROR, "Unable to lock directory %s\n", folder_path);
471  return 1;
472  }
473 
474  if (symlink(beep_path, snd_path)) {
475  ast_unlock_path(folder_path);
476  ast_log(AST_LOG_ERROR, "Failed to create a symbolic link from %s to %s: %s\n",
477  beep_path, snd_path, strerror(errno));
478  return 1;
479  }
480 
481  if (!(msg_file = fopen(msg_path, "w"))) {
482  /* Attempt to remove the sound file */
483  unlink(snd_path);
484  ast_unlock_path(folder_path);
485  ast_log(AST_LOG_ERROR, "Failed to open %s for writing\n", msg_path);
486  return 1;
487  }
488 
489  fprintf(msg_file, ";\n; Message Information file\n;\n"
490  "[message]\n"
491  "origmailbox=%s\n"
492  "context=%s\n"
493  "macrocontext=%s\n"
494  "exten=%s\n"
495  "rdnis=%s\n"
496  "priority=%d\n"
497  "callerchan=%s\n"
498  "callerid=%s\n"
499  "origdate=%s\n"
500  "origtime=%s\n"
501  "category=%s\n"
502  "msg_id=%s\n"
503  "flag=%s\n"
504  "duration=%s\n",
505  mailbox,
506  context,
507  "",
508  snapshot->exten,
509  "unknown",
510  1,
511  snapshot->callerchan,
512  snapshot->callerid,
513  snapshot->origdate,
514  snapshot->origtime,
515  "",
516  snapshot->msg_id,
517  snapshot->flag,
518  snapshot->duration);
519  fclose(msg_file);
520 
521  if (chmod(msg_path, VOICEMAIL_FILE_MODE) < 0) {
522  ast_unlock_path(folder_path);
523  ast_log(AST_LOG_ERROR, "Couldn't set permissions on voicemail text file %s: %s", msg_path, strerror(errno));
524  return 1;
525  }
526  ast_unlock_path(folder_path);
527 
528  return 0;
529 }
530 
531 /*!
532  * \internal
533  * \brief Destroy the voicemail on the file system associated with a snapshot
534  *
535  * \param snapshot The snapshot describing the voicemail
536  */
538 {
539  char msg_path[PATH_MAX];
540  char snd_path[PATH_MAX];
541  char folder_path[PATH_MAX];
542 
543  if (!snapshot) {
544  return;
545  }
546 
547  snprintf(folder_path, sizeof(folder_path), "%s/voicemail/%s/%s/%s",
548  ast_config_AST_SPOOL_DIR, "default", snapshot->exten, snapshot->folder_name);
549 
550  snprintf(msg_path, sizeof(msg_path), "%s/msg%04u.txt",
551  folder_path, snapshot->msg_number);
552  snprintf(snd_path, sizeof(snd_path), "%s/msg%04u.gsm",
553  folder_path, snapshot->msg_number);
554  unlink(msg_path);
555  unlink(snd_path);
556 
557  return;
558 }
559 
560 /*!
561  * \internal
562  * \brief Destroy the voicemails associated with a mailbox snapshot
563  *
564  * \param mailbox The actual mailbox name
565  * \param mailbox_snapshot The mailbox snapshot containing the voicemails to destroy
566  *
567  * \note It is necessary to specify not just the snapshot, but the mailbox itself. The
568  * message snapshots contained in the snapshot may have originated from a different mailbox
569  * then the one we're destroying, which means that we can't determine the files to delete
570  * without knowing the actual mailbox they exist in.
571  */
572 static void test_vm_api_destroy_mailbox_voicemails(const char *mailbox, struct ast_vm_mailbox_snapshot *mailbox_snapshot)
573 {
574  struct ast_vm_msg_snapshot *msg;
575  int i;
576 
577  for (i = 0; i < 12; ++i) {
578  AST_LIST_TRAVERSE(&mailbox_snapshot->snapshots[i], msg, msg) {
579  ast_string_field_set(msg, exten, mailbox);
581  }
582  }
583 }
584 
585 /*!
586  * \internal
587  * \brief Use snapshots to remove all messages in the mailboxes
588  */
590 {
591  struct ast_vm_mailbox_snapshot *mailbox_snapshot;
592 
593  /* Take a snapshot of each mailbox and remove the contents. Note that we need to use
594  * snapshots of the mailboxes in addition to our tracked test snapshots, as there's a good chance
595  * we've created copies of the snapshots */
596  if ((mailbox_snapshot = ast_vm_mailbox_snapshot_create("test_vm_api_1234", "default", NULL, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0))) {
597  test_vm_api_destroy_mailbox_voicemails("test_vm_api_1234", mailbox_snapshot);
598  mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot);
599  } else {
600  ast_log(AST_LOG_WARNING, "Failed to create mailbox snapshot - could not remove test messages for test_vm_api_1234\n");
601  }
602  if ((mailbox_snapshot = ast_vm_mailbox_snapshot_create("test_vm_api_2345", "default", NULL, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0))) {
603  test_vm_api_destroy_mailbox_voicemails("test_vm_api_2345", mailbox_snapshot);
604  mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot);
605  } else {
606  ast_log(AST_LOG_WARNING, "Failed to create mailbox snapshot - could not remove test messages for test_vm_api_2345\n");
607  }
608 }
609 
610 /*!
611  * \internal
612  * \brief Set up the necessary voicemails for a unit test run
613  *
614  * \details
615  * This creates 4 voicemails, stores them on the file system, and creates snapshot objects
616  * representing them for expected/actual value comparisons in the array test_snapshots.
617  *
618  * test_snapshots[0] => in test_vm_1234@default, folder INBOX, message 0
619  * test_snapshots[1] => in test_vm_1234@default, folder Old, message 0
620  * test_snapshots[2] => in test_vm_2345@default, folder INBOX, message 0
621  * test_snapshots[3] => in test_vm_2345@default, folder Old, message 1
622  *
623  * \returns 0 on success
624  * \returns 1 on failure
625  */
626 static int test_vm_api_test_setup(void)
627 {
628  int i, res = 0;
629  struct ast_vm_msg_snapshot *msg_one = NULL;
630  struct ast_vm_msg_snapshot *msg_two = NULL;
631  struct ast_vm_msg_snapshot *msg_three = NULL;
632  struct ast_vm_msg_snapshot *msg_four = NULL;
633 
634  /* Make the four sample voicemails */
635  if ( !((msg_one = test_vm_api_create_mock_snapshot("default", "test_vm_api_1234", "\"Phil\" <2000>")))
636  || !((msg_two = test_vm_api_create_mock_snapshot("default", "test_vm_api_1234", "\"Noel\" <8000>")))
637  || !((msg_three = test_vm_api_create_mock_snapshot("default", "test_vm_api_2345", "\"Phil\" <2000>")))
638  || !((msg_four = test_vm_api_create_mock_snapshot("default", "test_vm_api_2345", "\"Bill\" <3000>")))) {
639  ast_log(AST_LOG_ERROR, "Failed to create mock snapshots for test\n");
644  return 1;
645  }
646 
647  /* Create the voicemail users */
648  if (ast_vm_test_create_user("default", "test_vm_api_1234")
649  || ast_vm_test_create_user("default", "test_vm_api_2345")) {
650  ast_log(AST_LOG_ERROR, "Failed to create test voicemail users\n");
655  /* Note that the cleanup macro will ensure that any test user that
656  * was successfully created is removed
657  */
658  return 1;
659  }
660 
661  /* Now that the users exist from the perspective of the voicemail
662  * application, attempt to remove any existing voicemails
663  */
665 
666  /* Set the basic properties on each */
667  ast_string_field_set(msg_one, callerchan, "SIP/2000-00000000");
668  ast_string_field_set(msg_one, origdate, "Mon Mar 19 04:14:21 PM UTC 2012");
669  ast_string_field_set(msg_one, origtime, "1332173661");
670  ast_string_field_set(msg_one, duration, "8");
671  ast_string_field_set(msg_one, folder_name, "Old");
672  msg_one->msg_number = 0;
673  test_snapshots[0] = msg_one;
674 
675  ast_string_field_set(msg_two, callerchan, "SIP/8000-00000001");
676  ast_string_field_set(msg_two, origdate, "Mon Mar 19 06:16:13 PM UTC 2012");
677  ast_string_field_set(msg_two, origtime, "1332180973");
678  ast_string_field_set(msg_two, duration, "24");
679  ast_string_field_set(msg_two, folder_name, "INBOX");
680  msg_two->msg_number = 0;
681  test_snapshots[1] = msg_two;
682 
683  ast_string_field_set(msg_three, callerchan, "IAX/2000-000000a3");
684  ast_string_field_set(msg_three, origdate, "Thu Mar 22 23:13:03 PM UTC 2012");
685  ast_string_field_set(msg_three, origtime, "1332181251");
686  ast_string_field_set(msg_three, duration, "25");
687  ast_string_field_set(msg_three, folder_name, "INBOX");
688  msg_three->msg_number = 0;
689  test_snapshots[2] = msg_three;
690 
691  ast_string_field_set(msg_four, callerchan, "DAHDI/3000-00000010");
692  ast_string_field_set(msg_four, origdate, "Fri Mar 23 03:01:03 AM UTC 2012");
693  ast_string_field_set(msg_four, origtime, "1332181362");
694  ast_string_field_set(msg_four, duration, "13");
695  ast_string_field_set(msg_four, folder_name, "INBOX");
696  msg_three->msg_number = 1;
697  test_snapshots[3] = msg_four;
698 
699  /* Store the messages */
700  for (i = 0; i < TOTAL_SNAPSHOTS; ++i) {
701  if (test_vm_api_create_voicemail_files("default", test_snapshots[i]->exten, test_snapshots[i])) {
702  /* On a failure, the test_vm_api_test_teardown method will remove and
703  * unlink any created files. Since we failed to create the file, clean
704  * up the object here instead */
705  ast_log(AST_LOG_ERROR, "Failed to store voicemail %s/%s\n",
706  "default", test_snapshots[i]->exten);
707  test_vm_api_destroy_mock_snapshot(test_snapshots[i]);
708  test_snapshots[i] = NULL;
709  res = 1;
710  }
711  }
712 
713  return res;
714 }
715 
716 static void test_vm_api_test_teardown(void)
717 {
718  int i;
719 
720  /* Remove our test message snapshots */
721  for (i = 0; i < TOTAL_SNAPSHOTS; ++i) {
722  test_vm_api_remove_voicemail(test_snapshots[i]);
723  test_vm_api_destroy_mock_snapshot(test_snapshots[i]);
724  test_snapshots[i] = NULL;
725  }
726 
728 
729  /* Remove the test users */
730  ast_vm_test_destroy_user("default", "test_vm_api_1234");
731  ast_vm_test_destroy_user("default", "test_vm_api_2345");
732 }
733 
734 /*!
735  * \internal
736  * \brief Update the test snapshots with a new mailbox snapshot
737  *
738  * \param mailbox_snapshot The new mailbox shapshot to update the test snapshots with
739  */
740 static void test_vm_api_update_test_snapshots(struct ast_vm_mailbox_snapshot *mailbox_snapshot)
741 {
742  int i, j;
743  struct ast_vm_msg_snapshot *msg;
744 
745  for (i = 0; i < TOTAL_SNAPSHOTS; ++i) {
746  for (j = 0; j < 12; ++j) {
747  AST_LIST_TRAVERSE(&mailbox_snapshot->snapshots[j], msg, msg) {
748  if (!strcmp(msg->msg_id, test_snapshots[i]->msg_id)) {
749  ast_string_field_set(test_snapshots[i], callerid, msg->callerid);
750  ast_string_field_set(test_snapshots[i], callerchan, msg->callerchan);
751  ast_string_field_set(test_snapshots[i], exten, msg->exten);
752  ast_string_field_set(test_snapshots[i], origdate, msg->origdate);
753  ast_string_field_set(test_snapshots[i], origtime, msg->origtime);
754  ast_string_field_set(test_snapshots[i], duration, msg->duration);
755  ast_string_field_set(test_snapshots[i], folder_name, msg->folder_name);
756  ast_string_field_set(test_snapshots[i], flag, msg->flag);
757  test_snapshots[i]->msg_number = msg->msg_number;
758  }
759  }
760  }
761  }
762 }
763 
764 /*!
765  * \internal
766  * \brief A callback function for message playback
767  *
768  * \param chan The channel the file would be played back on
769  * \param file The file to play back
770  * \param duration The duration of the file
771  *
772  * \note This sets global_entered_playback_callback to 1 if the parameters
773  * passed to the callback are minimally valid
774  */
775 static void message_playback_callback_fn(struct ast_channel *chan, const char *file, int duration)
776 {
777  if ((chan) && !ast_strlen_zero(file) && duration > 0) {
779  } else {
780  ast_log(AST_LOG_WARNING, "Entered into message playback callback function with invalid parameters\n");
781  }
782 }
783 
784 /*!
785  * \internal
786  * \brief Dummy channel write function for mock_channel_tech
787  */
788 static int test_vm_api_mock_channel_write(struct ast_channel *chan, struct ast_frame *frame)
789 {
790  return 0;
791 }
792 
793 /*!
794  * \internal
795  * \brief Dummy channel read function for mock_channel_tech
796  */
798 {
799  return &ast_null_frame;
800 }
801 
802 /*!
803  * \internal
804  * \brief A dummy channel technology
805  */
806 static const struct ast_channel_tech mock_channel_tech = {
809 };
810 
811 /*!
812  * \internal
813  * \brief Create a dummy channel suitable for 'playing back' gsm sound files on
814  *
815  * \returns a channel on success
816  * \returns NULL on failure
817  */
819 {
820  struct ast_channel *mock_channel;
821  struct ast_format_cap *native_formats;
822 
823  if (!(mock_channel = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "TestChannel"))) {
824  return NULL;
825  }
826 
831  ast_channel_tech_set(mock_channel, &mock_channel_tech);
832  native_formats = ast_channel_nativeformats(mock_channel);
833  ast_format_cap_append(native_formats, ast_channel_writeformat(mock_channel), 0);
834 
835  ast_channel_unlock(mock_channel);
836 
837  return mock_channel;
838 }
839 
840 AST_TEST_DEFINE(voicemail_api_nominal_snapshot)
841 {
842  struct ast_vm_mailbox_snapshot *test_mbox_snapshot = NULL;
843 
844  switch (cmd) {
845  case TEST_INIT:
846  info->name = "nominal_snapshot";
847  info->category = "/main/voicemail_api/";
848  info->summary = "Nominal mailbox snapshot tests";
849  info->description =
850  "Test retrieving mailbox snapshots";
851  return AST_TEST_NOT_RUN;
852  case TEST_EXECUTE:
853  break;
854  }
855 
857 
858  ast_test_status_update(test, "Test retrieving message 1 from INBOX of test_vm_1234\n");
859  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
860  VM_API_INT_VERIFY(1, test_mbox_snapshot->total_msg_num);
861  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[1], test_mbox_snapshot, "INBOX", 0);
862  ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
863 
864  ast_test_status_update(test, "Test retrieving message 0 from Old of test_vm_1234\n");
865  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "Old", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
866  VM_API_INT_VERIFY(1, test_mbox_snapshot->total_msg_num);
867  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[0], test_mbox_snapshot, "Old", 0);
868  ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
869 
870  ast_test_status_update(test, "Test retrieving message 0, 1 from Old and INBOX of test_vm_1234 ordered by time\n");
871  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 1);
872  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
873  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[0], test_mbox_snapshot, "INBOX", 0);
874  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[1], test_mbox_snapshot, "INBOX", 1);
875  ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
876 
877  ast_test_status_update(test, "Test retrieving message 1, 0 from Old and INBOX of test_vm_1234 ordered by time desc\n");
878  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 1, AST_VM_SNAPSHOT_SORT_BY_TIME, 1);
879  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
880  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[1], test_mbox_snapshot, "INBOX", 0);
881  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[0], test_mbox_snapshot, "INBOX", 1);
882  ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
883 
884  ast_test_status_update(test, "Test retrieving message 0, 1 from Old and INBOX of test_vm_1234 ordered by id\n");
885  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_ID, 1);
886  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
887  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[1], test_mbox_snapshot, "INBOX", 0);
888  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[0], test_mbox_snapshot, "INBOX", 1);
889  ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
890 
891  ast_test_status_update(test, "Test retrieving message 1, 0 from Old and INBOX of test_vm_1234 ordered by id desc\n");
892  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 1, AST_VM_SNAPSHOT_SORT_BY_ID, 1);
893  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
894  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[0], test_mbox_snapshot, "INBOX", 0);
895  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[1], test_mbox_snapshot, "INBOX", 1);
896  ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
897 
898  ast_test_status_update(test, "Test retrieving message 0, 1 from all folders of test_vm_1234 ordered by id\n");
899  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", NULL, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0);
900  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
901  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[0], test_mbox_snapshot, "Old", 0);
902  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[1], test_mbox_snapshot, "INBOX", 0);
903  ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
904 
905  ast_test_status_update(test, "Test retrieving message 0, 1 from all folders of test_vm_1234 ordered by time\n");
906  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", NULL, 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
907  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
908  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[0], test_mbox_snapshot, "Old", 0);
909  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[1], test_mbox_snapshot, "INBOX", 0);
910  ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
911 
912  ast_test_status_update(test, "Test retrieving message 0, 1 from all folders of test_vm_1234, default context ordered by time\n");
913  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", NULL, NULL, 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
914  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
915  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[0], test_mbox_snapshot, "Old", 0);
916  VM_API_SNAPSHOT_MSG_VERIFY(test_snapshots[1], test_mbox_snapshot, "INBOX", 0);
917  ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
918 
920 
921  return AST_TEST_PASS;
922 }
923 
924 AST_TEST_DEFINE(voicemail_api_off_nominal_snapshot)
925 {
926  struct ast_vm_mailbox_snapshot *test_mbox_snapshot = NULL;
927 
928  switch (cmd) {
929  case TEST_INIT:
930  info->name = "off_nominal_snapshot";
931  info->category = "/main/voicemail_api/";
932  info->summary = "Off nominal mailbox snapshot tests";
933  info->description =
934  "Test off nominal requests for mailbox snapshots. This includes"
935  " testing the following:\n"
936  " * Access to non-exisstent mailbox\n"
937  " * Access to NULL mailbox\n"
938  " * Access to non-existent context\n"
939  " * Access to non-existent folder\n"
940  " * Access to NULL folder\n"
941  " * Invalid sort identifier";
942  return AST_TEST_NOT_RUN;
943  case TEST_EXECUTE:
944  break;
945  }
946 
948 
949  ast_test_status_update(test, "Test access to non-existent mailbox test_vm_api_3456\n");
950  VM_API_SNAPSHOT_OFF_NOMINAL_TEST("test_vm_api_3456", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
951 
952  ast_test_status_update(test, "Test access to null mailbox\n");
954 
955  ast_test_status_update(test, "Test access non-existent context test_vm_api_defunct\n");
956  VM_API_SNAPSHOT_OFF_NOMINAL_TEST("test_vm_api_1234", "test_vm_api_defunct", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
957 
958  ast_test_status_update(test, "Test non-existent folder test_vm_api_platypus\n");
959  VM_API_SNAPSHOT_OFF_NOMINAL_TEST("test_vm_api_1234", "default", "test_vm_api_platypus", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
960 
962 
963  return AST_TEST_PASS;
964 }
965 
966 AST_TEST_DEFINE(voicemail_api_nominal_move)
967 {
968  struct ast_vm_mailbox_snapshot *test_mbox_snapshot = NULL;
969  const char *inbox_msg_id;
970  const char *old_msg_id;
971  const char *multi_msg_ids[2];
972 
973  switch (cmd) {
974  case TEST_INIT:
975  info->name = "nominal_move";
976  info->category = "/main/voicemail_api/";
977  info->summary = "Nominal move voicemail tests";
978  info->description =
979  "Test nominal requests to move a voicemail to a different"
980  " folder. This includes moving messages given a context,"
981  " given a NULL context, and moving multiple messages";
982  return AST_TEST_NOT_RUN;
983  case TEST_EXECUTE:
984  break;
985  }
986 
988  old_msg_id = test_snapshots[0]->msg_id;
989  inbox_msg_id = test_snapshots[1]->msg_id;
990 
991  multi_msg_ids[0] = test_snapshots[2]->msg_id;
992  multi_msg_ids[1] = test_snapshots[3]->msg_id;
993 
994  ast_test_status_update(test, "Test move of test_vm_api_1234 message from INBOX to Family\n");
995  VM_API_MOVE_MESSAGE("test_vm_api_1234", "default", 1, "INBOX", &inbox_msg_id, "Family");
996 
997  ast_test_status_update(test, "Test move of test_vm_api_1234 message from Old to Family\n");
998  VM_API_MOVE_MESSAGE("test_vm_api_1234", NULL, 1, "Old", &old_msg_id, "Family");
999 
1000  /* Take a snapshot and update the test snapshots for verification */
1001  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "Family", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1002  test_vm_api_update_test_snapshots(test_mbox_snapshot);
1003  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1004 
1005  VM_API_STRING_FIELD_VERIFY("Family", test_snapshots[0]->folder_name);
1006  VM_API_STRING_FIELD_VERIFY("Family", test_snapshots[1]->folder_name);
1007  VM_API_INT_VERIFY(0, test_snapshots[1]->msg_number);
1008  VM_API_INT_VERIFY(1, test_snapshots[0]->msg_number);
1009 
1010  /* Move both of the 2345 messages to Family */
1011  ast_test_status_update(test, "Test move of test_vm_api_2345 messages from Inbox to Family\n");
1012  VM_API_MOVE_MESSAGE("test_vm_api_2345", "default", 2, "INBOX", multi_msg_ids, "Family");
1013 
1014  /* Take a snapshot and update the test snapshots for verification */
1015  VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "Family", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1016  test_vm_api_update_test_snapshots(test_mbox_snapshot);
1017  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1018 
1019  VM_API_STRING_FIELD_VERIFY("Family", test_snapshots[2]->folder_name);
1020  VM_API_STRING_FIELD_VERIFY("Family", test_snapshots[3]->folder_name);
1021 
1022  ast_test_status_update(test, "Test move of test_vm_api_2345 message from Family to INBOX\n");
1023  VM_API_MOVE_MESSAGE("test_vm_api_2345", "default", 2, "Family", multi_msg_ids, "INBOX");
1024 
1025  VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1026  test_vm_api_update_test_snapshots(test_mbox_snapshot);
1027  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1028 
1029  VM_API_STRING_FIELD_VERIFY("INBOX", test_snapshots[2]->folder_name);
1030  VM_API_STRING_FIELD_VERIFY("INBOX", test_snapshots[3]->folder_name);
1031 
1033 
1034  return AST_TEST_PASS;
1035 }
1036 
1037 AST_TEST_DEFINE(voicemail_api_off_nominal_move)
1038 {
1039  const char *inbox_msg_id;
1040  const char *multi_msg_ids[4];
1041 
1042  switch (cmd) {
1043  case TEST_INIT:
1044  info->name = "off_nominal_move";
1045  info->category = "/main/voicemail_api/";
1046  info->summary = "Off nominal mailbox message move tests";
1047  info->description =
1048  "Test nominal requests to move a voicemail to a different"
1049  " folder. This includes testing the following:\n"
1050  " * Moving to a non-existent mailbox\n"
1051  " * Moving to a NULL mailbox\n"
1052  " * Moving to a non-existent context\n"
1053  " * Moving to/from non-existent folder\n"
1054  " * Moving to/from NULL folder\n"
1055  " * Invalid message identifier(s)";
1056  return AST_TEST_NOT_RUN;
1057  case TEST_EXECUTE:
1058  break;
1059  }
1060 
1062 
1063  inbox_msg_id = test_snapshots[1]->msg_id;
1064 
1065  multi_msg_ids[0] = test_snapshots[0]->msg_id;
1066  multi_msg_ids[1] = test_snapshots[1]->msg_id;
1067  multi_msg_ids[2] = test_snapshots[2]->msg_id;
1068  multi_msg_ids[3] = test_snapshots[3]->msg_id;
1069 
1070  ast_test_status_update(test, "Test move attempt for invalid mailbox test_vm_3456\n");
1071  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_3456", "default", 1, "INBOX", &inbox_msg_id, "Family");
1072 
1073  VM_API_MOVE_MESSAGE_OFF_NOMINAL(NULL, "default", 1, "INBOX", &inbox_msg_id, "Family");
1074 
1075  ast_test_status_update(test, "Test move attempt for invalid context test_vm_api_defunct\n");
1076  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "test_vm_api_defunct", 1, "INBOX", &inbox_msg_id, "Family");
1077 
1078  ast_test_status_update(test, "Test move attempt to invalid folder\n");
1079  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 1, "INBOX", &inbox_msg_id, "SPAMALOT");
1080 
1081  ast_test_status_update(test, "Test move attempt from invalid folder\n");
1082  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 1, "MEATINACAN", &inbox_msg_id, "Family");
1083 
1084  ast_test_status_update(test, "Test move attempt to NULL folder\n");
1085  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 1, "INBOX", &inbox_msg_id, NULL);
1086 
1087  ast_test_status_update(test, "Test move attempt from NULL folder\n");
1088  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 1, NULL, &inbox_msg_id, "Family");
1089 
1090  ast_test_status_update(test, "Test move attempt with non-existent message number\n");
1091  inbox_msg_id = "6";
1092  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 1, "INBOX", &inbox_msg_id, "Family");
1093 
1094  ast_test_status_update(test, "Test move attempt with invalid message number\n");
1095  inbox_msg_id = "";
1096  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 1, "INBOX", &inbox_msg_id, "Family");
1097 
1098  ast_test_status_update(test, "Test move attempt with 0 number of messages\n");
1099  inbox_msg_id = test_snapshots[1]->msg_id;
1100  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 0, "INBOX", &inbox_msg_id, "Family");
1101 
1102  ast_test_status_update(test, "Test move attempt with invalid number of messages\n");
1103  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", -30, "INBOX", &inbox_msg_id, "Family");
1104 
1105  ast_test_status_update(test, "Test move attempt with non-existent multiple messages, where some messages exist\n");
1106  VM_API_MOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 4, "INBOX", multi_msg_ids, "Family");
1107 
1109 
1110  return AST_TEST_PASS;
1111 }
1112 
1113 AST_TEST_DEFINE(voicemail_api_nominal_remove)
1114 {
1115  struct ast_vm_mailbox_snapshot *test_mbox_snapshot = NULL;
1116  const char *inbox_msg_id;
1117  const char *old_msg_id;
1118  const char *multi_msg_ids[2];
1119 
1120  switch (cmd) {
1121  case TEST_INIT:
1122  info->name = "nominal_remove";
1123  info->category = "/main/voicemail_api/";
1124  info->summary = "Nominal mailbox remove message tests";
1125  info->description =
1126  "Tests removing messages from voicemail folders. Includes"
1127  " both removing messages one at a time, and in a set";
1128  return AST_TEST_NOT_RUN;
1129  case TEST_EXECUTE:
1130  break;
1131  }
1132 
1134 
1135  old_msg_id = test_snapshots[0]->msg_id;
1136  inbox_msg_id = test_snapshots[1]->msg_id;
1137 
1138  multi_msg_ids[0] = test_snapshots[2]->msg_id;
1139  multi_msg_ids[1] = test_snapshots[3]->msg_id;
1140 
1141  ast_test_status_update(test, "Test removing a single message from INBOX\n");
1142  VM_API_REMOVE_MESSAGE("test_vm_api_1234", "default", 1, "INBOX", &inbox_msg_id);
1143 
1144  ast_test_status_update(test, "Test removing a single message from Old\n");
1145  VM_API_REMOVE_MESSAGE("test_vm_api_1234", "default", 1, "Old", &old_msg_id);
1146 
1147  ast_test_status_update(test, "Test removing multiple messages from INBOX\n");
1148  VM_API_REMOVE_MESSAGE("test_vm_api_2345", "default", 2, "INBOX", multi_msg_ids);
1149 
1151 
1152  return AST_TEST_PASS;
1153 }
1154 
1155 AST_TEST_DEFINE(voicemail_api_off_nominal_remove)
1156 {
1157  const char *inbox_msg_id;
1158  const char *multi_msg_ids[2];
1159  const char *empty_msg_ids[] = { };
1160 
1161  switch (cmd) {
1162  case TEST_INIT:
1163  info->name = "off_nominal_remove";
1164  info->category = "/main/voicemail_api/";
1165  info->summary = "Off nominal mailbox message removal tests";
1166  info->description =
1167  "Test off nominal requests for removing messages from "
1168  "a mailbox. This includes:\n"
1169  " * Removing messages with an invalid mailbox\n"
1170  " * Removing messages from a NULL mailbox\n"
1171  " * Removing messages from an invalid context\n"
1172  " * Removing messages from an invalid folder\n"
1173  " * Removing messages from a NULL folder\n"
1174  " * Removing messages with bad identifiers";
1175  return AST_TEST_NOT_RUN;
1176  case TEST_EXECUTE:
1177  break;
1178  }
1179 
1181 
1182  inbox_msg_id = test_snapshots[1]->msg_id;
1183  multi_msg_ids[0] = test_snapshots[2]->msg_id;
1184  multi_msg_ids[1] = test_snapshots[3]->msg_id;
1185 
1186  ast_test_status_update(test, "Test removing a single message with an invalid mailbox\n");
1187  VM_API_REMOVE_MESSAGE_OFF_NOMINAL("test_vm_api_3456", "default", 1, "INBOX", &inbox_msg_id);
1188 
1189  ast_test_status_update(test, "Test removing a single message with a NULL mailbox\n");
1190  VM_API_REMOVE_MESSAGE_OFF_NOMINAL(NULL, "default", 1, "INBOX", &inbox_msg_id);
1191 
1192  ast_test_status_update(test, "Test removing a single message with an invalid context\n");
1193  VM_API_REMOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "defunct", 1, "INBOX", &inbox_msg_id);
1194 
1195  ast_test_status_update(test, "Test removing a single message with an invalid folder\n");
1196  VM_API_REMOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 1, "SPAMINACAN", &inbox_msg_id);
1197 
1198  ast_test_status_update(test, "Test removing a single message with a NULL folder\n");
1199  VM_API_REMOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 1, NULL, &inbox_msg_id);
1200 
1201  ast_test_status_update(test, "Test removing a single message with an invalid message number\n");
1202  inbox_msg_id = "POOPOO";
1203  VM_API_REMOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 1, "INBOX", &inbox_msg_id);
1204 
1205  ast_test_status_update(test, "Test removing multiple messages with a single invalid message number\n");
1206  multi_msg_ids[1] = "POOPOO";
1207  VM_API_REMOVE_MESSAGE_OFF_NOMINAL("test_vm_api_2345", "default", 2, "INBOX", multi_msg_ids);
1208 
1209  ast_test_status_update(test, "Test removing no messages with no message numbers\n");
1210  VM_API_REMOVE_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", 0, "INBOX", empty_msg_ids);
1211 
1212  ast_test_status_update(test, "Test removing multiple messages with an invalid size specifier\n");
1213  VM_API_REMOVE_MESSAGE_OFF_NOMINAL("test_vm_api_2345", "default", -30, "INBOX", multi_msg_ids);
1214 
1216 
1217  return AST_TEST_PASS;
1218 }
1219 
1220 AST_TEST_DEFINE(voicemail_api_nominal_forward)
1221 {
1222  struct ast_vm_mailbox_snapshot *test_mbox_snapshot = NULL;
1223  const char *inbox_msg_id;
1224  const char *multi_msg_ids[2];
1225 
1226  switch (cmd) {
1227  case TEST_INIT:
1228  info->name = "nominal_forward";
1229  info->category = "/main/voicemail_api/";
1230  info->summary = "Nominal message forward tests";
1231  info->description =
1232  "Tests the nominal cases of forwarding messages"
1233  " between mailboxes";
1234  return AST_TEST_NOT_RUN;
1235  case TEST_EXECUTE:
1236  break;
1237  }
1238 
1240 
1241  inbox_msg_id = test_snapshots[1]->msg_id;
1242 
1243  multi_msg_ids[0] = test_snapshots[2]->msg_id;
1244  multi_msg_ids[1] = test_snapshots[3]->msg_id;
1245 
1246  ast_test_status_update(test, "Test forwarding message 0 from test_vm_api_1234 INBOX to test_vm_api_2345 INBOX\n");
1247  VM_API_FORWARD_MESSAGE("test_vm_api_1234", "default", "INBOX", "test_vm_api_2345", "default", "INBOX", 1, &inbox_msg_id, 0);
1248 
1249  /* Make sure we didn't delete the message */
1250  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1251  VM_API_INT_VERIFY(1, test_mbox_snapshot->total_msg_num);
1252  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1253 
1254  /* We should now have a total of 3 messages in test_vm_api_2345 INBOX */
1255  VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1256  VM_API_INT_VERIFY(3, test_mbox_snapshot->total_msg_num);
1257  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1258 
1259  ast_test_status_update(test, "Test forwarding message 0 from test_vm_api_1234 INBOX with default context to test_vm_api_2345 INBOX\n");
1260  VM_API_FORWARD_MESSAGE("test_vm_api_1234", NULL, "INBOX", "test_vm_api_2345", "default", "INBOX", 1, &inbox_msg_id, 0);
1261 
1262  /* Make sure we didn't delete the message */
1263  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1264  VM_API_INT_VERIFY(1, test_mbox_snapshot->total_msg_num);
1265  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1266 
1267  /* We should now have a total of 4 messages in test_vm_api_2345 INBOX */
1268  VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1269  VM_API_INT_VERIFY(4, test_mbox_snapshot->total_msg_num);
1270  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1271 
1272  ast_test_status_update(test, "Test forwarding message 0 from test_vm_api_1234 INBOX to test_vm_api_2345 INBOX with default context\n");
1273  VM_API_FORWARD_MESSAGE("test_vm_api_1234", "default", "INBOX", "test_vm_api_2345", NULL, "INBOX", 1, &inbox_msg_id, 0);
1274 
1275  /* Make sure we didn't delete the message */
1276  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1277  VM_API_INT_VERIFY(1, test_mbox_snapshot->total_msg_num);
1278  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1279 
1280  /* We should now have a total of 5 messages in test_vm_api_2345 INBOX */
1281  VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1282  VM_API_INT_VERIFY(5, test_mbox_snapshot->total_msg_num);
1283  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1284 
1285  ast_test_status_update(test, "Test forwarding message 0 from test_vm_api_1234 INBOX to test_vm_api_2345 INBOX, deleting original\n");
1286  VM_API_FORWARD_MESSAGE("test_vm_api_1234", "default", "INBOX", "test_vm_api_2345", NULL, "INBOX", 1, &inbox_msg_id, 1);
1287 
1288  /* Make sure we deleted the message */
1289  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1290  VM_API_INT_VERIFY(0, test_mbox_snapshot->total_msg_num);
1291  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1292 
1293  /* We should now have a total of 6 messages in test_vm_api_2345 INBOX */
1294  VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1295  VM_API_INT_VERIFY(6, test_mbox_snapshot->total_msg_num);
1296  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1297 
1298  ast_test_status_update(test, "Test forwarding 2 messages from test_vm_api_2345 INBOX to test_vm_api_1234 INBOX");
1299  VM_API_FORWARD_MESSAGE("test_vm_api_2345", "default", "INBOX", "test_vm_api_1234", "default", "INBOX", 2, multi_msg_ids, 0);
1300 
1301  /* Make sure we didn't delete the messages */
1302  VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1303  VM_API_INT_VERIFY(6, test_mbox_snapshot->total_msg_num);
1304  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1305 
1306  /* We should now have a total of 2 messages in test_vm_api_1234 INBOX */
1307  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1308  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
1309  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1310 
1311  ast_test_status_update(test, "Test forwarding 2 messages from test_vm_api_2345 INBOX to test_vm_api_1234 Family, deleting original\n");
1312  VM_API_FORWARD_MESSAGE("test_vm_api_2345", "default", "INBOX", "test_vm_api_1234", "default", "Family", 2, multi_msg_ids, 1);
1313  /* Make sure we deleted the messages */
1314  VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "INBOX", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1315  VM_API_INT_VERIFY(4, test_mbox_snapshot->total_msg_num);
1316  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1317 
1318  /* We should now have a total of 2 messages in test_vm_api_1234 Family */
1319  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "Family", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1320  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
1321  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1322 
1324 
1325  return AST_TEST_PASS;
1326 }
1327 
1328 AST_TEST_DEFINE(voicemail_api_off_nominal_forward)
1329 {
1330  const char *inbox_msg_id;
1331  const char *multi_msg_ids[4];
1332 
1333  const char *empty_msg_ids[] = { };
1334 
1335  switch (cmd) {
1336  case TEST_INIT:
1337  info->name = "off_nominal_forward";
1338  info->category = "/main/voicemail_api/";
1339  info->summary = "Off nominal message forwarding tests";
1340  info->description =
1341  "Test off nominal forwarding of messages. This includes:\n"
1342  " * Invalid/NULL from mailbox\n"
1343  " * Invalid from context\n"
1344  " * Invalid/NULL from folder\n"
1345  " * Invalid/NULL to mailbox\n"
1346  " * Invalid to context\n"
1347  " * Invalid/NULL to folder\n"
1348  " * Invalid message numbers\n"
1349  " * Invalid number of messages";
1350  return AST_TEST_NOT_RUN;
1351  case TEST_EXECUTE:
1352  break;
1353  }
1354 
1356 
1357  inbox_msg_id = test_snapshots[1]->msg_id;
1358 
1359  multi_msg_ids[0] = test_snapshots[0]->msg_id;
1360  multi_msg_ids[1] = test_snapshots[1]->msg_id;
1361  multi_msg_ids[2] = test_snapshots[2]->msg_id;
1362  multi_msg_ids[3] = test_snapshots[3]->msg_id;
1363 
1364  ast_test_status_update(test, "Test forwarding from an invalid mailbox\n");
1365  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_3456", "default", "INBOX", "test_vm_api_2345", "default", "INBOX", 1, &inbox_msg_id, 0);
1366 
1367  ast_test_status_update(test, "Test forwarding from a NULL mailbox\n");
1368  VM_API_FORWARD_MESSAGE_OFF_NOMINAL(NULL, "default", "INBOX", "test_vm_api_2345", "default", "INBOX", 1, &inbox_msg_id, 0);
1369 
1370  ast_test_status_update(test, "Test forwarding from an invalid context\n");
1371  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "defunct", "INBOX", "test_vm_api_2345", "default", "INBOX", 1, &inbox_msg_id, 0);
1372 
1373  ast_test_status_update(test, "Test forwarding from an invalid folder\n");
1374  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", "POTTEDMEAT", "test_vm_api_2345", "default", "INBOX", 1, &inbox_msg_id, 0);
1375 
1376  ast_test_status_update(test, "Test forwarding from a NULL folder\n");
1377  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", NULL, "test_vm_api_2345", "default", "INBOX", 1, &inbox_msg_id, 0);
1378 
1379  ast_test_status_update(test, "Test forwarding to an invalid mailbox\n");
1380  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", "INBOX", "test_vm_api_3456", "default", "INBOX", 1, &inbox_msg_id, 0);
1381 
1382  ast_test_status_update(test, "Test forwarding to a NULL mailbox\n");
1383  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", "INBOX", NULL, "default", "INBOX", 1, &inbox_msg_id, 0);
1384 
1385  ast_test_status_update(test, "Test forwarding to an invalid context\n");
1386  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", "INBOX", "test_vm_api_2345", "defunct", "INBOX", 1, &inbox_msg_id, 0);
1387 
1388  ast_test_status_update(test, "Test forwarding to an invalid folder\n");
1389 
1390  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", "INBOX", "test_vm_api_2345", "default", "POTTEDMEAT", 1, &inbox_msg_id, 0);
1391 
1392  ast_test_status_update(test, "Test forwarding to a NULL folder\n");
1393  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", "INBOX", "test_vm_api_2345", "default", NULL, 1, &inbox_msg_id, 0);
1394 
1395  ast_test_status_update(test, "Test forwarding when no messages are select\n");
1396  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", "INBOX", "test_vm_api_2345", "default", "INBOX", 0, empty_msg_ids, 0);
1397 
1398  ast_test_status_update(test, "Test forwarding a message that doesn't exist\n");
1399  inbox_msg_id = "POOPOO";
1400  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", "INBOX", "test_vm_api_2345", "default", "INBOX", 1, &inbox_msg_id, 0);
1401 
1402  ast_test_status_update(test, "Test forwarding multiple messages, where some messages don't exist\n");
1403  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_2345", "default", "INBOX", "test_vm_api_1234", "default", "INBOX", 4, multi_msg_ids, 0);
1404 
1405  ast_test_status_update(test, "Test forwarding a message with an invalid size specifier\n");
1406  VM_API_FORWARD_MESSAGE_OFF_NOMINAL("test_vm_api_1234", "default", "INBOX", "test_vm_api_2345", "default", "INBOX", -30, &inbox_msg_id, 0);
1407 
1409 
1410  return AST_TEST_PASS;
1411 }
1412 
1413 AST_TEST_DEFINE(voicemail_api_nominal_msg_playback)
1414 {
1415  struct ast_vm_mailbox_snapshot *test_mbox_snapshot = NULL;
1416  struct ast_channel *test_channel;
1417  const char *message_id_1234;
1418  const char *message_id_2345[2];
1419 
1420  switch (cmd) {
1421  case TEST_INIT:
1422  info->name = "nominal_msg_playback";
1423  info->category = "/main/voicemail_api/";
1424  info->summary = "Nominal message playback";
1425  info->description =
1426  "Tests playing back a message on a provided"
1427  " channel or callback function";
1428  return AST_TEST_NOT_RUN;
1429  case TEST_EXECUTE:
1430  break;
1431  }
1432 
1434 
1435  message_id_1234 = test_snapshots[1]->msg_id;
1436  message_id_2345[0] = test_snapshots[2]->msg_id;
1437  message_id_2345[1] = test_snapshots[3]->msg_id;
1438 
1439  if (!(test_channel = test_vm_api_create_mock_channel())) {
1440  ast_log(AST_LOG_ERROR, "Failed to create mock channel for testing\n");
1442  return AST_TEST_FAIL;
1443  }
1444 
1445  ast_test_status_update(test, "Playing back message from test_vm_api_1234 to mock channel\n");
1446  VM_API_PLAYBACK_MESSAGE(test_channel, "test_vm_api_1234", "default", "INBOX", message_id_1234, NULL);
1447 
1448  ast_test_status_update(test, "Playing back message from test_vm_api_2345 to callback function\n");
1449  VM_API_PLAYBACK_MESSAGE(test_channel, "test_vm_api_2345", "default", "INBOX", message_id_2345[0], &message_playback_callback_fn);
1452 
1453  ast_test_status_update(test, "Playing back message from test_vm_api_2345 to callback function with default context\n");
1454  VM_API_PLAYBACK_MESSAGE(test_channel, "test_vm_api_2345", NULL, "INBOX", message_id_2345[1], &message_playback_callback_fn);
1457 
1458  VM_API_SNAPSHOT_CREATE("test_vm_api_1234", "default", "Old", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1459  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
1460  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1461 
1462  VM_API_SNAPSHOT_CREATE("test_vm_api_2345", "default", "Old", 0, AST_VM_SNAPSHOT_SORT_BY_TIME, 0);
1463  VM_API_INT_VERIFY(2, test_mbox_snapshot->total_msg_num);
1464  test_mbox_snapshot = ast_vm_mailbox_snapshot_destroy(test_mbox_snapshot);
1465 
1466  ast_hangup(test_channel);
1468 
1469  return AST_TEST_PASS;
1470 }
1471 
1472 AST_TEST_DEFINE(voicemail_api_off_nominal_msg_playback)
1473 {
1474  struct ast_channel *test_channel;
1475  const char *msg_id;
1476  const char *invalid_msg_id = "POOPOO";
1477 
1478  switch (cmd) {
1479  case TEST_INIT:
1480  info->name = "off_nominal_msg_playback";
1481  info->category = "/main/voicemail_api/";
1482  info->summary = "Off nominal message playback";
1483  info->description =
1484  "Tests off nominal conditions in playing back a "
1485  "message. This includes:\n"
1486  " * Invalid/NULL mailbox\n"
1487  " * Invalid context\n"
1488  " * Invalid/NULL folder\n"
1489  " * Invalid message identifiers";
1490  return AST_TEST_NOT_RUN;
1491  case TEST_EXECUTE:
1492  break;
1493  }
1494 
1496  msg_id = test_snapshots[0]->msg_id;
1497 
1498  if (!(test_channel = test_vm_api_create_mock_channel())) {
1499  ast_log(AST_LOG_ERROR, "Failed to create mock channel for testing\n");
1501  return AST_TEST_FAIL;
1502  }
1503 
1504  ast_test_status_update(test, "Playing back message from invalid mailbox\n");
1505  VM_API_PLAYBACK_MESSAGE_OFF_NOMINAL(test_channel, "test_vm_api_3456", "default", "INBOX", msg_id, NULL);
1506 
1507  ast_test_status_update(test, "Playing back message from NULL mailbox\n");
1508  VM_API_PLAYBACK_MESSAGE_OFF_NOMINAL(test_channel, NULL, "default", "INBOX", msg_id, NULL);
1509 
1510  ast_test_status_update(test, "Playing back message from invalid context\n");
1511  VM_API_PLAYBACK_MESSAGE_OFF_NOMINAL(test_channel, "test_vm_api_1234", "defunct", "INBOX", msg_id, NULL);
1512 
1513  ast_test_status_update(test, "Playing back message from invalid folder\n");
1514  VM_API_PLAYBACK_MESSAGE_OFF_NOMINAL(test_channel, "test_vm_api_1234", "default", "BACON", msg_id, NULL);
1515 
1516  ast_test_status_update(test, "Playing back message from NULL folder\n");
1517  VM_API_PLAYBACK_MESSAGE_OFF_NOMINAL(test_channel, "test_vm_api_1234", "default", NULL, msg_id, NULL);
1518 
1519  ast_test_status_update(test, "Playing back message with invalid message specifier\n");
1520  VM_API_PLAYBACK_MESSAGE_OFF_NOMINAL(test_channel, "test_vm_api_1234", "default", "INBOX", invalid_msg_id, NULL);
1521 
1522  ast_test_status_update(test, "Playing back message with NULL message specifier\n");
1523  VM_API_PLAYBACK_MESSAGE_OFF_NOMINAL(test_channel, "test_vm_api_1234", "default", "INBOX", NULL, NULL);
1524  ast_hangup(test_channel);
1526 
1527  return AST_TEST_PASS;
1528 }
1529 
1530 static int unload_module(void)
1531 {
1532  /* Snapshot tests */
1533  AST_TEST_UNREGISTER(voicemail_api_nominal_snapshot);
1534  AST_TEST_UNREGISTER(voicemail_api_off_nominal_snapshot);
1535 
1536  /* Move Tests */
1537  AST_TEST_UNREGISTER(voicemail_api_nominal_move);
1538  AST_TEST_UNREGISTER(voicemail_api_off_nominal_move);
1539 
1540  /* Remove Tests */
1541  AST_TEST_UNREGISTER(voicemail_api_nominal_remove);
1542  AST_TEST_UNREGISTER(voicemail_api_off_nominal_remove);
1543 
1544  /* Forward Tests */
1545  AST_TEST_UNREGISTER(voicemail_api_nominal_forward);
1546  AST_TEST_UNREGISTER(voicemail_api_off_nominal_forward);
1547 
1548  /* Message Playback Tests */
1549  AST_TEST_UNREGISTER(voicemail_api_nominal_msg_playback);
1550  AST_TEST_UNREGISTER(voicemail_api_off_nominal_msg_playback);
1551  return 0;
1552 }
1553 
1554 static int load_module(void)
1555 {
1556  /* Snapshot tests */
1557  AST_TEST_REGISTER(voicemail_api_nominal_snapshot);
1558  AST_TEST_REGISTER(voicemail_api_off_nominal_snapshot);
1559 
1560  /* Move Tests */
1561  AST_TEST_REGISTER(voicemail_api_nominal_move);
1562  AST_TEST_REGISTER(voicemail_api_off_nominal_move);
1563 
1564  /* Remove Tests */
1565  AST_TEST_REGISTER(voicemail_api_nominal_remove);
1566  AST_TEST_REGISTER(voicemail_api_off_nominal_remove);
1567 
1568  /* Forward Tests */
1569  AST_TEST_REGISTER(voicemail_api_nominal_forward);
1570  AST_TEST_REGISTER(voicemail_api_off_nominal_forward);
1571 
1572  /* Message Playback Tests */
1573  AST_TEST_REGISTER(voicemail_api_nominal_msg_playback);
1574  AST_TEST_REGISTER(voicemail_api_off_nominal_msg_playback);
1575 
1576  return AST_MODULE_LOAD_SUCCESS;
1577 }
1578 
1579 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Core Voicemail API Tests");
#define VM_API_REMOVE_MESSAGE_OFF_NOMINAL(mailbox, context, number_of_messages, folder, message_numbers_in)
static void test_vm_api_test_teardown(void)
static const struct ast_channel_tech mock_channel_tech
static void test_vm_api_destroy_mailbox_voicemails(const char *mailbox, struct ast_vm_mailbox_snapshot *mailbox_snapshot)
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
const ast_string_field msg_id
struct ast_vm_msg_snapshot::@222 msg
Main Channel structure associated with a channel.
const ast_string_field origdate
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
const ast_string_field duration
const ast_string_field folder_name
#define VM_API_TEST_CLEANUP
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
int(*const write)(struct ast_channel *chan, struct ast_frame *frame)
Write a frame, in standard format (see frame.h)
Definition: channel.h:751
#define VOICEMAIL_DIR_MODE
#define VM_API_SNAPSHOT_OFF_NOMINAL_TEST(mailbox, context, folder, desc, sort, old_and_inbox)
static void test_vm_api_remove_all_messages(void)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
static int test_vm_api_test_setup(void)
#define AST_LOG_WARNING
Definition: logger.h:279
static int get_folder_by_name(const char *folder)
Test Framework API.
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
static int unload_module(void)
int ast_vm_test_destroy_user(const char *context, const char *mailbox)
Definition: main/app.c:821
const ast_string_field callerchan
int ast_unlock_path(const char *path)
Unlock a path.
Definition: main/app.c:2473
#define NULL
Definition: resample.c:96
#define VM_API_FORWARD_MESSAGE_OFF_NOMINAL(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, number_of_messages, message_numbers_in, delete_old)
static void test_vm_api_destroy_mock_snapshot(struct ast_vm_msg_snapshot *snapshot)
static int test_vm_api_create_voicemail_files(const char *context, const char *mailbox, struct ast_vm_msg_snapshot *snapshot)
#define VM_API_PLAYBACK_MESSAGE(channel, mailbox, context, folder, message, callback_fn)
static struct ast_channel * test_vm_api_create_mock_channel(void)
static int test_vm_api_mock_channel_write(struct ast_channel *chan, struct ast_frame *frame)
Utility functions.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define VM_API_INT_VERIFY(expected, actual)
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define VM_API_FORWARD_MESSAGE(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, number_of_messages, message_numbers_in, delete_old)
enum AST_LOCK_RESULT ast_lock_path(const char *path)
Lock a filesystem path.
Definition: main/app.c:2457
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
static int load_module(void)
#define ast_log
Definition: astobj2.c:42
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
const ast_string_field exten
#define AST_LOG_ERROR
Definition: logger.h:290
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
AST_TEST_DEFINE(voicemail_api_nominal_snapshot)
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define VM_API_TEST_SETUP
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
static void message_playback_callback_fn(struct ast_channel *chan, const char *file, int duration)
#define AST_MAX_EXTENSION
Definition: channel.h:135
struct ast_format * ast_format_gsm
Built-in cached gsm format.
Definition: format_cache.c:101
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
#define VM_API_MOVE_MESSAGE(mailbox, context, number_of_messages, source, message_numbers_in, dest)
#define VM_API_REMOVE_MESSAGE(mailbox, context, number_of_messages, folder, message_numbers_in)
const ast_string_field origtime
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
static int test_vm_api_create_voicemail_folder(const char *folder_path)
struct ast_vm_mailbox_snapshot * ast_vm_mailbox_snapshot_destroy(struct ast_vm_mailbox_snapshot *mailbox_snapshot)
destroy a snapshot
Definition: main/app.c:748
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629
#define VM_API_SNAPSHOT_MSG_VERIFY(expected, actual, expected_folder, expected_index)
static int global_entered_playback_callback
static struct ast_frame * test_vm_api_mock_channel_read(struct ast_channel *chan)
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
static struct ast_vm_msg_snapshot * test_snapshots[TOTAL_SNAPSHOTS]
#define VM_API_STRING_FIELD_VERIFY(expected, actual)
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
#define VM_API_SNAPSHOT_CREATE(mailbox, context, folder, desc, sort, old_and_inbox)
struct ast_vm_mailbox_snapshot * ast_vm_mailbox_snapshot_create(const char *mailbox, const char *context, const char *folder, int descending, enum ast_vm_snapshot_sort_val sort_val, int combine_INBOX_and_OLD)
Create a snapshot of a mailbox which contains information about every msg.
Definition: main/app.c:734
struct ast_vm_mailbox_snapshot::@223 * snapshots
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
def info(msg)
int errno
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
long int flag
Definition: f2c.h:83
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define AST_MAX_CONTEXT
Definition: channel.h:136
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:154
static void test_vm_api_update_test_snapshots(struct ast_vm_mailbox_snapshot *mailbox_snapshot)
const ast_string_field flag
#define VM_API_PLAYBACK_MESSAGE_OFF_NOMINAL(channel, mailbox, context, folder, message, callback_fn)
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define VM_API_MOVE_MESSAGE_OFF_NOMINAL(mailbox, context, number_of_messages, source, message_numbers_in, dest)
#define VOICEMAIL_FILE_MODE
Data structure associated with a single frame of data.
const ast_string_field callerid
static struct ast_vm_msg_snapshot * test_vm_api_create_mock_snapshot(const char *context, const char *exten, const char *callerid)
#define PATH_MAX
Definition: asterisk.h:40
int ast_vm_test_create_user(const char *context, const char *mailbox)
Definition: main/app.c:813
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
Asterisk module definitions.
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
#define TOTAL_SNAPSHOTS
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
Media Format Cache API.
static void test_vm_api_remove_voicemail(struct ast_vm_msg_snapshot *snapshot)
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: main/utils.c:2231
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
static const char *const mailbox_folders[]