Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
test_devicestate.c File Reference

Device State Test Module. More...

#include "asterisk.h"
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/test.h"
#include "asterisk/devicestate.h"
#include "asterisk/pbx.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/vector.h"
Include dependency graph for test_devicestate.c:

Go to the source code of this file.

Data Structures

struct  consumer
 

Macros

#define DEVICE_STATE_CHANNEL_TYPE   "TestDeviceState"
 
#define DEVSTATE_PROVIDER   "TestDevState"
 
#define DEVSTATE_PROVIDER_LC   "testdevstate"
 
#define DEVSTATE_PROVIDER_LEN   12
 
#define UNIT_TEST_DEVICE_IDENTIFIER   "unit_test_device_identifier"
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (device2extenstate_test)
 
 AST_TEST_DEFINE (device_state_aggregation_test)
 
 AST_TEST_DEFINE (devstate_prov_add)
 
 AST_TEST_DEFINE (devstate_prov_del)
 
 AST_TEST_DEFINE (devstate_changed)
 
 AST_TEST_DEFINE (devstate_conversions)
 
 AST_TEST_DEFINE (devstate_channels)
 
static AST_VECTOR (, enum ast_device_state) result_states
 The resulting device state updates caused by some function call. More...
 
static void cache_cleanup (int unused)
 
static int chan_test_devicestate_cb (const char *device_number)
 
static void clear_result_states (void)
 Clear out all recorded device states in result_states. More...
 
static struct consumerconsumer_create (void)
 
static void consumer_dtor (void *obj)
 
