Files
libcoap/tests/test_session.c
T
Jon Shallow f026f5701e client+server: Reduce code size by building libcoap for client or server only
Add in new ./configure options --enable-client-mode or
--enable-server-mode which by default are enabled.

If --disable-client-mode is set, then disable all the client specific code.
[ COAP_CLIENT_SUPPORT is not defined ]

If --disable-server-mode is set, then disable all the server specific code.
[ COAP_SERVER_SUPPORT is not defined ]

Functions and variables are only #ifdef'd out in the include/coap3/*_internal.h
files.  They cannot be #ifdef'd out in the other include files as
COAP_CLIENT_SUPPORT and COAP_SERVER_SUPPORT are not available for application
compilations. The result of this is if, say, client only API functons are used
in a server application and COAP_CLIENT_SUPPORT is not defined, there will be
linking issues (missing functions).  Providing stub functions unecessarily
increases the code size.

For coap-server, if it is able to provide proxy support, requires both
COAP_SERVER_SUPPORT and COAP_CLIENT_SUPPORT to set up the ongoing sessions.
So, the build environment deliberatly sets SERVER_CAN_PROXY=0 if
COAP_CLIENT_SUPPORT is not available to allow linking.

Some of the tests have to be disabled if COAP_SERVER_SUPPORT or
COAP_CLIENT_SUPPORT is not set.

Code size change indications

   text    data     bss     sum   filename
 155912    1728   12080  169720   libcoap-3-notls.a
 138300    1728   12080  152108   libcoap-3-notls.a --disable-client-mode
 106734    1632   10304  118670   libcoap-3-notls.a --disable-server-mode

 180485    1733   12080  194298   libcoap-3-openssl.a
 160306    1733   12080  174119   libcoap-3-openssl.a --disable-client-mode
 125543    1637   10304  137484   libcoap-3-openssl.a --disable-server-mode

 181755    1728   12080  195563   libcoap-3-gnutls.a
 160972    1728   12080  174780   libcoap-3-gnutls.a --disable-client-mode
 127178    1632   10304  139114   libcoap-3-gnutls.a --disable-server-mode

 165879    1855   12128  179862   libcoap-3-tinydtls.a
 147022    1855   12128  161005   libcoap-3-tinydtls.a --disable-client-mode
 115618    1759   10352  127729   libcoap-3-tinydtls.a --disable-server-mode

 171690    1728   13744  187162   libcoap-3-mbedtls.a
 152099    1728   13712  167539   libcoap-3-mbedtls.a --disable-client-mode
 118786    1632   11984  132402   libcoap-3-mbedtls.a --disable-server-mode
2021-09-30 16:10:52 +01:00

227 lines
7.2 KiB
C

