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