static void consumer_exec (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void consumer_finalize (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void consumer_reset (struct consumer *consumer)
 
static void consumer_wait_for (struct consumer *consumer)
 
static void device_state_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 Stasis subscription callback for device state updates. More...
 
static enum ast_device_state devstate_prov_cb (const char *data)
 
static int load_module (void)
 
static int remove_device_states_cb (void *obj, void *arg, int flags)
 
static void safe_hangup (void *object)
 
static int unload_module (void)
 
static int wait_for_channel_callback (struct ast_test *test)
 Wait until the test channel driver's devicestate callback is called. More...
 
static int wait_for_device_state_updates (struct ast_test *test, int expected_updates)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Device State Test" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static int chan_callback_called
 Whether or not the channel device state callback was called. More...
 
static unsigned int chan_idx
 Used to assign an increasing integer to channel name. More...
 
struct ast_channel_tech chan_test_devicestate
 
static ast_cond_t channel_cb_cond
 Condition wait variable for channel tech device state cb. More...
 
static ast_mutex_t channel_cb_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Mutext for channel_cb_cond. More...
 
static int combined_results []
 
static enum ast_device_state current_device_state
 The current device state for our device state provider. More...
 
static int exten_results []
 
static ast_cond_t update_cond
 Condition wait variable for device state updates. More...
 
static ast_mutex_t update_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Mutex for update_cond. More...
 

Detailed Description

Device State Test Module.

Author
David Vossel dvoss[email protected][email protected][email protected]igium[email protected].com

Definition in file test_devicestate.c.

Macro Definition Documentation

◆ DEVICE_STATE_CHANNEL_TYPE

#define DEVICE_STATE_CHANNEL_TYPE   "TestDeviceState"

Definition at line 45 of file test_devicestate.c.

Referenced by AST_TEST_DEFINE().

◆ DEVSTATE_PROVIDER

#define DEVSTATE_PROVIDER   "TestDevState"

Definition at line 47 of file test_devicestate.c.

Referenced by AST_TEST_DEFINE(), and device_state_cb().

◆ DEVSTATE_PROVIDER_LC

#define DEVSTATE_PROVIDER_LC   "testdevstate"

Definition at line 49 of file test_devicestate.c.

Referenced by AST_TEST_DEFINE().

◆ DEVSTATE_PROVIDER_LEN

#define DEVSTATE_PROVIDER_LEN   12

Definition at line 51 of file test_devicestate.c.

Referenced by device_state_cb().

◆ UNIT_TEST_DEVICE_IDENTIFIER

#define UNIT_TEST_DEVICE_IDENTIFIER   "unit_test_device_identifier"

Definition at line 43 of file test_devicestate.c.

Referenced by AST_TEST_DEFINE(), consumer_exec(), and remove_device_states_cb().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 969 of file test_devicestate.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 969 of file test_devicestate.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 969 of file test_devicestate.c.

◆ AST_TEST_DEFINE() [1/7]

AST_TEST_DEFINE ( device2extenstate_test  )

Definition at line 312 of file test_devicestate.c.

References ARRAY_LEN, AST_DEVICE_TOTAL, ast_devstate2str(), ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_extension_state2str(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, combined_results, exten, exten_results, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

313 {
314  int res = AST_TEST_PASS;
315  struct ast_devstate_aggregate agg;
316  enum ast_device_state i, j, combined;
318  int k = 0;
319 
320  switch (cmd) {
321  case TEST_INIT:
322  info->name = "device2extenstate_test";
323  info->category = "/main/devicestate/";
324  info->summary = "Tests combined devstate mapping and device to extension state mapping.";
325  info->description =
326  "Verifies device state aggregate results match the expected combined "
327  "devstate. Then verifies the combined devstate maps to the expected "
328  "extension state.";
329  return AST_TEST_NOT_RUN;
330  case TEST_EXECUTE:
331  break;
332  }
333 
335  ast_test_status_update(test, "Result array is %d long when it should be %d. "
336  "Something has changed, this test must be updated.\n",
337  (int) ARRAY_LEN(exten_results), (AST_DEVICE_TOTAL * AST_DEVICE_TOTAL));
338  return AST_TEST_FAIL;
339  }
340 
342  ast_test_status_update(test, "combined_results and exten_results arrays do not match in length.\n");
343  return AST_TEST_FAIL;
344  }
345 
346  for (i = 0; i < AST_DEVICE_TOTAL; i++) {
347  for (j = 0; j < AST_DEVICE_TOTAL; j++) {
351  combined = ast_devstate_aggregate_result(&agg);
352  if (combined_results[k] != combined) {
353  ast_test_status_update(test, "Expected combined dev state %s "
354  "does not match %s at combined_result[%d].\n",
356  ast_devstate2str(combined), k);
357  res = AST_TEST_FAIL;
358  }
359 
360  exten = ast_devstate_to_extenstate(combined);
361 
362  if (exten_results[k] != exten) {
363  ast_test_status_update(test, "Expected exten state %s "
364  "does not match %s at exten_result[%d]\n",
366  ast_extension_state2str(exten), k);
367  res = AST_TEST_FAIL;
368  }
369  k++;
370  }
371  }
372 
373  return res;
374 }
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
ast_device_state
Device States.
Definition: devicestate.h:52
ast_extension_states
Extension states.
Definition: pbx.h:61
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int combined_results[]
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
Definition: devicestate.c:663
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
const char * ast_extension_state2str(int extension_state)
Return string representation of the state of an extension.
Definition: pbx.c:3126
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
Definition: devicestate.c:636
def info(msg)
enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
Map devstate to an extension state.
Definition: pbx.c:3006
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
Definition: devicestate.c:630
You shouldn&#39;t care about the contents of this struct.
Definition: devicestate.h:230
static int exten_results[]

◆ AST_TEST_DEFINE() [2/7]

AST_TEST_DEFINE ( device_state_aggregation_test  )

Definition at line 511 of file test_devicestate.c.

References consumer::aggregate_state, ao2_cleanup, ao2_ref, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, ast_device_state_cache(), ast_device_state_message_type(), ast_device_state_topic_cached(), AST_DEVICE_TOTAL, AST_DEVSTATE_CACHABLE, ast_free, ast_malloc, ast_publish_device_state, ast_publish_device_state_full(), AST_TEST_NOT_RUN, AST_TEST_PASS, cache_cleanup(), consumer_create(), consumer_exec(), consumer_finalize(), consumer_reset(), consumer_wait_for(), consumer::event_count, sip_to_pjsip::info(), NULL, RAII_VAR, consumer::sig_on_non_aggregate_state, stasis_cache_get_by_eid(), stasis_cache_update_type(), stasis_message_data(), stasis_message_router_add(), stasis_message_router_create, stasis_message_router_unsubscribe(), stasis_subscription_change_type(), ast_device_state_message::state, consumer::state, TEST_EXECUTE, TEST_INIT, and UNIT_TEST_DEVICE_IDENTIFIER.

512 {
515  RAII_VAR(struct ast_eid *, foreign_eid, NULL, ast_free);
516  RAII_VAR(int, cleanup_cache, 0, cache_cleanup);
517  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
518  int res;
519  struct ast_device_state_message *device_state;
520 
521  switch (cmd) {
522  case TEST_INIT:
523  info->name = "device_state_aggregation_test";
524  info->category = "/main/devicestate/";
525  info->summary = "Tests message routing and aggregation through the Stasis device state system.";
526  info->description =
527  "Verifies that the device state system passes "
528  "messages appropriately, that the aggregator is "
529  "working properly, that the aggregate results match "
530  "the expected combined devstate, and that the cached "
531  "aggregate devstate is correct.";
532  return AST_TEST_NOT_RUN;
533  case TEST_EXECUTE:
534  break;
535  }
536 
537  foreign_eid = ast_malloc(sizeof(*foreign_eid));
538  ast_test_validate(test, NULL != foreign_eid);
539  memset(foreign_eid, 0xFF, sizeof(*foreign_eid));
540 
542  ast_test_validate(test, NULL != consumer);
543 
545  ast_test_validate(test, NULL != device_msg_router);
546 
547  ao2_ref(consumer, +1);
549  ast_test_validate(test, !res);
550 
552  ast_test_validate(test, !res);
553 
554  /* push local state */
556 
557  /* Check cache aggregate state immediately */
558  ao2_cleanup(msg);
560  device_state = stasis_message_data(msg);
561  ast_test_validate(test, AST_DEVICE_NOT_INUSE == device_state->state);
562 
564  ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->state);
565  ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->aggregate_state);
566  ast_test_validate(test, 2 == consumer->event_count);
568 
569  /* push remote state */
570  /* this will not produce a new aggregate state message since the aggregate state does not change */
573 
574  /* Check cache aggregate state immediately */
575  ao2_cleanup(msg);
577  device_state = stasis_message_data(msg);
578  ast_test_validate(test, AST_DEVICE_NOT_INUSE == device_state->state);
579 
580  /* Check for expected events. */
582  ast_test_validate(test, AST_DEVICE_NOT_INUSE == consumer->state);
583  ast_test_validate(test, AST_DEVICE_TOTAL == consumer->aggregate_state);
584  ast_test_validate(test, 1 == consumer->event_count);
586 
587  /* push remote state different from local state */
589 
590  /* Check cache aggregate state immediately */
591  ao2_cleanup(msg);
593  device_state = stasis_message_data(msg);
594  ast_test_validate(test, AST_DEVICE_INUSE == device_state->state);
595 
596  /* Check for expected events. */
598  ast_test_validate(test, AST_DEVICE_INUSE == consumer->state);
599  ast_test_validate(test, AST_DEVICE_INUSE == consumer->aggregate_state);
600  ast_test_validate(test, 2 == consumer->event_count);
602 
603  /* push local state that will cause aggregated state different from local non-aggregate state */
605 
606  /* Check cache aggregate state immediately */
607  ao2_cleanup(msg);
609  device_state = stasis_message_data(msg);
610  ast_test_validate(test, AST_DEVICE_RINGINUSE == device_state->state);
611 
612  /* Check for expected events. */
614  ast_test_validate(test, AST_DEVICE_RINGING == consumer->state);
615  ast_test_validate(test, AST_DEVICE_RINGINUSE == consumer->aggregate_state);
616  ast_test_validate(test, 2 == consumer->event_count);
618 
619  return AST_TEST_PASS;
620 }
#define UNIT_TEST_DEVICE_IDENTIFIER
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
enum ast_device_state state
Definition: devicestate.h:250
static void cache_cleanup(int unused)
static void consumer_finalize(void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct stasis_message * stasis_cache_get_by_eid(struct stasis_cache *cache, struct stasis_message_type *type, const char *id, const struct ast_eid *eid)
Retrieve an item from the cache for a specific entity.
Definition: stasis_cache.c:659
#define NULL
Definition: resample.c:96
An Entity ID is essentially a MAC address, brief and unique.
Definition: utils.h:786
int sig_on_non_aggregate_state
static struct consumer * consumer_create(void)
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
struct stasis_topic * ast_device_state_topic_cached(void)
Get the Stasis caching topic for device state messages.
Definition: devicestate.c:678
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct stasis_message_type * stasis_cache_update_type(void)
Message type for cache update messages.
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define stasis_message_router_create(topic)
static void consumer_reset(struct consumer *consumer)
int ast_publish_device_state_full(const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, struct ast_eid *eid)
Publish a device state update with EID.
Definition: devicestate.c:709
struct stasis_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
Definition: devicestate.c:673
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
def info(msg)
#define ast_free(a)
Definition: astmm.h:182
enum ast_device_state state
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void stasis_message_router_unsubscribe(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic.
enum ast_device_state aggregate_state
The structure that contains device state.
Definition: devicestate.h:240
struct stasis_message_type * stasis_subscription_change_type(void)
Gets the message type for subscription change notices.
static void consumer_exec(void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void consumer_wait_for(struct consumer *consumer)
#define ast_publish_device_state(device, state, cachable)
Publish a device state update.
Definition: devicestate.h:323

◆ AST_TEST_DEFINE() [3/7]

AST_TEST_DEFINE ( devstate_prov_add  )

Definition at line 622 of file test_devicestate.c.

References ast_devstate_prov_add(), ast_devstate_prov_del(), AST_TEST_NOT_RUN, AST_TEST_PASS, devstate_prov_cb(), DEVSTATE_PROVIDER, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

623 {
624  switch (cmd) {
625  case TEST_INIT:
626  info->name = __func__;
627  info->category = "/main/devicestate/";
628  info->summary = "Test adding a device state provider";
629  info->description =
630  "Test that a custom device state provider can be added, and that\n"
631  "it cannot be added if already added.";
632  return AST_TEST_NOT_RUN;
633  case TEST_EXECUTE:
634  break;
635  }
636 
639  ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) == 0);
640 
641  return AST_TEST_PASS;
642 }
#define DEVSTATE_PROVIDER
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:418
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:391
static enum ast_device_state devstate_prov_cb(const char *data)
def info(msg)

◆ AST_TEST_DEFINE() [4/7]

AST_TEST_DEFINE ( devstate_prov_del  )

Definition at line 644 of file test_devicestate.c.

References ast_devstate_prov_add(), ast_devstate_prov_del(), AST_TEST_NOT_RUN, AST_TEST_PASS, devstate_prov_cb(), DEVSTATE_PROVIDER, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

645 {
646  switch (cmd) {
647  case TEST_INIT:
648  info->name = __func__;
649  info->category = "/main/devicestate/";
650  info->summary = "Test removing a device state provider";
651  info->description =
652  "Test that a custom device state provider can be removed, and that\n"
653  "it cannot be removed if already removed.";
654  return AST_TEST_NOT_RUN;
655  case TEST_EXECUTE:
656  break;
657  }
658 
660  ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) == 0);
661  ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) != 0);
662 
663  return AST_TEST_PASS;
664 }
#define DEVSTATE_PROVIDER
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:418
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:391
static enum ast_device_state devstate_prov_cb(const char *data)
def info(msg)

