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