/* libcoap unit tests
*
* Copyright (C) 2013,2015-2018 Olaf Bergmann <bergmann@tzi.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*
* This file is part of the CoAP library libcoap. Please see
* README for terms of use.
*/
#include "test_common.h"
#include "test_session.h"
#if COAP_CLIENT_SUPPORT
#include <stdio.h>
/* The error threshold for timeout calculations. The precision of
* coap_calc_timeout() is assumed to be sufficient if the resulting
* value deviates at most FP_ERR_THRESHOLD percent from the value that
* was calculated with double precision floating point arithmetic
* instead of fixed point integers.
*/
#define FP_ERR_THRESHOLD (1.0)
/* The maximum number of bits for fixed point integer representation.
* This number must be identical to the definition of MAX_BITS in
* net.c
*/
#define MAX_BITS 8
static coap_context_t *ctx; /* Holds the coap context for most tests */
static coap_session_t *session; /* Holds a reference-counted session object */
COAP_STATIC_INLINE int
fpeq(const coap_fixed_point_t a, const coap_fixed_point_t b) {
return (a.integer_part == b.integer_part) &&
(a.fractional_part == b.fractional_part);
}
static void
t_session1(void) {
CU_ASSERT(session->ref == 1);
coap_session_reference(session);
CU_ASSERT(session->ref == 2);
coap_session_release(session);
CU_ASSERT(session->ref == 1);
}
static void
t_session2(void) {
CU_ASSERT(session->max_retransmit == COAP_DEFAULT_MAX_RETRANSMIT);
CU_ASSERT(fpeq(session->ack_timeout, COAP_DEFAULT_ACK_TIMEOUT));
CU_ASSERT(fpeq(session->ack_random_factor, COAP_DEFAULT_ACK_RANDOM_FACTOR));
CU_ASSERT(coap_session_get_max_retransmit(session) == COAP_DEFAULT_MAX_RETRANSMIT);
CU_ASSERT(fpeq(coap_session_get_ack_timeout(session), COAP_DEFAULT_ACK_TIMEOUT));
CU_ASSERT(fpeq(coap_session_get_ack_random_factor(session), COAP_DEFAULT_ACK_RANDOM_FACTOR));
}
COAP_STATIC_INLINE double
fp_to_double(const coap_fixed_point_t fp) {
return fp.integer_part + fp.fractional_part/1000.0;
}
COAP_STATIC_INLINE double
q_to_double(uint8_t q) {
return (double)(q) / (1 << MAX_BITS);
}
/* Calculates the timeout using the following formula:
*
* COAP_TICKS_PER_SECOND * ack_timeout * (1 + (ack_random_factor - 1) * r)
*
* where @p r is the randomization value represented as Q0.MAX_BITS.
* This function returns the result as unsigned int to be
* checked against the result of coap_calc_timeout().
*/
COAP_STATIC_INLINE unsigned int
timeout(const coap_fixed_point_t ack_timeout,
const coap_fixed_point_t ack_random_factor,
uint8_t r) {
const unsigned int ctps = COAP_TICKS_PER_SECOND;
double ato = fp_to_double(ack_timeout);
double rnd = 1 + (fp_to_double(ack_random_factor) - 1.0) * q_to_double(r);
return (unsigned int)(ctps * ato * rnd);
}
/* Checks if @p v is within FP_ERR_THRESHOLD percent of @p ref. This
* function returns 1 if it is within range, 0 otherwise.
*/
COAP_STATIC_INLINE int
good_enough(unsigned int v, unsigned int ref) {
#define delta(a,b) (((a) < (b)) ? ((b) - (a)) : ((a) - (b)))
return (delta(v,ref) / 100.0) <= FP_ERR_THRESHOLD;
}
static void
t_session3(void) {
const coap_fixed_point_t ato = COAP_DEFAULT_ACK_TIMEOUT;
const coap_fixed_point_t arf = COAP_DEFAULT_ACK_RANDOM_FACTOR;
CU_ASSERT(good_enough(coap_calc_timeout(session, 0), timeout(ato, arf, 0)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 12), timeout(ato, arf, 12)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 55), timeout(ato, arf, 55)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 83), timeout(ato, arf, 83)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 117), timeout(ato, arf, 117)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 210), timeout(ato, arf, 210)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 255), timeout(ato, arf, 255)));
}
static void
t_session4(void) {
const coap_fixed_point_t ato = {8,300};
const coap_fixed_point_t arf = {2,011};
coap_session_set_ack_timeout(session, ato);
coap_session_set_ack_random_factor(session, arf);
CU_ASSERT(fpeq(coap_session_get_ack_timeout(session), ato));
CU_ASSERT(fpeq(coap_session_get_ack_random_factor(session), arf));
CU_ASSERT(good_enough(coap_calc_timeout(session, 0), timeout(ato, arf, 0)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 12), timeout(ato, arf, 12)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 55), timeout(ato, arf, 55)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 83), timeout(ato, arf, 83)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 117), timeout(ato, arf, 117)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 210), timeout(ato, arf, 210)));
CU_ASSERT(good_enough(coap_calc_timeout(session, 255), timeout(ato, arf, 255)));
}
static void
t_session5(void) {
coap_session_release(session);
CU_ASSERT_PTR_NULL(ctx->sessions);
session = NULL;
}
/* Test 6 creates a new session after the original session has been
* released by test 5 */
static void
t_session6(void) {
coap_address_t laddr, saddr;
coap_address_init(&laddr);
coap_address_init(&saddr);
CU_ASSERT_PTR_NULL(session);
laddr.size = sizeof(struct sockaddr_in6);
laddr.addr.sin6.sin6_family = AF_INET6;
laddr.addr.sin6.sin6_addr = in6addr_any;
laddr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT);
coap_address_copy(&saddr, &laddr);
saddr.addr.sin6.sin6_addr = in6addr_loopback;
saddr.addr.sin6.sin6_port = htons(20000);
session = coap_new_client_session(ctx, &saddr, &laddr, COAP_PROTO_UDP);
CU_ASSERT_PTR_NOT_NULL(session);
CU_ASSERT_PTR_NOT_NULL(ctx->sessions);
CU_ASSERT(session->state == COAP_SESSION_STATE_ESTABLISHED);
coap_session_release(session);
}
/* This function creates a set of nodes for testing. These nodes
* will exist for all tests and are modified by coap_insert_node()
* and coap_remove_from_queue().
*/
static int
t_session_tests_create(void) {
coap_address_t addr;
coap_address_init(&addr);
addr.size = sizeof(struct sockaddr_in6);
addr.addr.sin6.sin6_family = AF_INET6;
addr.addr.sin6.sin6_addr = in6addr_any;
addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT);
ctx = coap_new_context(&addr);
if (ctx != NULL) {
addr.addr.sin6.sin6_addr = in6addr_loopback;
session = coap_new_client_session(ctx, NULL, &addr, COAP_PROTO_UDP);
}
return (ctx == NULL) || (session == NULL);
}
static int
t_session_tests_remove(void) {
coap_free_context(ctx);
return 0;
}
CU_pSuite
t_init_session_tests(void) {
CU_pSuite suite;
suite = CU_add_suite("session",
t_session_tests_create, t_session_tests_remove);
if (!suite) { /* signal error */
fprintf(stderr, "W: cannot add session test suite (%s)\n",
CU_get_error_msg());
return NULL;
}
#define SESSION_TEST(s,t) \
if (!CU_ADD_TEST(s,t)) { \
fprintf(stderr, "W: cannot add session test (%s)\n", \
CU_get_error_msg()); \
}
SESSION_TEST(suite, t_session1);
SESSION_TEST(suite, t_session2);
SESSION_TEST(suite, t_session3);
SESSION_TEST(suite, t_session4);
SESSION_TEST(suite, t_session5);
SESSION_TEST(suite, t_session6);
return suite;
}
#endif /* COAP_CLIENT_SUPPORT */