◆ AST_TEST_DEFINE() [5/7]

AST_TEST_DEFINE ( devstate_changed  )

Definition at line 666 of file test_devicestate.c.

References ao2_cleanup, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, ast_device_state_topic_all(), AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, ast_devstate_changed_literal(), AST_DEVSTATE_NOT_CACHABLE, ast_devstate_prov_add(), ast_devstate_prov_del(), AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, AST_VECTOR_GET, AST_VECTOR_SIZE, clear_result_states(), current_device_state, device_state_cb(), devstate_prov_cb(), DEVSTATE_PROVIDER, DEVSTATE_PROVIDER_LC, sip_to_pjsip::info(), NULL, RAII_VAR, stasis_subscribe, stasis_unsubscribe_and_join(), sub, TEST_EXECUTE, TEST_INIT, and wait_for_device_state_updates().

667 {
669  int i;
670  enum ast_device_state expected_results[] = {
679  };
680 
681  switch (cmd) {
682  case TEST_INIT:
683  info->name = __func__;
684  info->category = "/main/devicestate/";
685  info->summary = "Test updates coming from a device state provider";
686  info->description =
687  "This unit test checks that a custom device state provider can\n"
688  "have updates published for it. This includes both cacheable and\n"
689  "non-cacheable events. In the case of non-cacheable events, the\n"
690  "device state provider's callback function is queried for the\n"
691  "device state when AST_DEVICE_UNKNOWN is published.";
692  return AST_TEST_NOT_RUN;
693  case TEST_EXECUTE:
694  break;
695  }
696 
698 
701 
703 
712 
713  ast_test_validate(test, wait_for_device_state_updates(test, 8) == 0);
714 
715  for (i = 0; i < AST_VECTOR_SIZE(&result_states); i++) {
716  ast_test_status_update(test, "Testing update %d: actual is %d; expected is %d\n",
717  i,
718  AST_VECTOR_GET(&result_states, i),
719  expected_results[i]);
720  ast_test_validate(test, AST_VECTOR_GET(&result_states, i) == expected_results[i]);
721  }
722 
725 
726  /*
727  * Since an update of AST_DEVICE_UNKNOWN will cause a different thread to retrieve
728  * the update from the custom device state provider, check it separately from the
729  * updates above.
730  */
733  ast_test_validate(test, wait_for_device_state_updates(test, 1) == 0);
734 
735  ast_test_validate(test, AST_VECTOR_GET(&result_states, 0) == AST_DEVICE_BUSY);
736  ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER ":foo") == AST_DEVICE_BUSY);
737  ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER_LC ":foo") == AST_DEVICE_BUSY);
738 
741 
751 
752  ast_test_validate(test, wait_for_device_state_updates(test, 8) == 0);
753  for (i = 0; i < AST_VECTOR_SIZE(&result_states); i++) {
754  ast_test_status_update(test, "Testing update %d: actual is %d; expected is %d\n",
755  i,
756  AST_VECTOR_GET(&result_states, i),
757  expected_results[i]);
758  ast_test_validate(test, AST_VECTOR_GET(&result_states, i) == expected_results[i]);
759  }
760 
761  /*
762  * Check the last value in the cache. Note that this should not hit
763  * the value of current_device_state.
764  */
765  ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER ":foo") == AST_DEVICE_ONHOLD);
766  /*
767  * This will miss on the cache, as it is case sensitive. It should go
768  * hit our device state callback however.
769  */
770  ast_test_validate(test, ast_device_state(DEVSTATE_PROVIDER_LC ":foo") == AST_DEVICE_BUSY);
771 
772  /* Generally, this test can't be run twice in a row, as you can't remove an
773  * item from the cache. Hence, subsequent runs won't hit the device state provider,
774  * and will merely return the cached value.
775  *
776  * To avoid annoying errors, set the last state to BUSY here.
777  */
779 
780  ast_test_validate(test, ast_devstate_prov_del(DEVSTATE_PROVIDER) == 0);
781 
784 
785  return AST_TEST_PASS;
786 }
ast_device_state
Device States.
Definition: devicestate.h:52
static enum ast_device_state current_device_state
The current device state for our device state provider.
#define DEVSTATE_PROVIDER
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:418
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:391
#define NULL
Definition: resample.c:96
static int wait_for_device_state_updates(struct ast_test *test, int expected_updates)
static void device_state_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Stasis subscription callback for device state updates.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
static enum ast_device_state devstate_prov_cb(const char *data)
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:652
def info(msg)
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:668
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1136
#define DEVSTATE_PROVIDER_LC
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static void clear_result_states(void)
Clear out all recorded device states in result_states.
struct stasis_forward * sub
Definition: res_corosync.c:240
int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:471
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ AST_TEST_DEFINE() [6/7]

AST_TEST_DEFINE ( devstate_conversions  )

Definition at line 788 of file test_devicestate.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_str(), ast_devstate_val(), AST_STATE_BUSY, ast_state_chan2dev(), AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_OFFHOOK, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

789 {
790  switch (cmd) {
791  case TEST_INIT:
792  info->name = __func__;
793  info->category = "/main/devicestate/";
794  info->summary = "Test ast_device_state conversions";
795  info->description =
796  "Test various transformations of ast_device_state values.";
797  return AST_TEST_NOT_RUN;
798  case TEST_EXECUTE:
799  break;
800  }
801 
802  ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_UNKNOWN), "UNKNOWN"));
803  ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_NOT_INUSE), "NOT_INUSE"));
804  ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_INUSE), "INUSE"));
805  ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_BUSY), "BUSY"));
806  ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_INVALID), "INVALID"));
807  ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_UNAVAILABLE), "UNAVAILABLE"));
808  ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_RINGING), "RINGING"));
809  ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_RINGINUSE), "RINGINUSE"));
810  ast_test_validate(test, !strcmp(ast_devstate_str(AST_DEVICE_ONHOLD), "ONHOLD"));
811 
812  ast_test_validate(test, ast_devstate_val("UNKNOWN") == AST_DEVICE_UNKNOWN);
813  ast_test_validate(test, ast_devstate_val("NOT_INUSE") == AST_DEVICE_NOT_INUSE);
814  ast_test_validate(test, ast_devstate_val("INUSE") == AST_DEVICE_INUSE);
815  ast_test_validate(test, ast_devstate_val("BUSY") == AST_DEVICE_BUSY);
816  ast_test_validate(test, ast_devstate_val("INVALID") == AST_DEVICE_INVALID);
817  ast_test_validate(test, ast_devstate_val("UNAVAILABLE") == AST_DEVICE_UNAVAILABLE);
818  ast_test_validate(test, ast_devstate_val("RINGING") == AST_DEVICE_RINGING);
819  ast_test_validate(test, ast_devstate_val("RINGINUSE") == AST_DEVICE_RINGINUSE);
820  ast_test_validate(test, ast_devstate_val("ONHOLD") == AST_DEVICE_ONHOLD);
821  ast_test_validate(test, ast_devstate_val("onhold") == AST_DEVICE_ONHOLD);
822  ast_test_validate(test, ast_devstate_val("FOO") == AST_DEVICE_UNKNOWN);
823 
828  ast_test_validate(test, ast_state_chan2dev(AST_STATE_RING) == AST_DEVICE_INUSE);
830  ast_test_validate(test, ast_state_chan2dev(AST_STATE_UP) == AST_DEVICE_INUSE);
831  ast_test_validate(test, ast_state_chan2dev(AST_STATE_BUSY) == AST_DEVICE_BUSY);
834 
835  return AST_TEST_PASS;
836 }
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
Definition: devicestate.c:260
enum ast_device_state ast_state_chan2dev(enum ast_channel_state chanstate)
Convert channel state to devicestate.
Definition: devicestate.c:242
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
Definition: devicestate.c:255
def info(msg)

◆ AST_TEST_DEFINE() [7/7]

AST_TEST_DEFINE ( devstate_channels  )

Definition at line 871 of file test_devicestate.c.

References ast_atomic_fetchadd_int(), ast_channel_alloc, AST_DEVICE_INUSE, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, ast_parse_device_state(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, AST_TEST_NOT_RUN, AST_TEST_PASS, chan_callback_called, chan_idx, DEVICE_STATE_CHANNEL_TYPE, sip_to_pjsip::info(), NULL, RAII_VAR, safe_hangup(), TEST_EXECUTE, TEST_INIT, and wait_for_channel_callback().

872 {
873  RAII_VAR(struct ast_channel *, chan, NULL, safe_hangup);
874 
875  switch (cmd) {
876  case TEST_INIT:
877  info->name = __func__;
878  info->category = "/main/devicestate/";
879  info->summary = "Test deriving device state from a channel's state";
880  info->description =
881  "Test querying a channel's state to derive a device state.";
882  return AST_TEST_NOT_RUN;
883  case TEST_EXECUTE:
884  break;
885  }
886 
888 
889  chan = ast_channel_alloc(0, AST_STATE_RINGING, "", "", "", "s", "default",
890  NULL, NULL, 0, DEVICE_STATE_CHANNEL_TYPE "/foo-%08x",
891  (unsigned) ast_atomic_fetchadd_int((int *) &chan_idx, +1));
892  ast_test_validate(test, chan != NULL);
893 
896 
897  ast_setstate(chan, AST_STATE_UP);
898 
899  ast_test_validate(test, wait_for_channel_callback(test) == 1);
901 
903 
904  return AST_TEST_PASS;
905 }
#define DEVICE_STATE_CHANNEL_TYPE
Main Channel structure associated with a channel.
static unsigned int chan_idx
Used to assign an increasing integer to channel name.
enum ast_device_state ast_parse_device_state(const char *device)
Search the Channels by Name.
Definition: devicestate.c:287
#define NULL
Definition: resample.c:96
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
static int chan_callback_called
Whether or not the channel device state callback was called.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static void safe_hangup(void *object)
def info(msg)
static int wait_for_channel_callback(struct ast_test *test)
Wait until the test channel driver&#39;s devicestate callback is called.
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7486
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259

◆ AST_VECTOR()

static AST_VECTOR ( enum  ast_device_state)
static

The resulting device state updates caused by some function call.

◆ cache_cleanup()

static void cache_cleanup ( int  unused)
static

Definition at line 498 of file test_devicestate.c.

References ao2_callback, ao2_cleanup, ast_device_state_cache(), NULL, remove_device_states_cb(), and stasis_cache_dump_all().

Referenced by AST_TEST_DEFINE().

499 {
500  struct ao2_container *cache_dump;
501 
502  /* remove all device states created during this test */
504  if (!cache_dump) {
505  return;
506  }
507  ao2_callback(cache_dump, 0, remove_device_states_cb, NULL);
508  ao2_cleanup(cache_dump);
509 }
struct ao2_container * stasis_cache_dump_all(struct stasis_cache *cache, struct stasis_message_type *type)
Dump all entity items from the cache to a subscription.
Definition: stasis_cache.c:757
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define NULL
Definition: resample.c:96
static int remove_device_states_cb(void *obj, void *arg, int flags)
struct stasis_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
Definition: devicestate.c:673
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Generic container type.

◆ chan_test_devicestate_cb()

static int chan_test_devicestate_cb ( const char *  device_number)
static

Definition at line 907 of file test_devicestate.c.

References ast_cond_signal, AST_DEVICE_INUSE, ast_mutex_lock, ast_mutex_unlock, chan_callback_called, channel_cb_cond, and channel_cb_lock.

908 {
909  /* Simply record that we were called when expected */
911 
915 
916  return AST_DEVICE_INUSE;
917 }
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_cond_signal(cond)
Definition: lock.h:201
static ast_mutex_t channel_cb_lock
Mutext for channel_cb_cond.
static int chan_callback_called
Whether or not the channel device state callback was called.
static ast_cond_t channel_cb_cond
Condition wait variable for channel tech device state cb.
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ clear_result_states()

static void clear_result_states ( void  )
static

Clear out all recorded device states in result_states.

Definition at line 244 of file test_devicestate.c.

References ast_mutex_lock, ast_mutex_unlock, AST_VECTOR_REMOVE_UNORDERED, AST_VECTOR_SIZE, and update_lock.

Referenced by AST_TEST_DEFINE().

245 {
247  while (AST_VECTOR_SIZE(&result_states) > 0) {
248  AST_VECTOR_REMOVE_UNORDERED(&result_states, 0);
249  }
251 }
static ast_mutex_t update_lock
Mutex for update_cond.
#define AST_VECTOR_REMOVE_UNORDERED(vec, idx)
Remove an element from an unordered vector by index.
Definition: vector.h:438
#define ast_mutex_lock(a)
Definition: lock.h:187
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ consumer_create()

static struct consumer* consumer_create ( void  )
static

Definition at line 400 of file test_devicestate.c.

References ao2_alloc, ast_cond_init, consumer_dtor(), consumer_reset(), NULL, and consumer::out.

Referenced by AST_TEST_DEFINE().

401 {
402  struct consumer *consumer;
403 
404  consumer = ao2_alloc(sizeof(*consumer), consumer_dtor);
405  if (!consumer) {
406  return NULL;
407  }
408 
409  ast_cond_init(&consumer->out, NULL);
410  consumer_reset(consumer);
411 
412  return consumer;
413 }
ast_cond_t out
#define ast_cond_init(cond, attr)
Definition: lock.h:199
static void consumer_dtor(void *obj)
#define NULL
Definition: resample.c:96
static void consumer_reset(struct consumer *consumer)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411

◆ consumer_dtor()

static void consumer_dtor ( void *  obj)
static

Definition at line 385 of file test_devicestate.c.

References ast_cond_destroy, and consumer::out.

Referenced by consumer_create().

386 {
387  struct consumer *consumer = obj;
388 
389  ast_cond_destroy(&consumer->out);
390 }
ast_cond_t out
#define ast_cond_destroy(cond)
Definition: lock.h:200

◆ consumer_exec()

static void consumer_exec ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 415 of file test_devicestate.c.

References consumer::aggregate_state, consumer::already_out, ast_cond_signal, cache_update(), ast_device_state_message::device, ast_device_state_message::eid, consumer::event_count, lock, stasis_cache_update::new_snapshot, consumer::out, SCOPED_AO2LOCK, consumer::sig_on_non_aggregate_state, stasis_message_data(), ast_device_state_message::state, consumer::state, and UNIT_TEST_DEVICE_IDENTIFIER.

Referenced by AST_TEST_DEFINE().

416 {
417  struct consumer *consumer = data;
419  struct ast_device_state_message *device_state;
420 
421  if (!cache_update->new_snapshot) {
422  return;
423  }
424 
425  device_state = stasis_message_data(cache_update->new_snapshot);
426 
427  if (strcmp(device_state->device, UNIT_TEST_DEVICE_IDENTIFIER)) {
428  /* not a device state we're interested in */
429  return;
430  }
431 
432  {
433  SCOPED_AO2LOCK(lock, consumer);
434 
435  ++consumer->event_count;
436  if (device_state->eid) {
437  consumer->state = device_state->state;
438  if (consumer->sig_on_non_aggregate_state) {
439  consumer->sig_on_non_aggregate_state = 0;
440  consumer->already_out = 1;
441  ast_cond_signal(&consumer->out);
442  }
443  } else {
444  consumer->aggregate_state = device_state->state;
445  consumer->already_out = 1;
446  ast_cond_signal(&consumer->out);
447  }
448  }
449 }
#define UNIT_TEST_DEVICE_IDENTIFIER
ast_cond_t out
enum ast_device_state state
Definition: devicestate.h:250
#define ast_cond_signal(cond)
Definition: lock.h:201
int sig_on_non_aggregate_state
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
ast_mutex_t lock
Definition: app_meetme.c:1091
Cache update message.
Definition: stasis.h:967
static int cache_update(struct stasis_message *msg, const void *data)
Message matcher looking for cache update messages.
struct stasis_message * new_snapshot
New value.
Definition: stasis.h:973
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
enum ast_device_state state
enum ast_device_state aggregate_state
The structure that contains device state.
Definition: devicestate.h:240

◆ consumer_finalize()

static void consumer_finalize ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 451 of file test_devicestate.c.

References ao2_cleanup, and stasis_subscription_final_message().

Referenced by AST_TEST_DEFINE().

452 {
453  struct consumer *consumer = data;
454 
455  if (stasis_subscription_final_message(sub, message)) {
456  ao2_cleanup(consumer);
457  }
458 }
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
Definition: stasis.c:1176
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ consumer_reset()

static void consumer_reset ( struct consumer consumer)
static

Definition at line 392 of file test_devicestate.c.

References consumer::aggregate_state, consumer::already_out, AST_DEVICE_TOTAL, consumer::event_count, and consumer::state.

Referenced by AST_TEST_DEFINE(), and consumer_create().

393 {
394  consumer->already_out = 0;
395  consumer->event_count = 0;
396  consumer->state = AST_DEVICE_TOTAL;
397  consumer->aggregate_state = AST_DEVICE_TOTAL;
398 }
enum ast_device_state state
enum ast_device_state aggregate_state

◆ consumer_wait_for()

static void consumer_wait_for ( struct consumer consumer)
static

Definition at line 460 of file test_devicestate.c.

References consumer::already_out, ao2_object_get_lockaddr(), ast_cond_timedwait, ast_tvnow(), lock, consumer::out, and SCOPED_AO2LOCK.

Referenced by AST_TEST_DEFINE().

461 {
462  int res;
463  struct timeval start = ast_tvnow();
464  struct timespec end = {
465  .tv_sec = start.tv_sec + 10,
466  .tv_nsec = start.tv_usec * 1000
467  };
468 
469  SCOPED_AO2LOCK(lock, consumer);
470 
471  while (!consumer->already_out) {
472  res = ast_cond_timedwait(&consumer->out, ao2_object_get_lockaddr(consumer), &end);
473  if (!res || res == ETIMEDOUT) {
474  break;
475  }
476  }
477 }
ast_cond_t out
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
char * end
Definition: eagi_proxy.c:73
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
ast_mutex_t lock
Definition: app_meetme.c:1091
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204

◆ device_state_cb()

static void device_state_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Stasis subscription callback for device state updates.

Definition at line 254 of file test_devicestate.c.

References ast_cond_signal, ast_device_state_message_type(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero, AST_VECTOR_APPEND, ast_device_state_message::device, DEVSTATE_PROVIDER, DEVSTATE_PROVIDER_LEN, ast_device_state_message::eid, stasis_message_data(), stasis_message_type(), ast_device_state_message::state, state, update_cond, and update_lock.

Referenced by AST_TEST_DEFINE().

255 {
256  struct ast_device_state_message *payload;
257  enum ast_device_state state;
258  const char *device;
259 
261  return;
262  }
263 
264  payload = stasis_message_data(message);
265  state = payload->state;
266  device = payload->device;
267 
268  if (ast_strlen_zero(device)) {
269  return;
270  }
271 
272  /* Ignore aggregate events */
273  if (!payload->eid) {
274  return;
275  }
276 
277  if (strncasecmp(device, DEVSTATE_PROVIDER, DEVSTATE_PROVIDER_LEN)) {
278  return;
279  }
280 
282  AST_VECTOR_APPEND(&result_states, state);
285 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
ast_device_state
Device States.
Definition: devicestate.h:52
static ast_mutex_t update_lock
Mutex for update_cond.
#define DEVSTATE_PROVIDER
enum ast_device_state state
Definition: devicestate.h:250
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_cond_signal(cond)
Definition: lock.h:201
#define DEVSTATE_PROVIDER_LEN
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
The structure that contains device state.
Definition: devicestate.h:240
#define ast_mutex_unlock(a)
Definition: lock.h:188
static ast_cond_t update_cond
Condition wait variable for device state updates.

◆ devstate_prov_cb()

static enum ast_device_state devstate_prov_cb ( const char *  data)
static

Definition at line 287 of file test_devicestate.c.

References current_device_state.

Referenced by AST_TEST_DEFINE().

288 {
289  return current_device_state;
290 }
static enum ast_device_state current_device_state
The current device state for our device state provider.

◆ load_module()

static int load_module ( void  )
static

Definition at line 944 of file test_devicestate.c.

References ast_channel_register(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_TEST_REGISTER, AST_VECTOR_FREE, and AST_VECTOR_INIT.

945 {
946  if (AST_VECTOR_INIT(&result_states, 8) == -1) {
948  }
949 
951  AST_VECTOR_FREE(&result_states);
953  }
954 
955  AST_TEST_REGISTER(device_state_aggregation_test);
956  AST_TEST_REGISTER(device2extenstate_test);
957 
958  AST_TEST_REGISTER(devstate_prov_add);
959  AST_TEST_REGISTER(devstate_prov_del);
960 
961  AST_TEST_REGISTER(devstate_changed);
962  AST_TEST_REGISTER(devstate_conversions);
963 
964  AST_TEST_REGISTER(devstate_channels);
965 
967 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
struct ast_channel_tech chan_test_devicestate

◆ remove_device_states_cb()

static int remove_device_states_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 479 of file test_devicestate.c.

References ao2_cleanup, ast_device_state_topic(), ast_device_state_message::device, stasis_cache_clear_create(), stasis_message_data(), stasis_publish(), and UNIT_TEST_DEVICE_IDENTIFIER.

Referenced by cache_cleanup().

480 {
481  struct stasis_message *msg = obj;
482  struct ast_device_state_message *device_state = stasis_message_data(msg);
483 
484  if (strcmp(UNIT_TEST_DEVICE_IDENTIFIER, device_state->device)) {
485  /* Not a unit test device */
486  return 0;
487  }
488 
489  msg = stasis_cache_clear_create(msg);
490  if (msg) {
491  /* topic guaranteed to have been created by this point */
492  stasis_publish(ast_device_state_topic(device_state->device), msg);
493  }
494  ao2_cleanup(msg);
495  return 0;
496 }
struct stasis_topic * ast_device_state_topic(const char *device)
Get the Stasis topic for device state messages for a specific device.
Definition: devicestate.c:683
#define UNIT_TEST_DEVICE_IDENTIFIER
struct stasis_message * stasis_cache_clear_create(struct stasis_message *message)
A message which instructs the caching topic to remove an entry from its cache.
Definition: stasis_cache.c:778
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
The structure that contains device state.
Definition: devicestate.h:240

◆ safe_hangup()

static void safe_hangup ( void *  object)
static

Definition at line 861 of file test_devicestate.c.

References ast_hangup().

Referenced by AST_TEST_DEFINE().

862 {
863  struct ast_channel *chan = object;
864 
865  if (!chan) {
866  return;
867  }
868  ast_hangup(chan);
869 }
Main Channel structure associated with a channel.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 925 of file test_devicestate.c.

References ast_channel_unregister(), AST_TEST_UNREGISTER, and AST_VECTOR_FREE.

926 {
927  AST_VECTOR_FREE(&result_states);
929 
930  AST_TEST_UNREGISTER(device2extenstate_test);
931  AST_TEST_UNREGISTER(device_state_aggregation_test);
932 
933  AST_TEST_UNREGISTER(devstate_prov_add);
934  AST_TEST_UNREGISTER(devstate_prov_del);
935 
936  AST_TEST_UNREGISTER(devstate_changed);
937  AST_TEST_UNREGISTER(devstate_conversions);
938 
939  AST_TEST_UNREGISTER(devstate_channels);
940 
941  return 0;
942 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
struct ast_channel_tech chan_test_devicestate

◆ wait_for_channel_callback()

static int wait_for_channel_callback ( struct ast_test test)
static

Wait until the test channel driver's devicestate callback is called.

Definition at line 842 of file test_devicestate.c.

References ast_cond_timedwait, ast_mutex_lock, ast_mutex_unlock, ast_test_status_update, ast_tvnow(), chan_callback_called, channel_cb_cond, channel_cb_lock, and error().

Referenced by AST_TEST_DEFINE().

843 {
844  int error;
845  struct timeval wait_now = ast_tvnow();
846  struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 1, .tv_nsec = wait_now.tv_usec * 1000 };
847 
849  while (!chan_callback_called) {
850  error = ast_cond_timedwait(&channel_cb_cond, &channel_cb_lock, &wait_time);
851  if (error == ETIMEDOUT) {
852  ast_test_status_update(test, "Test timed out while waiting channel callback\n");
853  break;
854  }
855  }
857 
858  return chan_callback_called;
859 }
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t channel_cb_lock
Mutext for channel_cb_cond.
static int chan_callback_called
Whether or not the channel device state callback was called.
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
static ast_cond_t channel_cb_cond
Condition wait variable for channel tech device state cb.
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ wait_for_device_state_updates()

static int wait_for_device_state_updates ( struct ast_test test,
int  expected_updates 
)
static

Definition at line 292 of file test_devicestate.c.

References ast_cond_timedwait, ast_mutex_lock, ast_mutex_unlock, ast_test_status_update, ast_tvnow(), AST_VECTOR_SIZE, error(), update_cond, and update_lock.

Referenced by AST_TEST_DEFINE().

293 {
294  int error;
295  struct timeval wait_now = ast_tvnow();
296  struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 1, .tv_nsec = wait_now.tv_usec * 1000 };
297 
299  while (AST_VECTOR_SIZE(&result_states) != expected_updates) {
300  error = ast_cond_timedwait(&update_cond, &update_lock, &wait_time);
301  if (error == ETIMEDOUT) {
302  ast_test_status_update(test, "Test timed out while waiting for %d expected updates\n", expected_updates);
303  break;
304  }
305  }
307 
308  ast_test_status_update(test, "Received %zu of %d updates\n", AST_VECTOR_SIZE(&result_states), expected_updates);
309  return !(AST_VECTOR_SIZE(&result_states) == expected_updates);
310 }
static ast_mutex_t update_lock
Mutex for update_cond.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
#define ast_mutex_unlock(a)
Definition: lock.h:188
static ast_cond_t update_cond
Condition wait variable for device state updates.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Device State Test" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 969 of file test_devicestate.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 969 of file test_devicestate.c.

◆ chan_callback_called

int chan_callback_called
static

Whether or not the channel device state callback was called.

Definition at line 839 of file test_devicestate.c.

Referenced by AST_TEST_DEFINE(), chan_test_devicestate_cb(), and wait_for_channel_callback().

◆ chan_idx

unsigned int chan_idx
static

Used to assign an increasing integer to channel name.

Definition at line 54 of file test_devicestate.c.

Referenced by AST_TEST_DEFINE().

◆ chan_test_devicestate

struct ast_channel_tech chan_test_devicestate
Initial value:
= {
.description = "Device State Unit Test Channel Driver",
.devicestate = chan_test_devicestate_cb,
}
#define DEVICE_STATE_CHANNEL_TYPE
static int chan_test_devicestate_cb(const char *device_number)

Definition at line 919 of file test_devicestate.c.

◆ channel_cb_cond

ast_cond_t channel_cb_cond
static

Condition wait variable for channel tech device state cb.

Definition at line 235 of file test_devicestate.c.

Referenced by chan_test_devicestate_cb(), and wait_for_channel_callback().

◆ channel_cb_lock

ast_mutex_t channel_cb_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Mutext for channel_cb_cond.

Definition at line 232 of file test_devicestate.c.

Referenced by chan_test_devicestate_cb(), and wait_for_channel_callback().

◆ combined_results

int combined_results[]
static

Definition at line 57 of file test_devicestate.c.

Referenced by AST_TEST_DEFINE().

◆ current_device_state

enum ast_device_state current_device_state
static

The current device state for our device state provider.

Definition at line 241 of file test_devicestate.c.

Referenced by AST_TEST_DEFINE(), and devstate_prov_cb().

◆ exten_results

int exten_results[]
static

Definition at line 141 of file test_devicestate.c.

Referenced by AST_TEST_DEFINE().

◆ update_cond

ast_cond_t update_cond
static

Condition wait variable for device state updates.

Definition at line 229 of file test_devicestate.c.

Referenced by device_state_cb(), and wait_for_device_state_updates().

◆ update_lock

ast_mutex_t update_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Mutex for update_cond.

Definition at line 226 of file test_devicestate.c.

Referenced by clear_result_states(), device_state_cb(), and wait_for_device_state_updates().