Porting PicoTCP WIP

This commit is contained in:
2025-10-29 14:29:06 +01:00
parent 6722f42e68
commit 815c2239fe
464 changed files with 235009 additions and 24 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,556 @@
#include "pico_addressing.h"
#include "pico_ipv6_nd.h"
#include "pico_stack.h"
#include "pico_frame.h"
#include "pico_ipv6.h"
#include "pico_6lowpan.h"
#include "modules/pico_802154.c"
#include "check.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*******************************************************************************
* MACROS
******************************************************************************/
#define STARTING() \
printf("*********************** STARTING %s ***\n", __func__); \
fflush(stdout)
#define TRYING(s, ...) \
printf("Trying %s: " s, __func__, ##__VA_ARGS__); \
fflush(stdout)
#define CHECKING(i) \
printf("Checking the results of test %2d in %s...", (i)++, \
__func__); \
fflush(stdout)
#define FAIL_UNLESS(cond, s, ...) \
if ((cond)) { \
printf(" SUCCESS\n"); \
} else { \
printf(" FAILED\n"); \
} \
fail_unless((cond), s, ##__VA_ARGS__)
#define FAIL_IF(cond, s, ...) \
if (!(cond)) { \
printf(" SUCCESS\n"); \
} else { \
printf(" FAILED\n"); \
} \
fail_if((cond), s, ##__VA_ARGS__)
#define ENDING(i) \
printf("*********************** ENDING %s *** NUMBER OF TESTS: %d\n",\
__func__, ((i)-1)); \
fflush(stdout)
#define DBG(s, ...) \
printf(s, ##__VA_ARGS__); \
fflush(stdout)
/*******************************************************************************
* HELPER FUNCTIONS
******************************************************************************/
static void dbg_addr_ext(const char *msg, uint8_t a[SIZE_6LOWPAN_EXT])
{
DBG("%s: (64-bit extended address): ", msg);
DBG("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]);
}
/*******************************************************************************
* ADDRESSES
******************************************************************************/
START_TEST(tc_swap)
{
int test = 1;
uint8_t a = 5;
uint8_t b = 1;
STARTING();
// TEST 1
TRYING("With a = %d and b = %d\n", a, b);
pico_swap(&a, &b);
CHECKING(test);
FAIL_IF(1 != a && b != 5, "Failed swapping numbers\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_to_ietf)
{
int test = 1;
struct pico_802154 a = {
.addr.data = { 1,2,3,4,5,6,7,8 },
.mode = AM_6LOWPAN_EXT
};
uint8_t buf[] = {8,7,6,5,4,3,2,1};
STARTING();
// TEST 1
TRYING("Extended address mode\n");
addr_802154_to_ietf(&a);
dbg_addr_ext("After", a.addr.data);
CHECKING(test);
FAIL_UNLESS(0 == memcmp(a.addr.data, buf, SIZE_6LOWPAN_EXT),
"Failed converting to IETF endianness\n");
// TEST 2
TRYING("Short address mode\n");
a.mode = AM_6LOWPAN_SHORT;
addr_802154_to_ietf(&a);
dbg_addr_ext("After", a.addr.data);
CHECKING(test);
FAIL_UNLESS(a.addr._short.addr == short_be(0x0708),
"Failed converting short to IETF endianness\n");
// TEST 3
TRYING("Wrong address mode\n");
a.mode = AM_6LOWPAN_NONE;
addr_802154_to_ietf(&a);
dbg_addr_ext("After", a.addr.data);
buf[0] = 7;
buf[1] = 8;
CHECKING(test);
FAIL_UNLESS(0 == memcmp(a.addr.data, buf, SIZE_6LOWPAN_EXT),
"Should've done nothing\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_ll_src)
{
int test = 1;
struct pico_ip6 ip = {
.addr = {0,0,0,0,0,0,0,0, 3,2,3,4,5,6,7,8}
};
struct pico_ip6 ip2 = {
.addr = {0,0,0,0,0,0,0,0, 0,0,0,0xff,0xfe,0,0x12,0x34}
};
struct pico_6lowpan_info info = {
.addr_short.addr = short_be(0x1234),
.addr_ext.addr = {3,2,3,4,5,6,7,8}
};
struct pico_device dev;
struct pico_802154 addr;
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->buffer;
STARTING();
dev.eth = (struct pico_ethdev *)&info;
f->net_hdr = f->buffer;
f->dev = &dev;
dev.hostvars.lowpan_flags = PICO_6LP_FLAG_LOWPAN;
// TEST 3
TRYING("With an IPv6 address that is derived from MAC short address\n");
info.addr_short.addr = short_be(0x1234);
hdr->src = ip2;
addr = addr_802154_ll_src(f);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_SHORT == addr.mode,
"Should've returned device's short address \n");
CHECKING(test);
FAIL_UNLESS(short_be(0x1234) == addr.addr._short.addr,
"Should've copied the short address from the device\n");
// TEST 4
TRYING("With an IPv6 address that is derived from MAC extended address\n");
ip.addr[8] = 1;
hdr->src = ip;
addr = addr_802154_ll_src(f);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode,
"Should've returned device's extended address\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(info.addr_ext.addr, addr.addr._ext.addr, SIZE_6LOWPAN_EXT),
"Should've copied device's extended address\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_ll_dst)
{
int test = 1;
struct pico_ip6 ip;
struct pico_ip6 local;
struct pico_ip6 local2;
struct pico_802154 addr;
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->buffer;
struct pico_device dev;
uint8_t buf[] = {3,2,3,4,5,6,7,8};
pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", ip.addr);
pico_string_to_ipv6("fe80:0:0:0:0102:0304:0506:0708", local.addr);
pico_string_to_ipv6("fe80:0:0:0:0:0ff:fe00:1234", local2.addr);
STARTING();
f->net_hdr = f->buffer;
f->dev = &dev;
dev.hostvars.lowpan_flags = PICO_6LP_FLAG_LOWPAN;
// TEST 1
TRYING("With a MCAST IPv6 address, should return 0xFFFF\n");
hdr->dst = ip;
addr = addr_802154_ll_dst(f);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_SHORT == addr.mode,
"Should've set address mode to SHORT\n");
CHECKING(test);
FAIL_UNLESS(short_be(ADDR_802154_BCAST) == addr.addr._short.addr,
"Should've set address to BCAST\n");
// TEST 2
TRYING("With a link local IPv6 address derived from an extended L2 address\n");
hdr->dst = local;
addr = addr_802154_ll_dst(f);
dbg_addr_ext("After:", addr.addr._ext.addr);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode,
"Should've set address mode to EXTENDED\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(buf, addr.addr._ext.addr, SIZE_6LOWPAN_EXT),
"Should've copied the extended address from the IP address\n");
// TEST 3
TRYING("With a link local IPv6 address derived from a short L2 address\n");
hdr->dst = local2;
addr = addr_802154_ll_dst(f);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_SHORT == addr.mode,
"Should've set address mode to SHORT\n");
CHECKING(test);
FAIL_UNLESS(short_be(0x1234) == addr.addr._short.addr,
"Should've copied the short address from the IP address\n");
/* TODO: Test getting address from neighbour table */
ENDING(test);
}
END_TEST
/*******************************************************************************
* FRAME
******************************************************************************/
/* Frame (123 bytes) */
static uint8_t pkt[] = {
0x41, 0xcc, 0xa6, 0xff, 0xff, 0x8a, /* A..... */
0x18, 0x00, 0xff, 0xff, 0xda, 0x1c, 0x00, 0x88, /* ........ */
0x18, 0x00, 0xff, 0xff, 0xda, 0x1c, 0x00, 0xc1, /* ........ */
0x09, 0x00, 0x02, 0x42, 0xfa, 0x40, 0x04, 0x01, /* ...B.@.. */
0xf0, 0xb1, 0x01, 0x06, 0x6f, 0xaf, 0x48, 0x65, /* ....o.He */
0x6c, 0x6c, 0x6f, 0x20, 0x30, 0x30, 0x36, 0x20, /* llo 006 */
0x30, 0x78, 0x46, 0x46, 0x33, 0x43, 0x0a, 0x00, /* 0xFF3C.. */
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, /* ........ */
0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, /* ...... ! */
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, /* "#$%&'() */
0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, /* *+,-./01 */
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, /* 23456789 */
0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, /* :;<=>?@A */
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, /* BCDEFGHI */
0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, /* JKLMNOPQ */
0x52, 0x53, 0x54, 0x68, 0x79 /* RSThy */
};
START_TEST(tc_dst_am)
{
int test = 1;
int ret = 0;
STARTING();
// TEST 1
TRYING("Trying to determine AM of destination addr from buffer \n");
ret = dst_am((struct pico_802154_hdr *)pkt);
DBG("ret = %d\n", ret);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == ret,
"Should've returned the AM of an extended address\n");
ENDING(test);
}
END_TEST
START_TEST(tc_src_am)
{
int test = 1;
int ret = 0;
STARTING();
// TEST 1
TRYING("Trying to determine AM of source addr from buffer \n");
ret = src_am((struct pico_802154_hdr *)pkt);
DBG("ret = %d\n", ret);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == ret,
"Should've returned the AM of an extended address\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_hdr_len)
{
int test = 1;
int ret = 0;
STARTING();
// TEST 1
TRYING("Trying to determine length of the header from buffer\n");
ret = frame_802154_hdr_len((struct pico_802154_hdr *)pkt);
DBG("ret = %d\n", ret);
CHECKING(test);
FAIL_UNLESS(21 == ret,
"Should've returned the correct length of the header\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_src)
{
int test = 1;
struct pico_802154_hdr *hdr;
struct pico_802154 addr;
uint8_t src[] = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x88};
STARTING();
hdr = (struct pico_802154_hdr *)pkt;
// TEST 1
TRYING("To receive the source address from a mapped buffer\n");
addr = frame_802154_src(hdr);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode,
"Should've returned an extended address\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(src, addr.addr._ext.addr, SIZE_6LOWPAN_EXT),
"Should've copied the extended source address\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_dst)
{
int test = 1;
struct pico_802154_hdr *hdr;
struct pico_802154 addr;
uint8_t dst[] = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a};
STARTING();
hdr = (struct pico_802154_hdr *)pkt;
// TEST 1
TRYING("To receive the source address from a mapped buffer\n");
addr = frame_802154_dst(hdr);
CHECKING(test);
FAIL_UNLESS(AM_6LOWPAN_EXT == addr.mode,
"Should've returned an extended address\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(dst, addr.addr._ext.addr, SIZE_6LOWPAN_EXT),
"Should've copied the extended source address\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_format)
{
int test = 1;
struct pico_802154 src = {
.addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x88},
.mode = AM_6LOWPAN_EXT
};
struct pico_802154 dst = {
.addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a},
.mode = AM_6LOWPAN_EXT
};
struct pico_6lowpan_short pan = { .addr = short_be(0xffff) };
uint8_t buf[127] = {0};
int i = 0;
STARTING();
// TEST 1
TRYING("To format a frame like sample capture\n");
frame_802154_format(buf, 166, FCF_INTRA_PAN, FCF_NO_ACK_REQ,
FCF_NO_SEC, pan, src, dst);
printf("Buffer:");
for (i = 0; i < 21; i++) {
if (i % 8 != 0)
printf("%02x ", buf[i]);
else {
printf("\n%02x ", buf[i]);
}
}
printf("\n");
CHECKING(test);
FAIL_UNLESS(21 == frame_802154_hdr_len((struct pico_802154_hdr *)buf),
"Failed to correctly set the frame header, the length isn't right\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(pkt, buf, 21),
"Failed to correctly format IEEE802.15.4 frame\n");
ENDING(test);
}
END_TEST
START_TEST(tc_802154_process_out)
{
int i = 0;
int ret = 0;
int test = 1;
struct pico_802154 src = {
.addr.data = {3,2,3,4,5,6,7,8},
.mode = AM_6LOWPAN_EXT
};
struct pico_802154 dst = {
.addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a},
.mode = AM_6LOWPAN_EXT
};
struct pico_frame *f = pico_frame_alloc(0);
struct pico_6lowpan_info info = {
.addr_short.addr = short_be(0x1234),
.addr_ext.addr = {3,2,3,4,5,6,7,8},
.pan_id.addr = short_be(0x1234)
};
struct pico_device dev;
uint8_t buf[] = {0x41,0xcc,0x00,0x34,0x12,0x8a,0x18,0x00,
0xff,0xff,0xda,0x1c,0x00,0x08,0x07,0x06,
0x05,0x04,0x03,0x02,0x03};
dev.eth = (struct pico_ethdev *)&info;
dev.q_out = PICO_ZALLOC(sizeof(struct pico_queue));
f->dev = &dev;
dev.hostvars.lowpan_flags = PICO_6LP_FLAG_LOWPAN;
STARTING();
pico_stack_init();
// TEST 1
TRYING("Trying with bare frame\n");
f->src.pan = src;
f->dst.pan = dst;
ret = pico_802154_process_out(f);
printf("Buffer:");
for (i = 0; i < 21; i++) {
if (i % 8 != 0)
printf("%02x ", f->datalink_hdr[i]);
else {
printf("\n%02x ", f->datalink_hdr[i]);
}
}
printf("\n");
CHECKING(test);
FAIL_UNLESS(0 < ret, "Shouldn't have returned an error\n");
CHECKING(test);
FAIL_UNLESS(0 == memcmp(buf, f->datalink_hdr, 21),
"Frame isn't correctly formatted\n");
pico_frame_discard(f);
ENDING(test);
}
END_TEST
START_TEST(tc_802154_process_in)
{
int ret = 0;
int test = 1;
struct pico_802154 src = {
.addr.data = {3,2,3,4,5,6,7,8},
.mode = AM_6LOWPAN_EXT
};
struct pico_802154 dst = {
.addr.data = {0x00, 0x1C, 0xDA, 0xFF, 0xFF, 0x00, 0x18, 0x8a},
.mode = AM_6LOWPAN_EXT
};
struct pico_frame *f = pico_frame_alloc(22);
uint8_t buf[] = {0x41,0xcc,0x00,0x34,0x12,0x8a,0x18,0x00,
0xff,0xff,0xda,0x1c,0x00,0x08,0x07,0x06,
0x05,0x04,0x03,0x02,0x03,0x60};
memcpy(f->buffer, buf, 22);
f->src.pan = src;
f->dst.pan = dst;
STARTING();
pico_stack_init();
TRYING("Apply processing function on predefined buffer\n");
ret = pico_802154_process_in(f);
CHECKING(test);
FAIL_UNLESS(0 < ret, "Should not return failure\n");
}
END_TEST
static Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_swap = tcase_create("Unit test for pico_swap");
TCase *TCase_802154_to_ietf = tcase_create("Unit test for 802154_to_ietf");
TCase *TCase_802154_ll_src = tcase_create("Unit test for 802154_ll_src");
TCase *TCase_802154_ll_dst = tcase_create("Unit test for 802154_ll_dst");
TCase *TCase_802154_hdr_len = tcase_create("Unit test for 802154_hdr_len");
TCase *TCase_src_am = tcase_create("Unit test for src_am");
TCase *TCase_dst_am = tcase_create("Unit test for dst_am");
TCase *TCase_802154_src = tcase_create("Unit test for 802154_src");
TCase *TCase_802154_dst = tcase_create("Unit test for 802154_dst");
TCase *TCase_802154_format = tcase_create("Unit test for 802154_format");
TCase *TCase_802154_process_out = tcase_create("Unit test for 802154_process_out");
TCase *TCase_802154_process_in = tcase_create("Unit test for 802154_process_in");
/*******************************************************************************
* ADDRESSES
******************************************************************************/
tcase_add_test(TCase_swap, tc_swap);
suite_add_tcase(s, TCase_swap);
tcase_add_test(TCase_802154_to_ietf, tc_802154_to_ietf);
suite_add_tcase(s, TCase_802154_to_ietf);
tcase_add_test(TCase_802154_ll_src, tc_802154_ll_src);
suite_add_tcase(s, TCase_802154_ll_src);
tcase_add_test(TCase_802154_ll_dst, tc_802154_ll_dst);
suite_add_tcase(s, TCase_802154_ll_dst);
/*******************************************************************************
* FRAME
******************************************************************************/
tcase_add_test(TCase_802154_hdr_len, tc_802154_hdr_len);
suite_add_tcase(s, TCase_802154_hdr_len);
tcase_add_test(TCase_src_am, tc_src_am);
suite_add_tcase(s, TCase_src_am);
tcase_add_test(TCase_dst_am, tc_dst_am);
suite_add_tcase(s, TCase_dst_am);
tcase_add_test(TCase_802154_src, tc_802154_src);
suite_add_tcase(s, TCase_802154_src);
tcase_add_test(TCase_802154_dst, tc_802154_dst);
suite_add_tcase(s, TCase_802154_dst);
tcase_add_test(TCase_802154_format, tc_802154_format);
suite_add_tcase(s, TCase_802154_format);
tcase_add_test(TCase_802154_process_out, tc_802154_process_out);
suite_add_tcase(s, TCase_802154_process_out);
tcase_add_test(TCase_802154_process_in, tc_802154_process_in);
suite_add_tcase(s, TCase_802154_process_in);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,545 @@
#include <pico_stack.h>
#include <pico_tree.h>
#include <pico_socket.h>
#include <pico_aodv.h>
#include <pico_device.h>
#include <pico_ipv4.h>
#include "modules/pico_aodv.c"
#include "check.h"
Suite *pico_suite(void);
START_TEST(tc_aodv_node_compare)
{
struct pico_aodv_node a, b;
a.dest.ip4.addr = long_be(1);
b.dest.ip4.addr = long_be(2);
fail_if(aodv_node_compare(&a, &b) >= 0);
a.dest.ip4.addr = long_be(3);
fail_if(aodv_node_compare(&a, &b) <= 0);
b.dest.ip4.addr = long_be(3);
fail_if(aodv_node_compare(&a, &b) != 0);
}
END_TEST
START_TEST(tc_aodv_dev_cmp)
{
struct pico_device a, b;
a.hash = 1;
b.hash = 2;
fail_if(aodv_dev_cmp(&a, &b) >= 0);
a.hash = 3;
fail_if(aodv_dev_cmp(&a, &b) <= 0);
b.hash = 3;
fail_if(aodv_dev_cmp(&a, &b) != 0);
}
END_TEST
START_TEST(tc_get_node_by_addr)
{
struct pico_aodv_node a;
union pico_address test;
a.dest.ip4.addr = long_be(10);
test.ip4.addr = long_be(10);
pico_tree_insert(&aodv_nodes, &a);
fail_if(get_node_by_addr(&test) != &a);
pico_tree_delete(&aodv_nodes, &a);
fail_if(get_node_by_addr(&test) != NULL);
}
END_TEST
static int set_bcast_link_called = 0;
void pico_ipv4_route_set_bcast_link(struct pico_ipv4_link *link)
{
IGNORE_PARAMETER(link);
set_bcast_link_called++;
}
START_TEST(tc_pico_aodv_set_dev)
{
struct pico_device *dev = NULL;
pico_aodv_set_dev(dev);
fail_if(set_bcast_link_called != 1);
}
END_TEST
START_TEST(tc_aodv_peer_refresh)
{
/* TODO: test this: static int aodv_peer_refresh(struct pico_aodv_node *node, uint32_t seq) */
struct pico_aodv_node node;
memset(&node, 0, sizeof(node));
node.dseq = 0xFFFF;
fail_if(aodv_peer_refresh(&node, 10) != 0); /* should succeed, because SYNC flag is not yet set... */
fail_if((node.flags & PICO_AODV_NODE_SYNC) == 0); /* Flag should be set after last call... */
fail_if(aodv_peer_refresh(&node, 5) == 0); /* should FAIL, because seq number is lower... */
fail_if(aodv_peer_refresh(&node, 10) == 0); /* should FAIL, because seq number is still the same... */
fail_if(aodv_peer_refresh(&node, 15) != 0); /* should succeed, because seq number is now bigger... */
fail_if(node.dseq != 15);
}
END_TEST
static int called_route_add = 0;
static uint32_t route_add_gw = 0u;
static int route_add_metric = 0;
int pico_ipv4_route_add(struct pico_ip4 address, struct pico_ip4 netmask, struct pico_ip4 gateway, int metric, struct pico_ipv4_link *link)
{
IGNORE_PARAMETER(link);
IGNORE_PARAMETER(netmask);
IGNORE_PARAMETER(address);
called_route_add++;
route_add_gw = gateway.addr;
route_add_metric = metric;
return 0;
}
START_TEST(tc_aodv_elect_route)
{
struct pico_aodv_node node;
union pico_address gateway;
memset(&node, 0, sizeof(node));
gateway.ip4.addr = 0x55555555;
called_route_add = 0;
aodv_elect_route(&node, NULL, 150, NULL);
fail_if(called_route_add != 1); /* Not active, should succeed */
fail_if(route_add_gw != 0u);
fail_if(route_add_metric != 1);
called_route_add = 0;
route_add_metric = 0;
route_add_gw = 0u;
node.flags = PICO_AODV_NODE_ROUTE_DOWN | PICO_AODV_NODE_ROUTE_UP;
aodv_elect_route(&node, &gateway, 150, NULL);
fail_if(called_route_add != 0); /* Already active, existing metric is lower */
called_route_add = 0;
route_add_metric = 0;
route_add_gw = 0u;
node.metric = 22;
aodv_elect_route(&node, &gateway, 15, NULL);
fail_if(called_route_add != 1); /* Already active, existing metric is higher */
fail_if(route_add_metric != 16);
fail_if(route_add_gw != 0x55555555);
}
END_TEST
START_TEST(tc_aodv_peer_new)
{
union pico_address addr;
struct pico_aodv_node *new;
addr.ip4.addr = 0x44444444;
new = aodv_peer_new(&addr);
fail_if(!new);
fail_if(!get_node_by_addr(&addr));
pico_set_mm_failure(1);
new = aodv_peer_new(&addr);
fail_if(new);
}
END_TEST
START_TEST(tc_aodv_peer_eval)
{
union pico_address addr;
struct pico_aodv_node *node = NULL;
/* Case 0: Creation */
addr.ip4.addr = 0x11224433;
node = aodv_peer_eval(&addr, 0, 0);
fail_if(!node);
fail_if((node->flags & PICO_AODV_NODE_SYNC) != 0); /* Not synced! */
/* Case 1: retrieve, unsynced */
node->metric = 42;
node = aodv_peer_eval(&addr, 0, 0); /* Should get existing node! */
fail_if(!node);
fail_if(node->metric != 42);
fail_if((node->flags & PICO_AODV_NODE_SYNC) != 0); /* Not synced! */
/* Case 2: new node, invalid allocation */
addr.ip4.addr = 0x11224455;
pico_set_mm_failure(1);
node = aodv_peer_eval(&addr, long_be(10), 1);
fail_if(node);
/* Case 3: existing node, setting the new sequence */
addr.ip4.addr = 0x11224433;
node = aodv_peer_eval(&addr, long_be(10), 1); /* Should get existing node! */
fail_if(node->metric != 42);
fail_if((node->flags & PICO_AODV_NODE_SYNC) == 0);
fail_if(node->dseq != 10);
}
END_TEST
START_TEST(tc_aodv_lifetime)
{
struct pico_aodv_node node;
pico_time now = PICO_TIME_MS();
memset(&node, 0, sizeof(node));
fail_if(aodv_lifetime(&node) == 0);
fail_if(node.last_seen < now);
node.last_seen = now - AODV_ACTIVE_ROUTE_TIMEOUT;
fail_if(aodv_lifetime(&node) != 0);
}
END_TEST
static uint8_t sent_pkt_type = 0xFF;
static uint32_t dest_addr = 0;
static int pico_socket_sendto_called = 0;
static int pico_socket_sendto_extended_called = 0;
uint32_t expected_dseq = 0;
int pico_socket_sendto(struct pico_socket *s, const void *buf, const int len, void *dst, uint16_t remote_port)
{
uint8_t *pkt = (uint8_t *)(uintptr_t)buf;
printf("Sendto called!\n");
pico_socket_sendto_called++;
fail_if(remote_port != short_be(PICO_AODV_PORT));
fail_if (s != aodv_socket);
fail_if(pkt[0] > 4);
fail_if(pkt[0] < 1);
sent_pkt_type = pkt[0];
dest_addr = ((union pico_address *)dst)->ip4.addr;
if (sent_pkt_type == AODV_TYPE_RREQ) {
/* struct pico_aodv_rreq *req = (struct pico_aodv_rreq *)(uintptr_t)buf; */
fail_if(len != sizeof(struct pico_aodv_rreq));
}
else if (sent_pkt_type == AODV_TYPE_RREP) {
struct pico_aodv_rrep *rep = (struct pico_aodv_rrep *)(uintptr_t)buf;
fail_if(len != sizeof(struct pico_aodv_rrep));
fail_if(rep->dest != 0x11111111);
fail_if(rep->orig != 0x22222222);
printf("rep->dseq= %08x, exp: %08x\n", rep->dseq, expected_dseq);
fail_if(rep->dseq != expected_dseq);
}
return len;
}
int pico_socket_sendto_extended(struct pico_socket *s, const void *buf, const int len,
void *dst, uint16_t remote_port, struct pico_msginfo *msginfo)
{
IGNORE_PARAMETER(msginfo);
pico_socket_sendto_extended_called++;
return pico_socket_sendto(s, buf, len, dst, remote_port);
}
START_TEST(tc_aodv_send_reply)
{
struct pico_aodv_node node;
struct pico_aodv_rreq req;
struct pico_msginfo info;
union pico_address addr;
addr.ip4.addr = 0x22222222;
memset(&node, 0, sizeof(node));
memset(&req, 0, sizeof(req));
memset(&info, 0, sizeof(info));
req.dest = 0x11111111;
req.orig = addr.ip4.addr;
req.dseq = 99;
aodv_send_reply(&node, &req, 1, &info);
fail_if(pico_socket_sendto_called != 0); /* Call should have no effect, due to non-existing origin node */
/* Creating origin... */
fail_if(aodv_peer_new(&addr) == NULL);
aodv_send_reply(&node, &req, 0, &info);
fail_if(pico_socket_sendto_called != 0); /* Call should have no effect, node non-local, non sync'd */
expected_dseq = long_be(pico_aodv_local_id + 1);
aodv_send_reply(&node, &req, 1, &info);
fail_if(pico_socket_sendto_called != 1); /* Call should succeed */
pico_socket_sendto_called = 0;
node.flags = PICO_AODV_NODE_SYNC;
node.dseq = 42;
expected_dseq = long_be(42);
aodv_send_reply(&node, &req, 0, &info);
fail_if(pico_socket_sendto_called != 1); /* Call should succeed */
pico_socket_sendto_called = 0;
}
END_TEST
static struct pico_ipv4_link global_link;
struct pico_ipv4_link *pico_ipv4_link_by_dev(struct pico_device *dev)
{
IGNORE_PARAMETER(dev);
if (!global_link.address.addr)
return NULL;
printf("Setting link!\n");
return &global_link;
}
static struct pico_device global_dev;
static int link_find_success = 0;
struct pico_device *pico_ipv4_link_find(struct pico_ip4 *ip4)
{
IGNORE_PARAMETER(ip4);
if (link_find_success)
return &global_dev;
return NULL;
}
static int timer_set = 0;
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
IGNORE_PARAMETER(arg);
IGNORE_PARAMETER(timer);
IGNORE_PARAMETER(expire);
printf("Timer set!\n");
timer_set++;
return (uint32_t ) 0x99999999;
}
START_TEST(tc_aodv_send_req)
{
struct pico_aodv_node node;
struct pico_device d;
aodv_socket = NULL;
memset(&node, 0, sizeof(node));
node.flags = PICO_AODV_NODE_ROUTE_DOWN | PICO_AODV_NODE_ROUTE_UP;
fail_if(aodv_send_req(&node) != 0); /* Should fail: node already active */
fail_if(pico_socket_sendto_called != 0);
fail_if(pico_socket_sendto_extended_called != 0);
node.flags = 0;
fail_if(aodv_send_req(&node) != 0); /* Should fail: no devices in tree */
fail_if(pico_socket_sendto_called != 0);
fail_if(pico_socket_sendto_extended_called != 0);
pico_tree_insert(&aodv_devices, &d);
fail_if(aodv_send_req(&node) != -1); /* Should fail: aodv_socket == NULL */
fail_if(pico_err != PICO_ERR_EINVAL);
fail_if(pico_socket_sendto_called != 0);
fail_if(pico_socket_sendto_extended_called != 0);
/* No valid link, timer is set, call does not send packets */
aodv_socket = (struct pico_socket*) 1;
global_link.address.addr = 0;
fail_if(aodv_send_req(&node) != 0);
fail_if(pico_socket_sendto_called != 0);
fail_if(pico_socket_sendto_extended_called != 0);
fail_if(timer_set != 1);
timer_set = 0;
/* One valid link, timer is set, one packet is sent */
global_link.address.addr = 0xFEFEFEFE;
fail_if(aodv_send_req(&node) != 1);
fail_if(pico_socket_sendto_called != 1);
fail_if(pico_socket_sendto_extended_called != 1);
fail_if(timer_set != 1);
pico_socket_sendto_called = 0;
pico_socket_sendto_extended_called = 0;
timer_set = 0;
}
END_TEST
START_TEST(tc_aodv_reverse_path_discover)
{
struct pico_aodv_node node;
memset(&node, 0, sizeof(node));
aodv_reverse_path_discover(0, &node);
}
END_TEST
START_TEST(tc_aodv_recv_valid_rreq)
{
struct pico_aodv_node node;
struct pico_aodv_rreq req;
struct pico_msginfo info;
union pico_address addr;
memset(&node, 0, sizeof(node));
memset(&req, 0, sizeof(req));
memset(&info, 0, sizeof(info));
addr.ip4.addr = 0x22222222;
link_find_success = 0;
aodv_recv_valid_rreq(&node, &req, &info);
fail_if(pico_socket_sendto_called > 0);
/* link not local, but active node, set to send reply, no timer */
link_find_success = 0;
fail_if(aodv_peer_new(&addr) == NULL);
global_link.address.addr = 0x44444444;
req.orig = addr.ip4.addr;
req.dest = 0x11111111;
node.flags = PICO_AODV_NODE_SYNC | PICO_AODV_NODE_ROUTE_UP | PICO_AODV_NODE_ROUTE_DOWN;
node.dseq = 42;
expected_dseq = long_be(42);
aodv_recv_valid_rreq(&node, &req, &info);
fail_if(pico_socket_sendto_called < 1);
fail_if(timer_set > 0);
pico_socket_sendto_called = 0;
/* link local, active node. Full send + set timer. */
link_find_success = 1;
expected_dseq = long_be(pico_aodv_local_id + 1);
aodv_peer_new(&addr);
aodv_recv_valid_rreq(&node, &req, &info);
fail_if(pico_socket_sendto_called < 1);
fail_if(timer_set < 1);
}
END_TEST
START_TEST(tc_aodv_parse_rreq)
{
/* TODO: test this: static void aodv_parse_rreq(union pico_address *from, uint8_t *buf, int len, struct pico_msginfo *msginfo) */
}
END_TEST
START_TEST(tc_aodv_parse_rrep)
{
/* TODO: test this: static void aodv_parse_rrep(union pico_address *from, uint8_t *buf, int len, struct pico_msginfo *msginfo) */
}
END_TEST
START_TEST(tc_aodv_parse_rerr)
{
/* TODO: test this: static void aodv_parse_rerr(union pico_address *from, uint8_t *buf, int len, struct pico_msginfo *msginfo) */
}
END_TEST
START_TEST(tc_aodv_parse_rack)
{
aodv_parse_rack(NULL, NULL, 0, NULL);
}
END_TEST
START_TEST(tc_pico_aodv_parse)
{
}
END_TEST
START_TEST(tc_pico_aodv_socket_callback)
{
/* TODO: test this: static void pico_aodv_socket_callback(uint16_t ev, struct pico_socket *s) */
}
END_TEST
START_TEST(tc_aodv_make_rreq)
{
/* TODO: test this: static void aodv_make_rreq(struct pico_aodv_node *node, struct pico_aodv_rreq *req) */
}
END_TEST
START_TEST(tc_aodv_retrans_rreq)
{
/* TODO: test this: static void aodv_retrans_rreq(pico_time now, void *arg) */
}
END_TEST
START_TEST(tc_pico_aodv_expired)
{
/* TODO: test this: static void pico_aodv_expired(struct pico_aodv_node *node) */
}
END_TEST
START_TEST(tc_pico_aodv_collector)
{
/* TODO: test this: static void pico_aodv_collector(pico_time now, void *arg) */
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_aodv_node_compare = tcase_create("Unit test for aodv_node_compare");
TCase *TCase_aodv_dev_cmp = tcase_create("Unit test for aodv_dev_cmp");
TCase *TCase_get_node_by_addr = tcase_create("Unit test for get_node_by_addr");
TCase *TCase_pico_aodv_set_dev = tcase_create("Unit test for pico_aodv_set_dev");
TCase *TCase_aodv_peer_refresh = tcase_create("Unit test for aodv_peer_refresh");
TCase *TCase_aodv_elect_route = tcase_create("Unit test for aodv_elect_route");
TCase *TCase_aodv_peer_new = tcase_create("Unit test for aodv_peer_new");
TCase *TCase_aodv_peer_eval = tcase_create("Unit test for aodv_peer_eval");
TCase *TCase_aodv_lifetime = tcase_create("Unit test for aodv_lifetime");
TCase *TCase_aodv_send_reply = tcase_create("Unit test for aodv_send_reply");
TCase *TCase_aodv_send_req = tcase_create("Unit test for aodv_send_req");
TCase *TCase_aodv_reverse_path_discover = tcase_create("Unit test for aodv_reverse_path_discover");
TCase *TCase_aodv_recv_valid_rreq = tcase_create("Unit test for aodv_recv_valid_rreq");
TCase *TCase_aodv_parse_rreq = tcase_create("Unit test for aodv_parse_rreq");
TCase *TCase_aodv_parse_rrep = tcase_create("Unit test for aodv_parse_rrep");
TCase *TCase_aodv_parse_rerr = tcase_create("Unit test for aodv_parse_rerr");
TCase *TCase_aodv_parse_rack = tcase_create("Unit test for aodv_parse_rack");
TCase *TCase_pico_aodv_parse = tcase_create("Unit test for pico_aodv_parse");
TCase *TCase_pico_aodv_socket_callback = tcase_create("Unit test for pico_aodv_socket_callback");
TCase *TCase_aodv_make_rreq = tcase_create("Unit test for aodv_make_rreq");
TCase *TCase_aodv_retrans_rreq = tcase_create("Unit test for aodv_retrans_rreq");
TCase *TCase_pico_aodv_expired = tcase_create("Unit test for pico_aodv_expired");
TCase *TCase_pico_aodv_collector = tcase_create("Unit test for pico_aodv_collector");
tcase_add_test(TCase_aodv_node_compare, tc_aodv_node_compare);
suite_add_tcase(s, TCase_aodv_node_compare);
tcase_add_test(TCase_aodv_dev_cmp, tc_aodv_dev_cmp);
suite_add_tcase(s, TCase_aodv_dev_cmp);
tcase_add_test(TCase_get_node_by_addr, tc_get_node_by_addr);
suite_add_tcase(s, TCase_get_node_by_addr);
tcase_add_test(TCase_pico_aodv_set_dev, tc_pico_aodv_set_dev);
suite_add_tcase(s, TCase_pico_aodv_set_dev);
tcase_add_test(TCase_aodv_peer_refresh, tc_aodv_peer_refresh);
suite_add_tcase(s, TCase_aodv_peer_refresh);
tcase_add_test(TCase_aodv_elect_route, tc_aodv_elect_route);
suite_add_tcase(s, TCase_aodv_elect_route);
tcase_add_test(TCase_aodv_peer_new, tc_aodv_peer_new);
suite_add_tcase(s, TCase_aodv_peer_new);
tcase_add_test(TCase_aodv_peer_eval, tc_aodv_peer_eval);
suite_add_tcase(s, TCase_aodv_peer_eval);
tcase_add_test(TCase_aodv_lifetime, tc_aodv_lifetime);
suite_add_tcase(s, TCase_aodv_lifetime);
tcase_add_test(TCase_aodv_send_reply, tc_aodv_send_reply);
suite_add_tcase(s, TCase_aodv_send_reply);
tcase_add_test(TCase_aodv_send_req, tc_aodv_send_req);
suite_add_tcase(s, TCase_aodv_send_req);
tcase_add_test(TCase_aodv_reverse_path_discover, tc_aodv_reverse_path_discover);
suite_add_tcase(s, TCase_aodv_reverse_path_discover);
tcase_add_test(TCase_aodv_recv_valid_rreq, tc_aodv_recv_valid_rreq);
suite_add_tcase(s, TCase_aodv_recv_valid_rreq);
tcase_add_test(TCase_aodv_parse_rreq, tc_aodv_parse_rreq);
suite_add_tcase(s, TCase_aodv_parse_rreq);
tcase_add_test(TCase_aodv_parse_rrep, tc_aodv_parse_rrep);
suite_add_tcase(s, TCase_aodv_parse_rrep);
tcase_add_test(TCase_aodv_parse_rerr, tc_aodv_parse_rerr);
suite_add_tcase(s, TCase_aodv_parse_rerr);
tcase_add_test(TCase_aodv_parse_rack, tc_aodv_parse_rack);
suite_add_tcase(s, TCase_aodv_parse_rack);
tcase_add_test(TCase_pico_aodv_parse, tc_pico_aodv_parse);
suite_add_tcase(s, TCase_pico_aodv_parse);
tcase_add_test(TCase_pico_aodv_socket_callback, tc_pico_aodv_socket_callback);
suite_add_tcase(s, TCase_pico_aodv_socket_callback);
tcase_add_test(TCase_aodv_make_rreq, tc_aodv_make_rreq);
suite_add_tcase(s, TCase_aodv_make_rreq);
tcase_add_test(TCase_aodv_retrans_rreq, tc_aodv_retrans_rreq);
suite_add_tcase(s, TCase_aodv_retrans_rreq);
tcase_add_test(TCase_pico_aodv_expired, tc_pico_aodv_expired);
suite_add_tcase(s, TCase_pico_aodv_expired);
tcase_add_test(TCase_pico_aodv_collector, tc_pico_aodv_collector);
suite_add_tcase(s, TCase_pico_aodv_collector);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,97 @@
#include "modules/pico_dev_loop.c"
#include "check.h"
static int called = 0;
static int fail = 0;
Suite *pico_suite(void);
int pico_device_init(struct pico_device __attribute__((unused)) *dev, const char __attribute__((unused)) *name, const uint8_t __attribute__((unused)) *mac)
{
if (fail)
return -1;
return 0;
}
void pico_device_destroy(struct pico_device *dev)
{
dev = dev;
}
int32_t pico_stack_recv(struct pico_device __attribute__((unused)) *dev, uint8_t __attribute__((unused)) *buffer, uint32_t __attribute__((unused)) len)
{
called = 1;
return 1;
}
START_TEST(tc_pico_loop_send)
{
uint8_t buf[LOOP_MTU + 1] = {};
fail_if(pico_loop_send(NULL, buf, LOOP_MTU + 1) != 0);
/* First send: OK */
fail_if(pico_loop_send(NULL, buf, LOOP_MTU) != LOOP_MTU);
/* Second: buffer busy */
fail_if(pico_loop_send(NULL, buf, LOOP_MTU) != 0);
}
END_TEST
START_TEST(tc_pico_loop_poll)
{
uint8_t buf[LOOP_MTU + 1] = {};
fail_if(pico_loop_poll(NULL, 0) != 0);
called = 0;
/* First send: OK */
fail_if(pico_loop_send(NULL, buf, LOOP_MTU) != LOOP_MTU);
fail_if(pico_loop_poll(NULL, 1) != 0);
fail_if(called == 0);
}
END_TEST
START_TEST(tc_pico_loop_create)
{
#ifdef PICO_FAULTY
printf("Testing with faulty memory in pico_loop_create (1)\n");
pico_set_mm_failure(1);
fail_if(pico_loop_create() != NULL);
#endif
fail = 1;
fail_if(pico_loop_create() != NULL);
fail = 0;
fail_if(pico_loop_create() == NULL);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_loop_send = tcase_create("Unit test for pico_loop_send");
TCase *TCase_pico_loop_poll = tcase_create("Unit test for pico_loop_poll");
TCase *TCase_pico_loop_create = tcase_create("Unit test for pico_loop_create");
tcase_add_test(TCase_pico_loop_send, tc_pico_loop_send);
suite_add_tcase(s, TCase_pico_loop_send);
tcase_add_test(TCase_pico_loop_poll, tc_pico_loop_poll);
suite_add_tcase(s, TCase_pico_loop_poll);
tcase_add_test(TCase_pico_loop_create, tc_pico_loop_create);
suite_add_tcase(s, TCase_pico_loop_create);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,229 @@
#include "pico_config.h"
#include "pico_stack.h"
#include "pico_addressing.h"
#include "pico_socket.h"
#include "pico_ipv4.h"
#include "pico_ipv6.h"
#include "pico_dns_client.h"
#include "pico_tree.h"
#include "pico_udp.h"
#include "modules/pico_dns_client.c"
#include "check.h"
Suite *pico_suite(void);
START_TEST(tc_pico_dns_client_callback)
{
struct pico_socket *s = pico_udp_open();
s->proto = &pico_proto_udp;
fail_if(!s);
/* Test with ERR */
pico_dns_client_callback(PICO_SOCK_EV_ERR, s);
/* Test with failing RD */
pico_dns_client_callback(PICO_SOCK_EV_RD, s);
}
END_TEST
START_TEST(tc_pico_dns_client_retransmission)
{
/* TODO: test this: static void pico_dns_client_retransmission(pico_time now, void *arg); */
}
END_TEST
START_TEST(tc_dns_ns_cmp)
{
/* TODO: test this: static int dns_ns_cmp(void *ka, void *kb) */
}
END_TEST
START_TEST(tc_dns_query_cmp)
{
/* TODO: test this: static int dns_query_cmp(void *ka, void *kb) */
}
END_TEST
START_TEST(tc_pico_dns_client_del_ns)
{
/* TODO: test this: static int pico_dns_client_del_ns(struct pico_ip4 *ns_addr) */
}
END_TEST
START_TEST(tc_pico_dns_ns)
{
/* TODO: test this: static struct pico_dns_ns *pico_dns_client_add_ns(struct pico_ip4 *ns_addr) */
}
END_TEST
START_TEST(tc_pico_dns_client_del_query)
{
/* TODO: test this: static int pico_dns_client_del_query(uint16_t id) */
}
END_TEST
START_TEST(tc_pico_dns_query)
{
/* TODO: test this: static struct pico_dns_query *pico_dns_client_find_query(uint16_t id) */
}
END_TEST
START_TEST(tc_pico_dns_client_strlen)
{
/* TODO: test this: static uint16_t pico_dns_client_strlen(const char *url) */
}
END_TEST
START_TEST(tc_pico_dns_client_seek)
{
/* TODO: test this: static char *pico_dns_client_seek(char *ptr) */
}
END_TEST
START_TEST(tc_pico_dns_client_mirror)
{
/* TODO: test this: static int8_t pico_dns_client_mirror(char *ptr) */
}
END_TEST
START_TEST(tc_pico_dns_client_query_prefix)
{
/* TODO: test this: static int pico_dns_client_query_prefix(struct pico_dns_prefix *pre) */
}
END_TEST
START_TEST(tc_pico_dns_client_query_suffix)
{
/* TODO: test this: static int pico_dns_client_query_suffix(struct pico_dns_query_suffix *suf, uint16_t type, uint16_t class) */
}
END_TEST
START_TEST(tc_pico_dns_client_query_domain)
{
/* TODO: test this: static int pico_dns_client_query_domain(char *ptr) */
}
END_TEST
START_TEST(tc_pico_dns_client_answer_domain)
{
/* TODO: test this: static int pico_dns_client_answer_domain(char *ptr) */
}
END_TEST
START_TEST(tc_pico_dns_client_check_prefix)
{
/* TODO: test this: static int pico_dns_client_check_prefix(struct pico_dns_prefix *pre) */
}
END_TEST
START_TEST(tc_pico_dns_client_check_qsuffix)
{
/* TODO: test this: static int pico_dns_client_check_qsuffix(struct pico_dns_query_suffix *suf, struct pico_dns_query *q) */
}
END_TEST
START_TEST(tc_pico_dns_client_check_asuffix)
{
/* TODO: test this: static int pico_dns_client_check_asuffix(struct pico_dns_answer_suffix *suf, struct pico_dns_query *q) */
}
END_TEST
START_TEST(tc_pico_dns_client_seek_suffix)
{
/* TODO: test this: static char *pico_dns_client_seek_suffix(char *suf, struct pico_dns_prefix *pre, struct pico_dns_query *q) */
}
END_TEST
START_TEST(tc_pico_dns_client_send)
{
/* TODO: test this: static int pico_dns_client_send(struct pico_dns_query *q) */
}
END_TEST
START_TEST(tc_pico_dns_client_user_callback)
{
/* TODO: test this: static int pico_dns_client_user_callback(struct pico_dns_answer_suffix *asuffix, struct pico_dns_query *q) */
}
END_TEST
START_TEST(tc_pico_dns_client_getaddr_init)
{
/* TODO: test this: static int pico_dns_client_getaddr_init(const char *url, uint16_t proto, void (*callback)(char *, void *), void *arg) */
}
END_TEST
START_TEST(tc_pico_dns_ipv6_set_ptr)
{
/* TODO: test this: static void pico_dns_ipv6_set_ptr(const char *ip, char *dst) */
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_dns_client_callback = tcase_create("Unit test for pico_dns_client_callback");
TCase *TCase_pico_dns_client_retransmission = tcase_create("Unit test for pico_dns_client_retransmission");
TCase *TCase_dns_ns_cmp = tcase_create("Unit test for dns_ns_cmp");
TCase *TCase_dns_query_cmp = tcase_create("Unit test for dns_query_cmp");
TCase *TCase_pico_dns_client_del_ns = tcase_create("Unit test for pico_dns_client_del_ns");
TCase *TCase_pico_dns_ns = tcase_create("Unit test for pico_dns_ns");
TCase *TCase_pico_dns_client_del_query = tcase_create("Unit test for pico_dns_client_del_query");
TCase *TCase_pico_dns_query = tcase_create("Unit test for pico_dns_query");
TCase *TCase_pico_dns_client_strlen = tcase_create("Unit test for pico_dns_client_strlen");
TCase *TCase_pico_dns_client_seek = tcase_create("Unit test for pico_dns_client_seek");
TCase *TCase_pico_dns_client_mirror = tcase_create("Unit test for pico_dns_client_mirror");
TCase *TCase_pico_dns_client_query_prefix = tcase_create("Unit test for pico_dns_client_query_prefix");
TCase *TCase_pico_dns_client_query_suffix = tcase_create("Unit test for pico_dns_client_query_suffix");
TCase *TCase_pico_dns_client_query_domain = tcase_create("Unit test for pico_dns_client_query_domain");
TCase *TCase_pico_dns_client_answer_domain = tcase_create("Unit test for pico_dns_client_answer_domain");
TCase *TCase_pico_dns_client_check_prefix = tcase_create("Unit test for pico_dns_client_check_prefix");
TCase *TCase_pico_dns_client_check_qsuffix = tcase_create("Unit test for pico_dns_client_check_qsuffix");
TCase *TCase_pico_dns_client_check_asuffix = tcase_create("Unit test for pico_dns_client_check_asuffix");
TCase *TCase_pico_dns_client_seek_suffix = tcase_create("Unit test for pico_dns_client_seek_suffix");
TCase *TCase_pico_dns_client_send = tcase_create("Unit test for pico_dns_client_send");
TCase *TCase_pico_dns_client_user_callback = tcase_create("Unit test for pico_dns_client_user_callback");
TCase *TCase_pico_dns_client_getaddr_init = tcase_create("Unit test for pico_dns_client_getaddr_init");
TCase *TCase_pico_dns_ipv6_set_ptr = tcase_create("Unit test for pico_dns_ipv6_set_ptr");
tcase_add_test(TCase_pico_dns_client_callback, tc_pico_dns_client_callback);
suite_add_tcase(s, TCase_pico_dns_client_callback);
tcase_add_test(TCase_pico_dns_client_retransmission, tc_pico_dns_client_retransmission);
suite_add_tcase(s, TCase_pico_dns_client_retransmission);
tcase_add_test(TCase_dns_ns_cmp, tc_dns_ns_cmp);
suite_add_tcase(s, TCase_dns_ns_cmp);
tcase_add_test(TCase_dns_query_cmp, tc_dns_query_cmp);
suite_add_tcase(s, TCase_dns_query_cmp);
tcase_add_test(TCase_pico_dns_client_del_ns, tc_pico_dns_client_del_ns);
suite_add_tcase(s, TCase_pico_dns_client_del_ns);
tcase_add_test(TCase_pico_dns_ns, tc_pico_dns_ns);
suite_add_tcase(s, TCase_pico_dns_ns);
tcase_add_test(TCase_pico_dns_client_del_query, tc_pico_dns_client_del_query);
suite_add_tcase(s, TCase_pico_dns_client_del_query);
tcase_add_test(TCase_pico_dns_query, tc_pico_dns_query);
suite_add_tcase(s, TCase_pico_dns_query);
tcase_add_test(TCase_pico_dns_client_strlen, tc_pico_dns_client_strlen);
suite_add_tcase(s, TCase_pico_dns_client_strlen);
tcase_add_test(TCase_pico_dns_client_seek, tc_pico_dns_client_seek);
suite_add_tcase(s, TCase_pico_dns_client_seek);
tcase_add_test(TCase_pico_dns_client_mirror, tc_pico_dns_client_mirror);
suite_add_tcase(s, TCase_pico_dns_client_mirror);
tcase_add_test(TCase_pico_dns_client_query_prefix, tc_pico_dns_client_query_prefix);
suite_add_tcase(s, TCase_pico_dns_client_query_prefix);
tcase_add_test(TCase_pico_dns_client_query_suffix, tc_pico_dns_client_query_suffix);
suite_add_tcase(s, TCase_pico_dns_client_query_suffix);
tcase_add_test(TCase_pico_dns_client_query_domain, tc_pico_dns_client_query_domain);
suite_add_tcase(s, TCase_pico_dns_client_query_domain);
tcase_add_test(TCase_pico_dns_client_answer_domain, tc_pico_dns_client_answer_domain);
suite_add_tcase(s, TCase_pico_dns_client_answer_domain);
tcase_add_test(TCase_pico_dns_client_check_prefix, tc_pico_dns_client_check_prefix);
suite_add_tcase(s, TCase_pico_dns_client_check_prefix);
tcase_add_test(TCase_pico_dns_client_check_qsuffix, tc_pico_dns_client_check_qsuffix);
suite_add_tcase(s, TCase_pico_dns_client_check_qsuffix);
tcase_add_test(TCase_pico_dns_client_check_asuffix, tc_pico_dns_client_check_asuffix);
suite_add_tcase(s, TCase_pico_dns_client_check_asuffix);
tcase_add_test(TCase_pico_dns_client_seek_suffix, tc_pico_dns_client_seek_suffix);
suite_add_tcase(s, TCase_pico_dns_client_seek_suffix);
tcase_add_test(TCase_pico_dns_client_send, tc_pico_dns_client_send);
suite_add_tcase(s, TCase_pico_dns_client_send);
tcase_add_test(TCase_pico_dns_client_user_callback, tc_pico_dns_client_user_callback);
suite_add_tcase(s, TCase_pico_dns_client_user_callback);
tcase_add_test(TCase_pico_dns_client_getaddr_init, tc_pico_dns_client_getaddr_init);
suite_add_tcase(s, TCase_pico_dns_client_getaddr_init);
tcase_add_test(TCase_pico_dns_ipv6_set_ptr, tc_pico_dns_ipv6_set_ptr);
suite_add_tcase(s, TCase_pico_dns_ipv6_set_ptr);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,403 @@
#include "pico_config.h"
#include "pico_stack.h"
#include "pico_addressing.h"
#include "pico_socket.h"
#include "pico_ipv4.h"
#include "pico_ipv6.h"
#include "pico_dns_common.h"
#include "pico_tree.h"
#include "pico_dev_mock.c"
#include "modules/pico_dns_sd.c"
#include "check.h"
Suite *pico_suite(void);
void callback( pico_mdns_rtree *tree, char *str, void *arg);
int dns_sd_init(void);
char text[] = "textvers";
char text2[] = "pass";
char text3[] = "color";
char value[] = "1";
char value3[] = "";
void callback( pico_mdns_rtree *tree,
char *str,
void *arg )
{
kv_vector vector = {
0
};
/* This doesn't even gets called, tests exit before possible callback */
IGNORE_PARAMETER(str);
IGNORE_PARAMETER(arg);
IGNORE_PARAMETER(tree);
fail_unless(pico_dns_sd_register_service("Hello World!",
"_kerberos._udp",
88, &vector, 120,
callback, NULL) == 0,
"dns_sd_register_service failed!\n");
}
int dns_sd_init()
{
struct mock_device *mock = NULL;
struct pico_ip4 local = {
.addr = long_be(0x0a280064)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
mock = pico_mock_create(NULL);
if (!mock)
return -1;
pico_ipv4_link_add(mock->dev, local, netmask);
/* Try to initialise the mDNS module right */
return pico_dns_sd_init("host.local", local, callback, NULL);
}
START_TEST(tc_dns_sd_kv_vector_strlen)
{
kv_vector pairs = {
0
};
pico_dns_sd_kv_vector_add(&pairs, text, value);
pico_dns_sd_kv_vector_add(&pairs, text2, NULL);
pico_dns_sd_kv_vector_add(&pairs, text3, value3);
fail_unless(pico_dns_sd_kv_vector_strlen(&pairs) == 23,
"dns_sd_kv_vector_strlen returned wrong length!\n");
pico_dns_sd_kv_vector_erase(&pairs);
}
END_TEST
START_TEST(tc_dns_sd_srv_record_create)
{
struct pico_mdns_record *record = NULL;
uint8_t buf[19] = {
0, 0, 0, 0, 0, 80,
5, 'h', 'i', 't', 'e', 'x',
5, 'l', 'o', 'c', 'a', 'l',
0
};
record = pico_dns_sd_srv_record_create("test.local", 0, 0, 80,
"hitex.local", 10,
PICO_MDNS_RECORD_UNIQUE);
fail_unless(strcmp(record->record->rname, "\4test\5local") == 0,
"Name of SRV record not correct!\n");
fail_unless(short_be(record->record->rsuffix->rtype) == 33,
"Type of SRV record not correctly set!\n");
fail_unless(short_be(record->record->rsuffix->rclass) == 0x8001,
"Class of SRV record not correctly set!\n");
fail_unless(short_be(record->record->rsuffix->rdlength) == 19,
"rdlength of SRV record not correctly set!\n");
fail_unless(long_be(record->record->rsuffix->rttl) == 10,
"TTL of SRV record not correctly set!\n");
fail_unless(memcmp(record->record->rdata, buf, 19) == 0,
"Rdata of TXT record not correctly set!\n");
pico_mdns_record_delete((void **)&record);
}
END_TEST
START_TEST(tc_dns_sd_txt_record_create)
{
struct pico_mdns_record *record = NULL;
kv_vector pairs = {
0
};
uint8_t buf[23] = {
10, 't', 'e', 'x', 't', 'v', 'e', 'r', 's', '=', '1',
4, 'p', 'a', 's', 's',
6, 'c', 'o', 'l', 'o', 'r', '='
};
pico_dns_sd_kv_vector_add(&pairs, text, value);
pico_dns_sd_kv_vector_add(&pairs, text2, NULL);
pico_dns_sd_kv_vector_add(&pairs, text3, value3);
record = pico_dns_sd_txt_record_create("test.local", pairs, 10,
PICO_MDNS_RECORD_UNIQUE);
fail_unless(strcmp(record->record->rname, "\4test\5local") == 0,
"Name of TXT record not correct!\n");
fail_unless(short_be(record->record->rsuffix->rtype) == 16,
"Type of TXT record not correctly set!\n");
fail_unless(short_be(record->record->rsuffix->rclass) == 0x8001,
"Class of TXT record not correctly set!\n");
fail_unless(short_be(record->record->rsuffix->rdlength) == 23,
"rdlength of TXT record not correctly set!\n");
fail_unless(long_be(record->record->rsuffix->rttl) == 10,
"TTL of TXT record not correctly set!\n");
fail_unless(memcmp(record->record->rdata, buf, 23) == 0,
"Rdata of TXT record not correctly set!\n");
pico_mdns_record_delete((void **)&record);
}
END_TEST
START_TEST(tc_dns_sd_kv_create)
{
key_value_pair_t *pair = NULL;
pair = pico_dns_sd_kv_create("textvers", "1");
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(strcmp(pair->value, "1") == 0,
"dns_sd_kv_create failed!\n");
PICO_FREE(pair->key);
PICO_FREE(pair->value);
PICO_FREE(pair);
pair = pico_dns_sd_kv_create("textvers", NULL);
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(pair->value == NULL,
"dns_sd_kv_create failed!\n");
PICO_FREE(pair->key);
PICO_FREE(pair);
pair = pico_dns_sd_kv_create("textvers", "");
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(strcmp(pair->value, "") == 0,
"dns_sd_kv_create failed!\n");
PICO_FREE(pair->key);
PICO_FREE(pair->value);
PICO_FREE(pair);
}
END_TEST
START_TEST(tc_dns_sd_kv_delete)
{
key_value_pair_t *pair = NULL;
pair = pico_dns_sd_kv_create("textvers", "1");
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(strcmp(pair->value, "1") == 0,
"dns_sd_kv_create failed!\n");
pico_dns_sd_kv_delete(&pair);
fail_unless(pair == NULL,
"dns_sd_kv_delete failed!\n");
pair = pico_dns_sd_kv_create("textvers", NULL);
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(pair->value == NULL,
"dns_sd_kv_create failed!\n");
pico_dns_sd_kv_delete(&pair);
fail_unless(pair == NULL,
"dns_sd_kv_delete failed!\n");
pair = pico_dns_sd_kv_create("textvers", "");
fail_unless(strcmp(pair->key, "textvers") == 0,
"dns_sd_kv_create failed!\n");
fail_unless(strcmp(pair->value, "") == 0,
"dns_sd_kv_create failed!\n");
pico_dns_sd_kv_delete(&pair);
fail_unless(pair == NULL,
"dns_sd_kv_delete failed!\n");
}
END_TEST
START_TEST(tc_dns_sd_check_type_format)
{
fail_unless(pico_dns_sd_check_type_format("_http._tcp") == 0,
"dns_sd_check_type_format failed with correct format!\n");
fail_unless(pico_dns_sd_check_type_format("_printer._sub._http._tcp")
== 0,
"dns_sd_check_type_format failed with subtype!\n");
/* Test too long subtype */
fail_unless(pico_dns_sd_check_type_format(
"1234567891123456789212345678931234567894123456789512345678961234._sub._http._tcp"), "dns_sd_check_type_format failed with too big subtype!\n");
/* Test too long service type with subtype */
fail_unless(pico_dns_sd_check_type_format(
"printer._sub.0123456789112345678._tcp"),
"dns_sd_check_type_format failed with too big sn w/ sub!\n");
/* Test too long service type with subtype */
fail_unless(pico_dns_sd_check_type_format("0123456789112345678._tcp"),
"dns_sd_check_type_format failed with too big sn!\n");
}
END_TEST
START_TEST(tc_dns_sd_check_instance_name_format)
{
/* Test too long name */
fail_unless(pico_dns_sd_check_instance_name_format(
"1234567891123456789212345678931234567894123456789512345678961234"),
"dns_sd_check_instance_name_format failed with too big name!\n");
fail_unless(pico_dns_sd_check_instance_name_format("Hello World!") == 0,
"dns_sd_check_instance_name_format failed!\n");
}
END_TEST
START_TEST(tc_dns_sd_create_service_url)
{
char *service_url = NULL;
service_url = pico_dns_sd_create_service_url("Hello World!", "_http._tcp");
fail_unless(strcmp(service_url, "Hello World!._http._tcp.local") == 0,
"dns_sd_create_service_url failed!\n");
}
END_TEST
START_TEST(tc_dns_sd_init)
{
pico_stack_init();
fail_unless(dns_sd_init() == 0,
"dns_sd_init failed!\n");
}
END_TEST
START_TEST(tc_dns_sd_register_service)
{
pico_stack_init();
dns_sd_init();
}
END_TEST
START_TEST(tc_dns_sd_browse_service)
{
/* Not implemented in code */
}
END_TEST
START_TEST(tc_dns_sd_kv_vector_add)
{
kv_vector pairs = {
0
};
char *key = NULL;
pico_dns_sd_kv_vector_add(&pairs, text, value);
pico_dns_sd_kv_vector_add(&pairs, text2, NULL);
pico_dns_sd_kv_vector_add(&pairs, text3, value3);
key = pico_dns_sd_kv_vector_get(&pairs, 2)->key;
fail_unless(strcmp("color", key) == 0,
"dns_sd_kv_vector_add failed!\n");
}
END_TEST
START_TEST(tc_dns_sd_kv_vector_get)
{
kv_vector pairs = {
0
};
char *key = NULL;
pico_dns_sd_kv_vector_add(&pairs, text, value);
pico_dns_sd_kv_vector_add(&pairs, text2, NULL);
pico_dns_sd_kv_vector_add(&pairs, text3, value3);
key = pico_dns_sd_kv_vector_get(&pairs, 2)->key;
fail_unless(strcmp("color", key) == 0,
"dns_sd_kv_vector_get failed!\n");
fail_unless(pico_dns_sd_kv_vector_get(&pairs, 3) == NULL,
"dns_sd_kv_vector_get failed @ OOB!\n");
}
END_TEST
START_TEST(tc_dns_sd_kv_vector_erase)
{
kv_vector pairs = {
0
};
pico_dns_sd_kv_vector_add(&pairs, text, value);
pico_dns_sd_kv_vector_add(&pairs, text2, NULL);
pico_dns_sd_kv_vector_add(&pairs, text3, value3);
pico_dns_sd_kv_vector_erase(&pairs);
fail_unless(pairs.pairs == NULL,
"dns_sd_kv_vector_erase failed!\n");
fail_unless(pairs.count == 0,
"dns_sd_kv_vector_erase failed!\n");
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
/* Key-Value pair vector plain creation function */
TCase *TCase_dns_sd_kv_vector_strlen = tcase_create("Unit test for dns_sd_kv_vector_strlen");
/* DNS utility functions */
TCase *TCase_dns_sd_srv_record_create = tcase_create("Unit test for dns_sd_srv_record_create");
TCase *TCase_dns_sd_txt_record_create = tcase_create("Unit test for dns_sd_txt_record_create");
/* Key-Value pair creation */
TCase *TCase_dns_sd_kv_create = tcase_create("Unit test for dns_sd_kv_create");
TCase *TCase_dns_sd_kv_delete = tcase_create("Unit test for dns_sd_kv_delete");
/* Utility functions */
TCase *TCase_dns_sd_check_type_format = tcase_create("Unit test for dns_sd_check_type_format");
TCase *TCase_dns_sd_check_instance_name_format = tcase_create("Unit test for dns_sd_check_instance_name_format");
TCase *TCase_dns_sd_create_service_url = tcase_create("Unit test for dns_sd_create_service_url");
/* DNS SD API functions */
TCase *TCase_dns_sd_init = tcase_create("Unit test for dns_sd_init");
TCase *TCase_dns_sd_register_service = tcase_create("Unit test for dns_sd_register_service");
TCase *TCase_dns_sd_browse_service = tcase_create("Unit test for dns_sd_browse_service");
/* Key-Value vector functions */
TCase *TCase_dns_sd_kv_vector_add = tcase_create("Unit test for dns_sd_kv_vector_add");
TCase *TCase_dns_sd_kv_vector_get = tcase_create("Unit test for dns_sd_kv_vector_get");
TCase *TCase_dns_sd_kv_vector_erase = tcase_create("Unit test for dns_sd_kv_vector_erase");
/* Key-Value pair vector plain creation function */
tcase_add_test(TCase_dns_sd_kv_vector_strlen, tc_dns_sd_kv_vector_strlen);
suite_add_tcase(s, TCase_dns_sd_kv_vector_strlen);
/* DNS utility functions */
tcase_add_test(TCase_dns_sd_srv_record_create, tc_dns_sd_srv_record_create);
suite_add_tcase(s, TCase_dns_sd_srv_record_create);
tcase_add_test(TCase_dns_sd_txt_record_create, tc_dns_sd_txt_record_create);
suite_add_tcase(s, TCase_dns_sd_txt_record_create);
/* Key-Value pair creation */
tcase_add_test(TCase_dns_sd_kv_create, tc_dns_sd_kv_create);
suite_add_tcase(s, TCase_dns_sd_kv_create);
tcase_add_test(TCase_dns_sd_kv_delete, tc_dns_sd_kv_delete);
suite_add_tcase(s, TCase_dns_sd_kv_delete);
/* Utility functions */
tcase_add_test(TCase_dns_sd_check_type_format, tc_dns_sd_check_type_format);
suite_add_tcase(s, TCase_dns_sd_check_type_format);
tcase_add_test(TCase_dns_sd_check_instance_name_format, tc_dns_sd_check_instance_name_format);
suite_add_tcase(s, TCase_dns_sd_check_instance_name_format);
tcase_add_test(TCase_dns_sd_create_service_url, tc_dns_sd_create_service_url);
suite_add_tcase(s, TCase_dns_sd_create_service_url);
/* DNS SD API functions */
tcase_add_test(TCase_dns_sd_init, tc_dns_sd_init);
suite_add_tcase(s, TCase_dns_sd_init);
tcase_add_test(TCase_dns_sd_register_service, tc_dns_sd_register_service);
suite_add_tcase(s, TCase_dns_sd_register_service);
tcase_add_test(TCase_dns_sd_browse_service, tc_dns_sd_browse_service);
suite_add_tcase(s, TCase_dns_sd_browse_service);
/* Key-Value vector functions */
tcase_add_test(TCase_dns_sd_kv_vector_add, tc_dns_sd_kv_vector_add);
suite_add_tcase(s, TCase_dns_sd_kv_vector_add);
tcase_add_test(TCase_dns_sd_kv_vector_get, tc_dns_sd_kv_vector_get);
suite_add_tcase(s, TCase_dns_sd_kv_vector_get);
tcase_add_test(TCase_dns_sd_kv_vector_erase, tc_dns_sd_kv_vector_erase);
suite_add_tcase(s, TCase_dns_sd_kv_vector_erase);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,315 @@
//#include "pico_config.h"
#include "pico_stack.h"
#include "pico_ipv4.h"
#include "pico_ipv6.h"
#include "pico_icmp4.h"
#include "pico_icmp6.h"
#include "pico_arp.h"
#include "pico_ethernet.h"
#include "modules/pico_ethernet.c"
#include "check.h"
#define STARTING() \
printf("*********************** STARTING %s ***\n", __func__); \
fflush(stdout)
#define TRYING(s, ...) \
printf("Trying %s: " s, __func__, ##__VA_ARGS__); \
fflush(stdout)
#define CHECKING(i) \
printf("Checking the results of test %2d in %s...", (i)++, \
__func__); \
fflush(stdout)
#define SUCCESS() \
printf(" SUCCES\n"); \
fflush(stdout)
#define BREAKING(s, ...) \
printf("Breaking %s: " s, __func__, ##__VA_ARGS__); \
fflush(stdout)
#define ENDING(i) \
printf("*********************** ENDING %s *** N TESTS: %d\n", \
__func__, ((i)-1)); \
fflush(stdout)
#define DBG(s, ...) \
printf(s, ##__VA_ARGS__); \
fflush(stdout)
Suite *pico_suite(void);
START_TEST(tc_destination_is_bcast)
{
/* test this: static int destination_is_bcast(struct pico_frame *f) */
struct pico_ip6 addr = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }};
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
struct pico_ipv6_hdr *h = (struct pico_ipv6_hdr *)f->buffer;
struct pico_ipv4_hdr *h4 = NULL;
/* Test parameters */
int ret = 0, count = 0;
f->net_hdr = (uint8_t*) h;
f->buffer[0] = 0x60; /* Ipv6 */
STARTING();
TRYING("With wrong protocol -> IPv6\n");
memcpy(h->dst.addr, addr.addr, PICO_SIZE_IP6);
ret = destination_is_bcast(f);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since IPv6 frame\n");
SUCCESS();
pico_frame_discard(f);
f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr));
h4 = (struct pico_ipv4_hdr *)f->buffer;
f->net_hdr = (uint8_t *)h4;
f->buffer[0] = 0x40; /* IPv4 */
TRYING("With right protocol -> IPv4\n");
ret = destination_is_bcast(f);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since not a mcast address\n");
SUCCESS();
BREAKING();
ret = destination_is_bcast(NULL);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since NULL-pointer\n");
SUCCESS();
ENDING(count);
}
END_TEST
START_TEST(tc_destination_is_mcast)
{
struct pico_ip6 addr = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }};
struct pico_ip6 mcast = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }};
struct pico_ip4 addr4 = {0};
struct pico_ip4 mcast4 = {0};
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
struct pico_ipv6_hdr *h = (struct pico_ipv6_hdr *)f->buffer;
struct pico_ipv4_hdr *h4 = (struct pico_ipv4_hdr *)f->buffer;
/* Test parameters */
int ret = 0, count = 0;
f->net_hdr = (uint8_t*) h;
f->buffer[0] = 0x60; /* Ipv6 */
STARTING();
pico_string_to_ipv4("232.1.1.0", &(mcast4.addr)); /* 0 */
pico_string_to_ipv4("10.20.0.1", &(addr4.addr));
pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", (mcast.addr)); /* 0 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:100", (addr.addr)); /* 0 */
TRYING("With IPv6 unicast addr\n");
memcpy(h->dst.addr, addr.addr, PICO_SIZE_IP6);
ret = destination_is_mcast(f);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since not an IPv6 multicast\n");
SUCCESS();
TRYING("With IPv6 multicast addr\n");
memcpy(h->dst.addr, mcast.addr, PICO_SIZE_IP6);
ret = destination_is_mcast(f);
CHECKING(count);
fail_unless(1 == ret, "Should've returned 1 since an IPv6 multicast\n");
SUCCESS();
pico_frame_discard(f);
f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr));
h4 = (struct pico_ipv4_hdr *)f->buffer;
f->net_hdr = (uint8_t *)h4;
f->buffer[0] = 0x40; /* IPv4 */
TRYING("With IPv4 unicast addr\n");
h4->dst = addr4;
ret = destination_is_bcast(f);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since not an IPv4 mcast address\n");
SUCCESS();
TRYING("With IPv4 multicast addr\n");
h4->dst = mcast4;
ret = destination_is_mcast(f);
CHECKING(count);
fail_unless(1 == ret, "Should've returned 1 since an IPv4 multicast\n");
SUCCESS();
BREAKING();
ret = destination_is_bcast(NULL);
CHECKING(count);
fail_unless(0 == ret, "Should've returned 0 since NULL-pointer\n");
SUCCESS();
ENDING(count);
}
END_TEST
START_TEST(tc_pico_ipv4_ethernet_receive)
{
/* test this: static int32_t pico_ipv4_ethernet_receive(struct pico_frame *f) */
struct pico_frame *f = NULL;
struct pico_ipv4_hdr *h4 = NULL;
int ret = 0, count = 0;
STARTING();
f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr));
h4 = (struct pico_ipv4_hdr *)f->buffer;
f->net_hdr = (uint8_t *)h4;
f->buffer[0] = 0x40; /* IPv4 */
TRYING("With IPv4 frame\n");
ret = pico_ipv4_ethernet_receive(f);
CHECKING(count);
fail_unless(ret > 0, "Was correct frame should've returned size of frame\n");
SUCCESS();
CHECKING(count);
fail_unless(pico_proto_ipv4.q_in->size == f->buffer_len, "Frame not enqueued\n");
SUCCESS();
ENDING(count);
}
END_TEST
START_TEST(tc_pico_ipv6_ethernet_receive)
{
/* test this: static int32_t pico_ipv6_ethernet_receive(struct pico_frame *f) */
struct pico_frame *f = NULL;
struct pico_ipv6_hdr *h = NULL;
int ret = 0, count = 0;
STARTING();
f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
h = (struct pico_ipv6_hdr *)f->buffer;
f->net_hdr = (uint8_t*) h;
f->buffer[0] = 0x40; /* Ipv6 */
TRYING("With wrong network type\n");
ret = pico_ipv6_ethernet_receive(f);
CHECKING(count);
fail_unless(ret == -1, "Wrong type should've returned an error\n");
SUCCESS();
f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
h = (struct pico_ipv6_hdr *)f->buffer;
f->net_hdr = (uint8_t*) h;
f->buffer[0] = 0x60;
TRYING("With correct network type\n");
ret = pico_ipv6_ethernet_receive(f);
CHECKING(count);
fail_unless(ret == (int32_t)f->buffer_len, "Was correct frame, should've returned success\n");
SUCCESS();
CHECKING(count);
fail_unless(pico_proto_ipv6.q_in->size == f->buffer_len, "Frame not enqueued\n");
SUCCESS();
ENDING(count);
}
END_TEST
START_TEST(tc_pico_eth_receive)
{
struct pico_frame *f = NULL;
struct pico_eth_hdr *eth = NULL;
int ret = 0, count = 0;
STARTING();
f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr) + sizeof(struct pico_eth_hdr));
f->datalink_hdr = f->buffer;
f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
eth = (struct pico_eth_hdr *)f->datalink_hdr;
((uint8_t *)(f->net_hdr))[0] = 0x40; /* Ipv4 */
/* ETHERNET PROTOCOL : IPV6 */
eth->proto = PICO_IDETH_IPV6;
TRYING("With wrong network type\n");
ret = pico_eth_receive(f);
CHECKING(count);
fail_unless(ret == -1, "Wrong type should've returned an error\n");
SUCCESS();
f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr) + sizeof(struct pico_eth_hdr));
f->datalink_hdr = f->buffer;
f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
eth = (struct pico_eth_hdr *)f->datalink_hdr;
((uint8_t *)(f->net_hdr))[0] = 0x60; /* Ipv6 */
/* ETHERNET PROTOCOL : IPV6 */
eth->proto = PICO_IDETH_IPV6;
TRYING("With correct network type\n");
ret = pico_eth_receive(f);
CHECKING(count);
fail_unless(ret == (int32_t)f->buffer_len, "Was correct frame, should've returned success\n");
SUCCESS();
CHECKING(count);
fail_unless(pico_proto_ipv6.q_in->size == f->buffer_len, "Frame not enqueued\n");
SUCCESS();
pico_frame_discard(f);
f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr) + sizeof(struct pico_eth_hdr));
f->datalink_hdr = f->buffer;
f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
eth = (struct pico_eth_hdr *)f->datalink_hdr;
((uint8_t *)(f->net_hdr))[0] = 0x40; /* Ipv4 */
TRYING("With wrong frame type\n");
ret = pico_eth_receive(f);
CHECKING(count);
fail_unless(ret == -1, "should've returned -1 wrong ethernet protocol\n");
SUCCESS();
f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr) + sizeof(struct pico_eth_hdr));
f->datalink_hdr = f->buffer;
f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
eth = (struct pico_eth_hdr *)f->datalink_hdr;
((uint8_t *)(f->net_hdr))[0] = 0x40; /* Ipv4 */
eth->proto = PICO_IDETH_IPV4;
TRYING("With IPv4 frame\n");
ret = pico_eth_receive(f);
CHECKING(count);
fail_unless(ret > 0, "Was correct frame should've returned size of frame\n");
SUCCESS();
CHECKING(count);
fail_unless(pico_proto_ipv4.q_in->size == f->buffer_len, "Frame not enqueued\n");
SUCCESS();
ENDING(count);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_destination_is_bcast = tcase_create("Unit test for destination_is_bcast");
TCase *TCase_destination_is_mcast = tcase_create("Unit test for destination_is_mcast");
TCase *TCase_pico_ipv4_ethernet_receive = tcase_create("Unit test for pico_ipv4_ethernet_receive");
TCase *TCase_pico_ipv6_ethernet_receive = tcase_create("Unit test for pico_ipv6_ethernet_receive");
TCase *TCase_pico_eth_receive = tcase_create("Unit test for pico_eth_receive");
tcase_add_test(TCase_destination_is_bcast, tc_destination_is_bcast);
suite_add_tcase(s, TCase_destination_is_bcast);
tcase_add_test(TCase_destination_is_mcast, tc_destination_is_mcast);
suite_add_tcase(s, TCase_destination_is_mcast);
tcase_add_test(TCase_pico_ipv4_ethernet_receive, tc_pico_ipv4_ethernet_receive);
suite_add_tcase(s, TCase_pico_ipv4_ethernet_receive);
tcase_add_test(TCase_pico_ipv6_ethernet_receive, tc_pico_ipv6_ethernet_receive);
suite_add_tcase(s, TCase_pico_ipv6_ethernet_receive);
tcase_add_test(TCase_pico_eth_receive, tc_pico_eth_receive);
suite_add_tcase(s, TCase_pico_eth_receive);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,274 @@
#include "pico_config.h"
#include "pico_protocol.h"
#include "pico_frame.h"
#include "stack/pico_frame.c"
#include "check.h"
volatile pico_err_t pico_err;
#define FRAME_SIZE 1000
Suite *pico_suite(void);
START_TEST(tc_pico_frame_alloc_discard)
{
struct pico_frame *f = pico_frame_alloc(FRAME_SIZE);
/* Test consistency */
fail_if(!f);
fail_if(!f->buffer);
fail_if(!f->usage_count);
fail_if(*f->usage_count != 1);
fail_if(f->start != f->buffer);
fail_if(f->len != f->buffer_len);
fail_if(f->len != FRAME_SIZE);
pico_frame_discard(f);
/* Test empty discard */
pico_frame_discard(NULL);
#ifdef PICO_FAULTY
printf("Testing with faulty memory in frame_alloc (1)\n");
pico_set_mm_failure(1);
f = pico_frame_alloc(FRAME_SIZE);
fail_if(f);
printf("Testing with faulty memory in frame_alloc (2)\n");
pico_set_mm_failure(2);
f = pico_frame_alloc(FRAME_SIZE);
fail_if(f);
printf("Testing with faulty memory in frame_do_alloc, with external buffer, failing to allocate usage_count \n");
pico_set_mm_failure(2);
f = pico_frame_do_alloc(FRAME_SIZE, 1, 1);
fail_if(f);
#endif
printf("Testing frame_do_alloc, with invalid flags combination\n");
f = pico_frame_do_alloc(FRAME_SIZE, 0, 1);
fail_if(f);
}
END_TEST
START_TEST(tc_pico_frame_grow_head)
{
struct pico_frame *f = pico_frame_alloc(3);
struct pico_frame *f2 = pico_frame_alloc(0);
int ret = 0;
uint8_t buf[6] = { 0, 0, 0, 'a', 'b', 'c'};
/* I don't care about usage_count, it's tested 'pico_frame_grow' */
fail_if(pico_frame_grow_head(f, 2) == 0);
/* Check for dereferencing OOB */
fail_if(pico_frame_grow_head(f2, 2) == -1);
f2->net_hdr[0] = 1;
f->net_hdr = f->buffer;
f->net_len = 3;
f->net_hdr[0] = 'a';
f->net_hdr[1] = 'b';
f->net_hdr[2] = 'c';
/* Try to grow head */
ret = pico_frame_grow_head(f, 6);
fail_if(ret != 0);
fail_unless(0 == memcmp(f->buffer, buf, f->buffer_len));
fail_unless(3 == f->net_hdr - f->buffer);
f->datalink_hdr = f->net_hdr - 3;
f->datalink_hdr[0] = 1;
}
END_TEST
START_TEST(tc_pico_frame_grow)
{
struct pico_frame *f = pico_frame_alloc(3);
struct pico_frame *f2 = pico_frame_alloc(0);
fail_if(f->buffer_len != 3);
/* Ensure that the usage_count starts at byte 4, for good alignment */
fail_if(((void*)f->usage_count - (void *)f->buffer) != 4);
((uint8_t *)f->buffer)[0] = 'a';
((uint8_t *)f->buffer)[1] = 'b';
((uint8_t *)f->buffer)[2] = 'c';
*f->usage_count = 12;
/* First, the failing cases. */
fail_if(pico_frame_grow(NULL, 30) == 0);
fail_if(pico_frame_grow(f, 2) == 0);
f->flags = 0;
/* Check for dereferencing OOB */
fail_if(pico_frame_grow(f2, 3) != 0);
f2->net_hdr[0] = 1;
f2->net_hdr[1] = 2;
pico_set_mm_failure(1);
fail_if(pico_frame_grow(f, 21) == 0);
/* Now, the good one. */
fail_if(pico_frame_grow(f, 21) != 0);
fail_if(f->buffer_len != 21);
fail_if(((void *)f->usage_count - (void *)f->buffer) != 24);
fail_if(((uint8_t *)f->buffer)[0] != 'a');
fail_if(((uint8_t *)f->buffer)[1] != 'b');
fail_if(((uint8_t *)f->buffer)[2] != 'c');
fail_if(*f->usage_count != 12);
*f->usage_count = 1;
pico_frame_discard(f);
f = pico_frame_alloc_skeleton(10, 1);
fail_if(!f);
fail_if(f->buffer);
fail_if(!f->flags);
f->buffer = PICO_ZALLOC(10);
fail_if(pico_frame_grow(f, 22) != 0);
fail_if (f->flags);
pico_frame_discard(f);
}
END_TEST
START_TEST(tc_pico_frame_copy)
{
struct pico_frame *f = pico_frame_alloc(FRAME_SIZE);
struct pico_frame *c1, *c2, *c3;
(void)c3;
fail_if(!f);
fail_if(!f->buffer);
fail_if(*f->usage_count != 1);
/* First copy */
c1 = pico_frame_copy(f);
fail_if(!c1);
fail_if(!c1->buffer);
fail_if(!c1->usage_count);
fail_if (c1->buffer != f->buffer);
fail_if(c1->usage_count != f->usage_count);
fail_if(*c1->usage_count != 2);
fail_if(*f->usage_count != 2);
fail_if(c1->start != c1->buffer);
fail_if(c1->len != c1->buffer_len);
fail_if(c1->len != FRAME_SIZE);
/* Second copy */
c2 = pico_frame_copy(f);
fail_if (c2->buffer != f->buffer);
fail_if(c2->usage_count != f->usage_count);
fail_if(*c2->usage_count != 3);
fail_if(*f->usage_count != 3);
fail_if(c2->start != c2->buffer);
fail_if(c2->len != c2->buffer_len);
fail_if(c2->len != FRAME_SIZE);
#ifdef PICO_FAULTY
printf("Testing with faulty memory in frame_copy (1)\n");
pico_set_mm_failure(1);
c3 = pico_frame_copy(f);
fail_if(c3);
fail_if(!f);
#endif
/* Discard 1 */
pico_frame_discard(c1);
fail_if(*f->usage_count != 2);
/* Discard 2 */
pico_frame_discard(c2);
fail_if(*f->usage_count != 1);
pico_frame_discard(f);
}
END_TEST
START_TEST(tc_pico_frame_deepcopy)
{
struct pico_frame *f = pico_frame_alloc(FRAME_SIZE);
struct pico_frame *dc = pico_frame_deepcopy(f);
fail_if(*f->usage_count != 1);
fail_if(*dc->usage_count != 1);
fail_if(dc->buffer == f->buffer);
#ifdef PICO_FAULTY
printf("Testing with faulty memory in frame_deepcopy (1)\n");
pico_set_mm_failure(1);
dc = pico_frame_deepcopy(f);
fail_if(dc);
fail_if(!f);
#endif
}
END_TEST
START_TEST(tc_pico_is_digit)
{
fail_if(pico_is_digit('a'));
fail_if(pico_is_digit('Z'));
fail_if(pico_is_digit('\0'));
fail_if(pico_is_digit('\n'));
fail_if(pico_is_digit('0' - 1));
fail_if(pico_is_digit('9' + 1));
fail_unless(pico_is_digit('0'));
fail_unless(pico_is_digit('9'));
}
END_TEST
START_TEST(tc_pico_is_hex)
{
fail_if(pico_is_hex('g'));
fail_if(pico_is_hex('Z'));
fail_if(pico_is_hex('\0'));
fail_if(pico_is_hex('\n'));
fail_if(pico_is_hex('0' - 1));
fail_if(pico_is_hex('f' + 1));
fail_if(pico_is_hex('F' + 1));
fail_unless(pico_is_hex('0'));
fail_unless(pico_is_hex('f'));
fail_unless(pico_is_hex('A'));
fail_unless(pico_is_hex('F'));
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("pico_frame.c");
TCase *TCase_pico_frame_alloc_discard = tcase_create("Unit test for pico_frame_alloc_discard");
TCase *TCase_pico_frame_copy = tcase_create("Unit test for pico_frame_copy");
TCase *TCase_pico_frame_grow = tcase_create("Unit test for pico_frame_grow");
TCase *TCase_pico_frame_grow_head = tcase_create("Unit test for pico_frame_grow_head");
TCase *TCase_pico_frame_deepcopy = tcase_create("Unit test for pico_frame_deepcopy");
TCase *TCase_pico_is_digit = tcase_create("Unit test for pico_is_digit");
TCase *TCase_pico_is_hex = tcase_create("Unit test for pico_is_hex");
tcase_add_test(TCase_pico_frame_alloc_discard, tc_pico_frame_alloc_discard);
tcase_add_test(TCase_pico_frame_copy, tc_pico_frame_copy);
tcase_add_test(TCase_pico_frame_grow, tc_pico_frame_grow);
tcase_add_test(TCase_pico_frame_grow_head, tc_pico_frame_grow_head);
tcase_add_test(TCase_pico_frame_deepcopy, tc_pico_frame_deepcopy);
tcase_add_test(TCase_pico_is_digit, tc_pico_is_digit);
tcase_add_test(TCase_pico_is_hex, tc_pico_is_hex);
suite_add_tcase(s, TCase_pico_frame_alloc_discard);
suite_add_tcase(s, TCase_pico_frame_copy);
suite_add_tcase(s, TCase_pico_frame_grow);
suite_add_tcase(s, TCase_pico_frame_grow_head);
suite_add_tcase(s, TCase_pico_frame_deepcopy);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,192 @@
#include "pico_hotplug_detection.h"
#include "pico_tree.h"
#include "pico_device.h"
#include "modules/pico_hotplug_detection.c"
#include "check.h"
#include "pico_dev_null.c"
Suite *pico_suite(void);
void cb_one(struct pico_device *dev, int event);
void cb_two(struct pico_device *dev, int event);
int link_state_a(struct pico_device *self);
int link_state_b(struct pico_device *self);
/* stubs for timer */
static int8_t timer_active = 0;
void (*timer_cb_function)(pico_time, void *);
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
IGNORE_PARAMETER(expire);
IGNORE_PARAMETER(arg);
timer_active++;
timer_cb_function = timer;
return 123;
}
void pico_timer_cancel(uint32_t id)
{
timer_active--;
fail_if(id != 123);
}
/* callbacks for testing */
uint32_t cb_one_cntr = 0;
int cb_one_last_event = 0;
void cb_one(struct pico_device *dev, int event)
{
IGNORE_PARAMETER(dev);
cb_one_cntr++;
cb_one_last_event = event;
}
uint32_t cb_two_cntr = 0;
int cb_two_last_event = 0;
void cb_two(struct pico_device *dev, int event)
{
IGNORE_PARAMETER(dev);
cb_two_cntr++;
cb_two_last_event = event;
}
/* link state functions for the testing devices */
int state_a = 0;
int link_state_a(struct pico_device *self)
{
IGNORE_PARAMETER(self);
return state_a;
}
int state_b = 0;
int link_state_b(struct pico_device *self)
{
IGNORE_PARAMETER(self);
return state_b;
}
START_TEST(tc_pico_hotplug_reg_dereg)
{
/* create some devices */
struct pico_device *dev_a, *dev_b;
dev_a = pico_null_create("dummy1");
dev_b = pico_null_create("dummy2");
dev_a->link_state = &link_state_a;
dev_b->link_state = &link_state_b;
/* add some function pointers to be called */
pico_hotplug_register(dev_a, &cb_one);
fail_unless(timer_active == 1);
pico_hotplug_register(dev_a, &cb_two);
pico_hotplug_register(dev_b, &cb_two);
fail_unless(timer_active == 1);
/* remove function pointers */
pico_hotplug_deregister(dev_a, &cb_one);
pico_hotplug_deregister(dev_a, &cb_two);
pico_hotplug_deregister(dev_b, &cb_two);
/* check that our tree is empty at the end */
fail_unless(pico_tree_empty(&Hotplug_device_tree));
/* register functions multiple times */
pico_hotplug_register(dev_a, &cb_one);
pico_hotplug_register(dev_a, &cb_one);
pico_hotplug_register(dev_a, &cb_two);
pico_hotplug_register(dev_a, &cb_two);
pico_hotplug_register(dev_b, &cb_two);
pico_hotplug_register(dev_b, &cb_two);
/* remove function pointers once */
pico_hotplug_deregister(dev_a, &cb_one);
pico_hotplug_deregister(dev_a, &cb_two);
fail_unless(timer_active == 1);
pico_hotplug_deregister(dev_b, &cb_two);
fail_unless(timer_active == 0);
/* check that our tree is empty at the end */
fail_unless(pico_tree_empty(&Hotplug_device_tree));
}
END_TEST
START_TEST(tc_pico_hotplug_callbacks)
{
/* create some devices */
struct pico_device *dev_a, *dev_b;
dev_a = pico_null_create("dummy1");
dev_b = pico_null_create("dummy2");
dev_a->link_state = &link_state_a;
dev_b->link_state = &link_state_b;
/* add some function pointers to be called */
pico_hotplug_register(dev_a, &cb_one);
pico_hotplug_register(dev_a, &cb_two);
pico_hotplug_register(dev_b, &cb_two);
fail_unless(timer_active == 1);
timer_active = 0;
timer_cb_function(0, NULL);
fail_unless(timer_active == 1);
fail_unless(cb_one_cntr == 1);
fail_unless(cb_two_cntr == 2);
state_a = 1;
timer_active = 0;
timer_cb_function(0, NULL);
fail_unless(timer_active == 1);
fail_unless(cb_one_cntr == 2);
fail_unless(cb_one_last_event == PICO_HOTPLUG_EVENT_UP );
fail_unless(cb_two_cntr == 3);
fail_unless(cb_two_last_event == PICO_HOTPLUG_EVENT_UP );
state_b = 1;
timer_active = 0;
timer_cb_function(0, NULL);
fail_unless(timer_active == 1);
fail_unless(cb_one_cntr == 2);
fail_unless(cb_one_last_event == PICO_HOTPLUG_EVENT_UP );
fail_unless(cb_two_cntr == 4);
fail_unless(cb_two_last_event == PICO_HOTPLUG_EVENT_UP );
state_a = 0;
state_b = 0;
timer_active = 0;
timer_cb_function(0, NULL);
fail_unless(timer_active == 1);
fail_unless(cb_one_cntr == 3);
fail_unless(cb_one_last_event == PICO_HOTPLUG_EVENT_DOWN );
fail_unless(cb_two_cntr == 6);
fail_unless(cb_two_last_event == PICO_HOTPLUG_EVENT_DOWN );
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_hotplug_reg_dereg = tcase_create("Unit test for pico_hotplug_reg_dereg");
TCase *TCase_pico_hotplug_callbacks = tcase_create("Unit test for pico_hotplug_callbacks");
tcase_add_test(TCase_pico_hotplug_reg_dereg, tc_pico_hotplug_reg_dereg);
suite_add_tcase(s, TCase_pico_hotplug_reg_dereg);
tcase_add_test(TCase_pico_hotplug_callbacks, tc_pico_hotplug_callbacks);
suite_add_tcase(s, TCase_pico_hotplug_callbacks);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,359 @@
#include "pico_config.h"
#include "pico_eth.h"
#include "pico_socket.h"
#include "pico_stack.h"
#include "pico_socket.h"
#include "pico_queue.h"
#include "pico_tree.h"
#include "modules/pico_igmp.c"
#include "check.h"
#include "pico_dev_null.c"
Suite *pico_suite(void);
void mock_callback(struct igmp_timer *t);
static uint32_t timers_added = 0;
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
IGNORE_PARAMETER(expire);
IGNORE_PARAMETER(timer);
IGNORE_PARAMETER(arg);
return ++timers_added;
}
void mock_callback(struct igmp_timer *t)
{
IGNORE_PARAMETER(t);
}
static int mcast_filter_cmp(void *ka, void *kb)
{
union pico_address *a = ka, *b = kb;
if (a->ip4.addr < b->ip4.addr)
return -1;
if (a->ip4.addr > b->ip4.addr)
return 1;
return 0;
}
static int mcast_sources_cmp(void *ka, void *kb)
{
union pico_address *a = ka, *b = kb;
if (a->ip4.addr < b->ip4.addr)
return -1;
if (a->ip4.addr > b->ip4.addr)
return 1;
return 0;
}
static PICO_TREE_DECLARE(_MCASTFilter, mcast_filter_cmp);
START_TEST(tc_pico_igmp_report_expired)
{
struct igmp_timer *t = PICO_ZALLOC(sizeof(struct igmp_timer));
struct pico_ip4 zero = {0};
t->mcast_link = zero;
t->mcast_group = zero;
/* void function, just check for side effects */
pico_igmp_report_expired(t);
}
END_TEST
START_TEST(tc_igmpt_type_compare)
{
struct igmp_timer a;
struct igmp_timer b;
a.type = 1;
b.type = 2;
fail_if(igmpt_type_compare(&a, &b) != -1);
fail_if(igmpt_type_compare(&b, &a) != 1);
fail_if(igmp_timer_cmp(&b, &a) != 1);
}
END_TEST
START_TEST(tc_pico_igmp_state_change)
{
struct pico_ip4 mcast_link, mcast_group;
pico_string_to_ipv4("192.168.1.1", &mcast_link.addr);
pico_string_to_ipv4("224.7.7.7", &mcast_group.addr);
fail_if(pico_igmp_state_change(&mcast_link, &mcast_group, 0, NULL, 99) != -1);
fail_if(pico_igmp_state_change(&mcast_link, &mcast_group, 0, NULL, PICO_IGMP_STATE_CREATE) != 0);
}
END_TEST
START_TEST(tc_pico_igmp_timer_expired)
{
struct igmp_timer *t, *s;
t = PICO_ZALLOC(sizeof(struct igmp_timer));
t->stopped = IGMP_TIMER_STOPPED;
t->type = 0;
pico_string_to_ipv4("192.168.1.1", &t->mcast_link.addr);
pico_string_to_ipv4("244.7.7.7", &t->mcast_group.addr);
/* void function, just check for side effects */
pico_igmp_timer_expired(0, (void *)t);
pico_tree_insert(&IGMPTimers, t);
s = PICO_ZALLOC(sizeof(struct igmp_timer));
memcpy(s,t,sizeof(struct igmp_timer)); // t will be freed next test
pico_igmp_timer_expired(0, (void *)t); /* t is freed here */
s->stopped++;
s->start = PICO_TIME_MS()*2;
s->type++;
pico_tree_insert(&IGMPTimers, s);
t = PICO_ZALLOC(sizeof(struct igmp_timer));
memcpy(t,s,sizeof(struct igmp_timer)); // s will be freed next test
pico_igmp_timer_expired(0, (void *)s); /* s is freed here */
t->callback = mock_callback;
pico_igmp_timer_expired(0, (void *)t);
}
END_TEST
START_TEST(tc_pico_igmp_v2querier_expired)
{
struct igmp_timer *t = PICO_ZALLOC(sizeof(struct igmp_timer));
struct pico_ip4 addr = {0};
struct pico_device *dev = pico_null_create("dummy2");
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_frame));
t->f = f;
pico_string_to_ipv4("192.168.1.1", &(addr.addr));
/* void function, just check for side effects */
/* No link */
pico_igmp_v2querier_expired(t);
f->dev = dev;
pico_ipv4_link_add(dev, addr, addr);
pico_igmp_v2querier_expired(t);
}
END_TEST
START_TEST(tc_pico_igmp_delete_parameter)
{
struct mcast_parameters p;
fail_if(pico_igmp_delete_parameter(&p) != -1);
}
END_TEST
START_TEST(tc_pico_igmp_process_in)
{
struct mcast_parameters *p;
struct pico_device *dev = pico_null_create("dummy3");
struct pico_ipv4_link *link;
uint8_t i, j, _i, _j;
int result;
struct pico_mcast_group g;
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv4("192.168.1.1", &p->mcast_link.ip4.addr);
pico_string_to_ipv4("244.7.7.7", &p->mcast_group.ip4.addr);
/* no link */
fail_if(pico_igmp_generate_report(p) != -1);
pico_ipv4_link_add(dev, p->mcast_link.ip4, p->mcast_link.ip4);
link = pico_ipv4_link_get(&p->mcast_link.ip4);
link->mcast_compatibility = PICO_IGMPV2;
g.mcast_addr.ip4 = p->mcast_group.ip4;
g.MCASTSources.root = &LEAF;
g.MCASTSources.compare = mcast_sources_cmp;
/* No mcastsources tree */
link->mcast_compatibility = PICO_IGMPV3;
fail_if(pico_igmp_generate_report(p) != -1);
pico_tree_insert(link->MCASTGroups, &g);
pico_tree_insert(&IGMPParameters, p);
link->mcast_compatibility = 99;
fail_if(pico_igmp_generate_report(p) != -1);
link->mcast_compatibility = PICO_IGMPV2;
fail_if(pico_igmp_generate_report(p) != 0);
link->mcast_compatibility = PICO_IGMPV3;
for(_j = 0; _j < 3; _j++) { /* FILTER */
(_j == 2) ? (result = -1) : (result = 0);
for(_i = 0; _i < 3; _i++) { /* FILTER */
if(_i == 2) result = -1;
for(i = 0; i < 3; i++) { /* STATES */
for(j = 0; j < 6; j++) { /* EVENTS */
p->MCASTFilter = &_MCASTFilter;
p->filter_mode = _i;
g.filter_mode = _j;
if(p->event == IGMP_EVENT_DELETE_GROUP || p->event == IGMP_EVENT_QUERY_RECV)
p->event++;
fail_if(pico_igmp_generate_report(p) != result);
p->state = i;
p->event = j;
if(result != -1 && p->f) /* in some combinations, no frame is created */
fail_if(pico_igmp_process_in(NULL, p->f) != 0);
}
}
}
}
}
END_TEST
START_TEST(tc_pico_igmp_find_parameter)
{
struct pico_ip4 mcast_link, mcast_group;
struct mcast_parameters test = {
0
};
fail_if(pico_igmp_find_parameter(NULL, NULL) != NULL);
pico_string_to_ipv4("192.168.1.1", &mcast_link.addr);
fail_if(pico_igmp_find_parameter(&mcast_link, NULL) != NULL);
pico_string_to_ipv4("192.168.1.2", &mcast_group.addr);
fail_if(pico_igmp_find_parameter(&mcast_link, &mcast_group) != NULL);
test.mcast_link.ip4 = mcast_link;
test.mcast_group.ip4 = mcast_group;
pico_tree_insert(&IGMPParameters, &test);
fail_if(pico_igmp_find_parameter(&mcast_link, &mcast_group) == NULL);
}
END_TEST
START_TEST(tc_pico_igmp_compatibility_mode)
{
struct pico_frame *f;
struct pico_device *dev = pico_null_create("dummy1");
struct pico_ip4 addr;
struct pico_ipv4_hdr *hdr;
struct igmp_message *query;
uint8_t ihl = 24;
f = pico_proto_ipv4.alloc(&pico_proto_ipv4, dev, sizeof(struct igmpv3_report) + sizeof(struct igmpv3_group_record) + (0 * sizeof(struct pico_ip4)));
pico_string_to_ipv4("192.168.1.2", &addr.addr);
hdr = (struct pico_ipv4_hdr *) f->net_hdr;
ihl = (uint8_t)((hdr->vhl & 0x0F) * 4); /* IHL is in 32bit words */
query = (struct igmp_message *) f->transport_hdr;
/* No link */
fail_if(pico_igmp_compatibility_mode(f) != -1);
pico_ipv4_link_add(dev, addr, addr);
f->dev = dev;
/* Igmpv3 query */
hdr->len = short_be((uint16_t)(12 + ihl));
fail_if(pico_igmp_compatibility_mode(f) != 0);
/* Igmpv2 query */
hdr->len = short_be((uint16_t)(8 + ihl));
query->max_resp_time = 0;
fail_if(pico_igmp_compatibility_mode(f) == 0);
query->max_resp_time = 1;
fail_if(pico_igmp_compatibility_mode(f) != 0);
/* Invalid Query */
hdr->len = short_be((uint16_t)(9 + ihl));
fail_if(pico_igmp_compatibility_mode(f) == 0);
}
END_TEST
START_TEST(tc_pico_igmp_analyse_packet)
{
struct pico_frame *f;
struct pico_device *dev = pico_null_create("dummy0");
struct pico_ip4 addr;
struct igmp_message *igmp;
f = pico_proto_ipv4.alloc(&pico_proto_ipv4, dev, sizeof(struct igmp_message));
pico_string_to_ipv4("192.168.1.1", &addr.addr);
/* No link */
fail_if(pico_igmp_analyse_packet(f) != NULL);
pico_ipv4_link_add(dev, addr, addr);
f->dev = dev;
igmp = (struct igmp_message *) (f->transport_hdr);
igmp->type = 0;
/* wrong type */
fail_if(pico_igmp_analyse_packet(f) != NULL);
/* all correct */
igmp->type = IGMP_TYPE_MEM_QUERY;
fail_if(pico_igmp_analyse_packet(f) == NULL);
igmp->type = IGMP_TYPE_MEM_REPORT_V1;
fail_if(pico_igmp_analyse_packet(f) == NULL);
igmp->type = IGMP_TYPE_MEM_REPORT_V2;
fail_if(pico_igmp_analyse_packet(f) == NULL);
igmp->type = IGMP_TYPE_MEM_REPORT_V3;
fail_if(pico_igmp_analyse_packet(f) == NULL);
}
END_TEST
START_TEST(tc_pico_igmp_discard)
{
/* TODO */
}
END_TEST
START_TEST(tc_srst)
{
struct mcast_parameters p;
struct pico_device *dev = pico_null_create("dummy0");
struct pico_ipv4_link *link;
pico_string_to_ipv4("192.168.1.1", &p.mcast_link.ip4.addr);
/* no link */
fail_if(srst(&p) != -1);
pico_ipv4_link_add(dev, p.mcast_link.ip4, p.mcast_link.ip4);
link = pico_ipv4_link_get(&p.mcast_link.ip4);
/* Not supported protocol for this call */
link->mcast_compatibility = PICO_IGMPV2;
fail_if(srst(&p) != -1);
link->mcast_compatibility = PICO_IGMPV3;
fail_if(srst(&p) != -1);
}
END_TEST
START_TEST(tc_stcl)
{
struct igmp_timer *t = PICO_ZALLOC(sizeof(struct igmp_timer));
struct mcast_parameters p;
pico_string_to_ipv4("192.168.1.10", &t->mcast_link.addr);
pico_string_to_ipv4("244.7.7.7", &t->mcast_group.addr);
p.mcast_link.ip4 = t->mcast_link;
p.mcast_group.ip4 = t->mcast_group;
t->type = IGMP_TIMER_GROUP_REPORT;
/* not in tree */
fail_if(stcl(&p) != -1);
pico_igmp_timer_start(t);
fail_if(stcl(&p) != 0);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_igmp_report_expired = tcase_create("Unit test for pico_igmp_report_expired");
TCase *TCase_igmpt_type_compare = tcase_create("Unit test for igmpt_type_compare");
TCase *TCase_pico_igmp_analyse_packet = tcase_create("Unit test for pico_igmp_analyse_packet");
TCase *TCase_pico_igmp_discard = tcase_create("Unit test for pico_igmp_discard");
TCase *TCase_pico_igmp_compatibility_mode = tcase_create("Unit test for pico_igmp_compatibility");
TCase *TCase_pico_igmp_state_change = tcase_create("Unit test for pico_igmp_state_change");
TCase *TCase_pico_igmp_process_in = tcase_create("Unit test for pico_igmp_process_in");
TCase *TCase_pico_igmp_timer_expired = tcase_create("Unit test for pico_igmp_timer_expired");
TCase *TCase_pico_igmp_delete_parameter = tcase_create("Unit test for pico_igmp_delete_parameter");
TCase *TCase_pico_igmp_find_parameter = tcase_create("Unit test for pico_igmp_find_parameter");
TCase *TCase_stcl = tcase_create("Unit test for stcl");
TCase *TCase_srst = tcase_create("Unit test for srst");
TCase *TCase_pico_igmp_v2querier_expired = tcase_create("Unit test for pico_igmp_v2_querier_expired");
tcase_add_test(TCase_pico_igmp_report_expired, tc_pico_igmp_report_expired);
suite_add_tcase(s, TCase_pico_igmp_report_expired);
tcase_add_test(TCase_igmpt_type_compare, tc_igmpt_type_compare);
suite_add_tcase(s, TCase_igmpt_type_compare);
tcase_add_test(TCase_pico_igmp_analyse_packet, tc_pico_igmp_analyse_packet);
suite_add_tcase(s, TCase_pico_igmp_analyse_packet);
tcase_add_test(TCase_pico_igmp_discard, tc_pico_igmp_discard);
suite_add_tcase(s, TCase_pico_igmp_discard);
tcase_add_test(TCase_pico_igmp_compatibility_mode, tc_pico_igmp_compatibility_mode);
suite_add_tcase(s, TCase_pico_igmp_compatibility_mode);
suite_add_tcase(s, TCase_pico_igmp_state_change);
tcase_add_test(TCase_pico_igmp_state_change, tc_pico_igmp_state_change);
suite_add_tcase(s, TCase_pico_igmp_process_in);
tcase_add_test(TCase_pico_igmp_process_in, tc_pico_igmp_process_in);
suite_add_tcase(s, TCase_pico_igmp_timer_expired);
tcase_add_test(TCase_pico_igmp_timer_expired, tc_pico_igmp_timer_expired);
suite_add_tcase(s, TCase_pico_igmp_delete_parameter);
tcase_add_test(TCase_pico_igmp_delete_parameter, tc_pico_igmp_delete_parameter);
suite_add_tcase(s, TCase_pico_igmp_find_parameter);
tcase_add_test(TCase_pico_igmp_find_parameter, tc_pico_igmp_find_parameter);
suite_add_tcase(s, TCase_stcl);
tcase_add_test(TCase_stcl, tc_stcl);
suite_add_tcase(s, TCase_srst);
tcase_add_test(TCase_srst, tc_srst);
suite_add_tcase(s, TCase_pico_igmp_v2querier_expired);
tcase_add_test(TCase_pico_igmp_v2querier_expired, tc_pico_igmp_v2querier_expired);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,321 @@
#include "pico_ipv4.h"
#include "pico_config.h"
#include "pico_icmp4.h"
#include "pico_stack.h"
#include "pico_eth.h"
#include "pico_socket.h"
#include "pico_device.h"
#include "pico_ipfilter.h"
#include "pico_tcp.h"
#include "pico_udp.h"
#include "pico_tree.h"
#include "modules/pico_ipfilter.c"
#include "check.h"
Suite *pico_suite(void);
int pico_icmp4_packet_filtered(struct pico_frame *f)
{
(void)f;
return 0;
}
void pico_frame_discard(struct pico_frame *f)
{
(void)f;
}
volatile pico_err_t pico_err;
START_TEST(tc_ipfilter)
{
uint32_t r;
struct filter_node a = {
0
}, b = {
0
};
fail_if(filter_compare(&a, &b) != 0);
/* a is rule, matching packet b */
a.filter_id = 1;
/* check that rule is matched properly */
fail_if(filter_match_packet_find_rule(&a, &b) != &a);
/* a has a out port that does not match packet */
b.out_port = 8;
a.out_port = 7;
fail_if(filter_compare(&a, &b) == 0);
/* a matches all ports */
a.out_port = 0;
fail_if(filter_compare(&a, &b) != 0);
/*** NEXT TEST ***/
/* a has a in port that does not match packet */
b.in_port = 8;
a.in_port = 7;
fail_if(filter_compare(&a, &b) == 0);
/* a matches all ports */
a.in_port = 0;
fail_if(filter_compare(&a, &b) != 0);
/* a matches port exactly */
a.in_port = 0;
fail_if(filter_compare(&a, &b) != 0);
/*** NEXT TEST ***/
/* a matches all out addresses */
b.out_addr = 0x010000a0;
fail_if(filter_compare(&a, &b) != 0);
/* a does not match b via 8-bit netmask */
a.out_addr = 0x000000c0;
a.out_addr_netmask = 0x000000ff;
fail_if(filter_compare(&a, &b) == 0);
/* a does not match b at all*/
a.out_addr = 0x020000b0;
a.out_addr_netmask = 0xffffffff;
fail_if(filter_compare(&a, &b) == 0);
/* a matches b via 8-bit netmask */
a.out_addr = 0x000000a0;
a.out_addr_netmask = 0x000000ff;
fail_if(filter_compare(&a, &b) != 0);
/* a matches b exactly */
a.out_addr = 0x010000a0;
a.out_addr_netmask = 0xffffffff;
fail_if(filter_compare(&a, &b) != 0);
/*** NEXT TEST ***/
/* a matches all in addresses */
b.in_addr = 0x010000a0;
fail_if(filter_compare(&a, &b) != 0);
/* a does not match b via 8-bit netmask */
a.in_addr = 0x000000c0;
a.in_addr_netmask = 0x000000ff;
fail_if(filter_compare(&a, &b) == 0);
/* a does not match b at all*/
a.in_addr = 0x020000b0;
a.in_addr_netmask = 0xffffffff;
fail_if(filter_compare(&a, &b) == 0);
/* a matches b via 8-bit netmask */
a.in_addr = 0x000000a0;
a.in_addr_netmask = 0x000000ff;
fail_if(filter_compare(&a, &b) != 0);
/* a matches b exactly */
a.in_addr = 0x010000a0;
a.in_addr_netmask = 0xffffffff;
fail_if(filter_compare(&a, &b) != 0);
/*** NEXT TEST ***/
/* a matches all protocols */
b.proto = 4u;
fail_if(filter_compare(&a, &b) != 0);
/* a does not match protocol */
a.proto = 5u;
fail_if(filter_compare(&a, &b) == 0);
/* a matches b's protocol */
a.proto = b.proto;
fail_if(filter_compare(&a, &b) != 0);
/*** NEXT TEST ***/
/* a matches all devices */
b.fdev = (struct pico_device *) &b;
fail_if(filter_compare(&a, &b) != 0);
/* a does not match device */
a.fdev = (struct pico_device *)&a;
fail_if(filter_compare(&a, &b) == 0);
/* a matches b's device */
a.fdev = b.fdev;
fail_if(filter_compare(&a, &b) != 0);
/*** SAME TEST DUPLICATED WITH INVERTED ORDER OF PARAMETERS ***/
memset(&a, 0, sizeof(struct filter_node));
memset(&b, 0, sizeof(struct filter_node));
a.filter_id = 2;
/* check that rule is matched properly */
fail_if(filter_match_packet_find_rule(&b, &a) != &a);
/* a has a out port that does not match packet */
b.out_port = 8;
a.out_port = 7;
fail_if(filter_compare(&b, &a) == 0);
/* a matches all ports */
a.out_port = 0;
fail_if(filter_compare(&b, &a) != 0);
/*** NEXT TEST ***/
/* a has a in port that does not match packet */
b.in_port = 8;
a.in_port = 7;
fail_if(filter_compare(&b, &a) == 0);
/* a matches all ports */
a.in_port = 0;
fail_if(filter_compare(&b, &a) != 0);
/* a matches port exactly */
a.in_port = 0;
fail_if(filter_compare(&b, &a) != 0);
/*** NEXT TEST ***/
/* a matches all out addresses */
b.out_addr = 0x010000a0;
fail_if(filter_compare(&b, &a) != 0);
/* a does not match b via 8-bit netmask */
a.out_addr = 0x000000c0;
a.out_addr_netmask = 0x000000ff;
fail_if(filter_compare(&b, &a) == 0);
/* a does not match b at all*/
a.out_addr = 0x020000b0;
a.out_addr_netmask = 0xffffffff;
fail_if(filter_compare(&b, &a) == 0);
/* a matches b via 8-bit netmask */
a.out_addr = 0x000000a0;
a.out_addr_netmask = 0x000000ff;
fail_if(filter_compare(&b, &a) != 0);
/* a matches b exactly */
a.out_addr = 0x010000a0;
a.out_addr_netmask = 0xffffffff;
fail_if(filter_compare(&b, &a) != 0);
/*** NEXT TEST ***/
/* a matches all in addresses */
b.in_addr = 0x010000a0;
fail_if(filter_compare(&b, &a) != 0);
/* a does not match b via 8-bit netmask */
a.in_addr = 0x000000c0;
a.in_addr_netmask = 0x000000ff;
fail_if(filter_compare(&b, &a) == 0);
/* a does not match b at all*/
a.in_addr = 0x020000b0;
a.in_addr_netmask = 0xffffffff;
fail_if(filter_compare(&b, &a) == 0);
/* a matches b via 8-bit netmask */
a.in_addr = 0x000000a0;
a.in_addr_netmask = 0x000000ff;
fail_if(filter_compare(&b, &a) != 0);
/* a matches b exactly */
a.in_addr = 0x010000a0;
a.in_addr_netmask = 0xffffffff;
fail_if(filter_compare(&b, &a) != 0);
/*** NEXT TEST ***/
/* a matches all protocols */
b.proto = 4u;
fail_if(filter_compare(&b, &a) != 0);
/* a does not match protocol */
a.proto = 5u;
fail_if(filter_compare(&b, &a) == 0);
/* a matches b's protocol */
a.proto = b.proto;
fail_if(filter_compare(&b, &a) != 0);
/*** NEXT TEST ***/
/* a matches all devices */
b.fdev = (struct pico_device *)&b;
fail_if(filter_compare(&b, &a) != 0);
/* a does not match device */
a.fdev = (struct pico_device *)&a;
fail_if(filter_compare(&b, &a) == 0);
/* a matches b's device */
a.fdev = b.fdev;
fail_if(filter_compare(&b, &a) != 0);
/*********** TEST ADD FILTER **************/
/*
uint32_t pico_ipv4_filter_add(struct pico_device *dev, uint8_t proto,
struct pico_ip4 *out_addr, struct pico_ip4 *out_addr_netmask,
struct pico_ip4 *in_addr, struct pico_ip4 *in_addr_netmask,
uint16_t out_port, uint16_t in_port, int8_t priority,
uint8_t tos, enum filter_action action)
*/
r = pico_ipv4_filter_add(NULL, 0, NULL, NULL, NULL, NULL, 0, 0, MAX_PRIORITY + 1, 0, FILTER_DROP);
fail_if(r > 0);
r = pico_ipv4_filter_add(NULL, 0, NULL, NULL, NULL, NULL, 0, 0, MIN_PRIORITY - 1, 0, FILTER_PRIORITY);
fail_if(r > 0);
r = pico_ipv4_filter_add(NULL, 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0, FILTER_COUNT);
fail_if(r > 0);
#ifdef FAULTY
pico_set_mm_failure(1);
r = pico_ipv4_filter_add(NULL, 0, NULL, NULL, NULL, NULL, 0, 0, 0, 0, FILTER_DROP);
fail_if(r > 0);
fail_if(pico_err != PICO_ERR_ENOMEM);
#endif
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("IPfilter module");
TCase *TCase_ipfilter = tcase_create("Unit test for ipfilter");
tcase_add_test(TCase_ipfilter, tc_ipfilter);
suite_add_tcase(s, TCase_ipfilter);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,289 @@
#include "pico_config.h"
#include "pico_tree.h"
#include "pico_ipv6_nd.h"
#include "pico_icmp6.h"
#include "pico_ipv6.h"
#include "pico_stack.h"
#include "pico_device.h"
#include "pico_eth.h"
#include "pico_addressing.h"
#include "modules/pico_ipv6_nd.c"
#include "check.h"
#ifdef PICO_SUPPORT_IPV6
#undef PICO_TIME
#undef PICO_TIME_MS
#define PICO_TIME_MS (0)
#define PICO_TIME (0)
Suite *pico_suite(void);
START_TEST(tc_pico_nd_new_expire_time)
{
struct pico_ipv6_neighbor n = {
0
};
struct pico_device d = { {0} };
/* TODO: how to test these time values */
n.dev = &d;
d.hostvars.retranstime = 666;
n.state = PICO_ND_STATE_INCOMPLETE;
pico_nd_new_expire_time(&n);
n.state = PICO_ND_STATE_REACHABLE;
pico_nd_new_expire_time(&n);
n.state = PICO_ND_STATE_STALE;
pico_nd_new_expire_time(&n);
n.state = PICO_ND_STATE_PROBE;
pico_nd_new_expire_time(&n);
}
END_TEST
START_TEST(tc_pico_nd_queue)
{
struct pico_ip6 addr = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 }};
int i;
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv6_hdr));
struct pico_ipv6_hdr *h = (struct pico_ipv6_hdr *) f->buffer;
f->net_hdr = (uint8_t*) h;
f->buffer[0] = 0x60; /* Ipv6 */
memcpy(h->dst.addr, addr.addr, PICO_SIZE_IP6);
fail_if(!f);
for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) {
fail_if(frames_queued_v6[i] != NULL);
}
pico_ipv6_nd_unreachable(&addr);
for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) {
fail_if(frames_queued_v6[i] != NULL);
}
pico_ipv6_nd_postpone(f);
fail_if(frames_queued_v6[0]->buffer != f->buffer);
pico_ipv6_nd_unreachable(&addr);
for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) {
fail_if(frames_queued_v6[i] != NULL);
}
}
END_TEST
START_TEST(tc_pico_nd_discover)
{
/* TODO: test this: static void pico_nd_discover(struct pico_ipv6_neighbor *n) */
}
END_TEST
START_TEST(tc_neigh_options)
{
/* TODO: test this: static int neigh_options(struct pico_frame *f, struct pico_icmp6_opt_lladdr *opt, uint8_t expected_opt) */
}
END_TEST
START_TEST(tc_neigh_adv_complete)
{
/* TODO: test this: static int neigh_adv_complete(struct pico_ipv6_neighbor *n, struct pico_icmp6_opt_lladdr *opt) */
}
END_TEST
START_TEST(tc_neigh_adv_reconfirm_router_option)
{
/* TODO: test this: static void neigh_adv_reconfirm_router_option(struct pico_ipv6_neighbor *n, unsigned int isRouter) */
}
END_TEST
START_TEST(tc_neigh_adv_reconfirm)
{
/* TODO: test this: static int neigh_adv_reconfirm(struct pico_ipv6_neighbor *n, struct pico_icmp6_opt_lladdr *opt, struct pico_icmp6_hdr *hdr) */
}
END_TEST
START_TEST(tc_neigh_adv_check_solicited)
{
/* TODO: test this: static void neigh_adv_check_solicited(struct pico_icmp6_hdr *ic6, struct pico_ipv6_neighbor *n) */
}
END_TEST
START_TEST(tc_neigh_adv_process)
{
/* TODO: test this: static int neigh_adv_process(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_ipv6_neighbor)
{
/* TODO: test this: static struct pico_ipv6_neighbor *neighbor_from_sol_new(struct pico_ip6 *ip, struct pico_icmp6_opt_lladdr *opt, struct pico_device *dev) */
}
END_TEST
START_TEST(tc_neighbor_from_sol)
{
/* TODO: test this: static void neighbor_from_sol(struct pico_ip6 *ip, struct pico_icmp6_opt_lladdr *opt, struct pico_device *dev) */
}
END_TEST
START_TEST(tc_neigh_sol_process)
{
/* TODO: test this: static int neigh_sol_process(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_icmp6_initial_checks)
{
/* TODO: test this: static int icmp6_initial_checks(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_neigh_adv_mcast_validity_checks)
{
/* TODO: test this: static int neigh_adv_mcast_validity_check(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_neigh_sol_mcast_validity_checks)
{
/* TODO: test this: static int neigh_sol_mcast_validity_check(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_neigh_adv_validity_checks)
{
/* TODO: test this: static int neigh_adv_validity_checks(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_neigh_sol_validity_checks)
{
/* TODO: test this: static int neigh_sol_validity_checks(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_neigh_adv_checks)
{
/* TODO: test this: static int neigh_adv_checks(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_nd_router_sol_recv)
{
/* TODO: test this: static int pico_nd_router_sol_recv(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_nd_router_adv_recv)
{
/* TODO: test this: static int pico_nd_router_adv_recv(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_nd_neigh_sol_recv)
{
/* TODO: test this: static int pico_nd_neigh_sol_recv(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_nd_neigh_adv_recv)
{
/* TODO: test this: static int pico_nd_neigh_adv_recv(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_nd_redirect_recv)
{
/* TODO: test this: static int pico_nd_redirect_recv(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_ipv6_nd_timer_callback)
{
/* TODO: test this: static void pico_ipv6_nd_timer_callback(pico_time now, void *arg) */
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_nd_new_expire_time = tcase_create("Unit test for pico_nd_new_expire_time");
TCase *TCase_pico_nd_discover = tcase_create("Unit test for pico_nd_discover");
TCase *TCase_neigh_options = tcase_create("Unit test for neigh_options");
TCase *TCase_neigh_adv_complete = tcase_create("Unit test for neigh_adv_complete");
TCase *TCase_neigh_adv_reconfirm_router_option = tcase_create("Unit test for neigh_adv_reconfirm_router_option");
TCase *TCase_neigh_adv_reconfirm = tcase_create("Unit test for neigh_adv_reconfirm");
TCase *TCase_neigh_adv_check_solicited = tcase_create("Unit test for neigh_adv_check_solicited");
TCase *TCase_neigh_adv_process = tcase_create("Unit test for neigh_adv_process");
TCase *TCase_pico_ipv6_neighbor = tcase_create("Unit test for pico_ipv6_neighbor");
TCase *TCase_neighbor_from_sol = tcase_create("Unit test for neighbor_from_sol");
TCase *TCase_neigh_sol_process = tcase_create("Unit test for neigh_sol_process");
TCase *TCase_icmp6_initial_checks = tcase_create("Unit test for icmp6_initial_checks");
TCase *TCase_neigh_sol_mcast_validity_checks = tcase_create("Unit test for neigh_sol_mcast_validity_checks");
TCase *TCase_neigh_sol_validity_checks = tcase_create("Unit test for neigh_sol_validity_checks");
TCase *TCase_neigh_adv_checks = tcase_create("Unit test for neigh_adv_checks");
TCase *TCase_neigh_adv_validity_checks = tcase_create("Unit test for neigh_adv_validity_checks");
TCase *TCase_neigh_adv_mcast_validity_checks = tcase_create("Unit test for neigh_adv_mcast_validity_checks");
TCase *TCase_pico_nd_router_sol_recv = tcase_create("Unit test for pico_nd_router_sol_recv");
TCase *TCase_pico_nd_router_adv_recv = tcase_create("Unit test for pico_nd_router_adv_recv");
TCase *TCase_pico_nd_neigh_sol_recv = tcase_create("Unit test for pico_nd_neigh_sol_recv");
TCase *TCase_pico_nd_neigh_adv_recv = tcase_create("Unit test for pico_nd_neigh_adv_recv");
TCase *TCase_pico_nd_redirect_recv = tcase_create("Unit test for pico_nd_redirect_recv");
TCase *TCase_pico_ipv6_nd_timer_callback = tcase_create("Unit test for pico_ipv6_nd_timer_callback");
TCase *TCase_pico_nd_queue = tcase_create("Unit test for pico_ipv6_nd: queue for pending frames");
tcase_add_test(TCase_pico_nd_new_expire_time, tc_pico_nd_new_expire_time);
suite_add_tcase(s, TCase_pico_nd_new_expire_time);
tcase_add_test(TCase_pico_nd_discover, tc_pico_nd_discover);
suite_add_tcase(s, TCase_pico_nd_discover);
tcase_add_test(TCase_neigh_options, tc_neigh_options);
suite_add_tcase(s, TCase_neigh_options);
tcase_add_test(TCase_neigh_adv_complete, tc_neigh_adv_complete);
suite_add_tcase(s, TCase_neigh_adv_complete);
tcase_add_test(TCase_neigh_adv_reconfirm_router_option, tc_neigh_adv_reconfirm_router_option);
suite_add_tcase(s, TCase_neigh_adv_reconfirm_router_option);
tcase_add_test(TCase_neigh_adv_reconfirm, tc_neigh_adv_reconfirm);
suite_add_tcase(s, TCase_neigh_adv_reconfirm);
tcase_add_test(TCase_neigh_adv_check_solicited, tc_neigh_adv_check_solicited);
suite_add_tcase(s, TCase_neigh_adv_check_solicited);
tcase_add_test(TCase_neigh_adv_process, tc_neigh_adv_process);
suite_add_tcase(s, TCase_neigh_adv_process);
tcase_add_test(TCase_pico_ipv6_neighbor, tc_pico_ipv6_neighbor);
suite_add_tcase(s, TCase_pico_ipv6_neighbor);
tcase_add_test(TCase_neighbor_from_sol, tc_neighbor_from_sol);
suite_add_tcase(s, TCase_neighbor_from_sol);
tcase_add_test(TCase_neigh_sol_process, tc_neigh_sol_process);
suite_add_tcase(s, TCase_neigh_sol_process);
tcase_add_test(TCase_icmp6_initial_checks, tc_icmp6_initial_checks);
suite_add_tcase(s, TCase_icmp6_initial_checks);
tcase_add_test(TCase_neigh_adv_mcast_validity_checks, tc_neigh_adv_mcast_validity_checks);
suite_add_tcase(s, TCase_neigh_adv_mcast_validity_checks);
tcase_add_test(TCase_neigh_sol_mcast_validity_checks, tc_neigh_sol_mcast_validity_checks);
suite_add_tcase(s, TCase_neigh_sol_mcast_validity_checks);
tcase_add_test(TCase_neigh_adv_validity_checks, tc_neigh_adv_validity_checks);
suite_add_tcase(s, TCase_neigh_adv_validity_checks);
tcase_add_test(TCase_neigh_sol_validity_checks, tc_neigh_sol_validity_checks);
suite_add_tcase(s, TCase_neigh_sol_validity_checks);
tcase_add_test(TCase_neigh_adv_checks, tc_neigh_adv_checks);
suite_add_tcase(s, TCase_neigh_adv_checks);
tcase_add_test(TCase_pico_nd_router_sol_recv, tc_pico_nd_router_sol_recv);
suite_add_tcase(s, TCase_pico_nd_router_sol_recv);
tcase_add_test(TCase_pico_nd_router_adv_recv, tc_pico_nd_router_adv_recv);
suite_add_tcase(s, TCase_pico_nd_router_adv_recv);
tcase_add_test(TCase_pico_nd_neigh_sol_recv, tc_pico_nd_neigh_sol_recv);
suite_add_tcase(s, TCase_pico_nd_neigh_sol_recv);
tcase_add_test(TCase_pico_nd_neigh_adv_recv, tc_pico_nd_neigh_adv_recv);
suite_add_tcase(s, TCase_pico_nd_neigh_adv_recv);
tcase_add_test(TCase_pico_nd_redirect_recv, tc_pico_nd_redirect_recv);
suite_add_tcase(s, TCase_pico_nd_redirect_recv);
tcase_add_test(TCase_pico_ipv6_nd_timer_callback, tc_pico_ipv6_nd_timer_callback);
suite_add_tcase(s, TCase_pico_ipv6_nd_timer_callback);
tcase_add_test(TCase_pico_nd_queue, tc_pico_nd_queue);
suite_add_tcase(s, TCase_pico_nd_queue);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}
#else
int main(void)
{
return 0;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,584 @@
#include "pico_config.h"
#include "pico_eth.h"
#include "pico_socket.h"
#include "pico_stack.h"
#include "pico_socket.h"
#include "pico_queue.h"
#include "pico_tree.h"
#include "modules/pico_mld.c"
#include "check.h"
#include "pico_dev_null.c"
Suite *pico_suite(void);
void mock_callback(struct mld_timer *t);
static uint32_t timers_added = 0;
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
IGNORE_PARAMETER(expire);
IGNORE_PARAMETER(timer);
IGNORE_PARAMETER(arg);
return ++timers_added;
}
void mock_callback(struct mld_timer *t)
{
IGNORE_PARAMETER(t);
}
static int mcast_filter_cmp_ipv6(void *ka, void *kb)
{
union pico_address *a = ka, *b = kb;
return memcmp(&a->ip6, &b->ip6, sizeof(struct pico_ip6));
}
static int mcast_sources_cmp_ipv6(void *ka, void *kb)
{
union pico_address *a = ka, *b = kb;
return memcmp(&a->ip6, &b->ip6, sizeof(struct pico_ip6));
}
static PICO_TREE_DECLARE(_MCASTFilter, mcast_filter_cmp_ipv6);
START_TEST(tc_pico_mld_fill_hopbyhop)
{
struct pico_ipv6_hbhoption *hbh = NULL;
/* Not-null case tested by unit_ipv6.c */
fail_if(pico_mld_fill_hopbyhop(hbh) != NULL);
}
END_TEST
START_TEST(tc_pico_mld_check_hopbyhop)
{
struct pico_ipv6_hbhoption *hbh = NULL;
struct pico_ipv6_hbhoption _hbh;
uint8_t *p;
uint8_t options[8] = {
PICO_PROTO_ICMP6, 0, PICO_IPV6_EXTHDR_OPT_ROUTER_ALERT, \
PICO_IPV6_EXTHDR_OPT_ROUTER_ALERT_DATALEN, 0, 0, 1, 0
};
int i = 0;
int test = 0;
fail_if(pico_mld_check_hopbyhop(hbh) != -1);
_hbh.type = 1;
_hbh.len = 0;
fail_if(pico_mld_check_hopbyhop(&_hbh) != -1);
_hbh.type = PICO_PROTO_ICMP6;
_hbh.len = 1;
fail_if(pico_mld_check_hopbyhop(&_hbh) != -1);
hbh = (struct pico_ipv6_hbhoption *) PICO_ZALLOC(sizeof(struct pico_ipv6_hbhoption) + 7);
hbh->type = PICO_PROTO_ICMP6;
hbh->len = 0;
for(test = 0; test < 7; test++) {
p = (uint8_t *)hbh + sizeof(struct pico_ipv6_hbhoption);
for(i = 0; i < 6; i++ ) {
if(i != test)
*(p++) = options[i + 2];
else
*(p++) = 9;
}
if(test != 6)
fail_if(pico_mld_check_hopbyhop(hbh) != -1);
else
fail_if(pico_mld_check_hopbyhop(hbh) != 0);
}
}
END_TEST
START_TEST(tc_pico_mld_v1querier_expired)
{
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
struct pico_ip6 addr = {{0}};
struct pico_device *dev = pico_null_create("dummy2");
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_frame));
t->f = f;
pico_string_to_ipv6("AAAA::109", addr.addr);
/* void function, just check for side effects */
/* No link */
pico_mld_v1querier_expired(t);
f->dev = dev;
pico_ipv6_link_add(dev, addr, addr);
pico_mld_v1querier_expired(t);
}
END_TEST
START_TEST(tc_pico_mld_send_report)
{
struct pico_frame *f;
struct pico_device *dev = pico_null_create("dummy1");
struct pico_ip6 addr;
struct pico_ipv6_link *link;
struct mcast_parameters p;
f = pico_proto_ipv6.alloc(&pico_proto_ipv6, dev, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6)));
pico_string_to_ipv6("AAAA::110", addr.addr);
p.mcast_link.ip6 = addr;
/* No link */
fail_if(pico_mld_send_report(&p, f) != -1);
link = pico_ipv6_link_add(dev, addr, addr);
p.event = 0;
link->mcast_compatibility = PICO_MLDV1;
fail_if(pico_mld_send_report(&p, f) != 0);
link->mcast_compatibility = 99;
fail_if(pico_mld_send_report(&p, f) != -1);
}
END_TEST
START_TEST(tc_pico_mld_report_expired)
{
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
struct pico_ip6 zero = {0};
t->mcast_link = zero;
t->mcast_group = zero;
/* void function, just check for side effects */
pico_mld_report_expired(t);
}
END_TEST
START_TEST(tc_pico_mld_delete_parameter)
{
struct mcast_parameters p;
fail_if(pico_mld_delete_parameter(&p) != -1);
}
END_TEST
START_TEST(tc_mldt_type_compare)
{
struct mld_timer a;
struct mld_timer b;
a.type = 1;
b.type = 2;
fail_if(mldt_type_compare(&a, &b) != -1);
fail_if(mldt_type_compare(&b, &a) != 1);
fail_if(mld_timer_cmp(&b, &a) != 1);
}
END_TEST
START_TEST(tc_pico_mld_is_checksum_valid)
{
struct pico_frame *f;
f = pico_proto_ipv6.alloc(&pico_proto_ipv6, NULL, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6)));
fail_if(pico_mld_is_checksum_valid(f) == 1);
}
END_TEST
START_TEST(tc_pico_mld_find_parameter)
{
struct pico_ip6 mcast_link, mcast_group;
struct mcast_parameters test = {
0
};
fail_if(pico_mld_find_parameter(NULL, NULL) != NULL);
pico_string_to_ipv6("AAAA::111", mcast_link.addr);
fail_if(pico_mld_find_parameter(&mcast_link, NULL) != NULL);
pico_string_to_ipv6("AAAA::211", mcast_group.addr);
fail_if(pico_mld_find_parameter(&mcast_link, &mcast_group) != NULL);
test.mcast_link.ip6 = mcast_link;
test.mcast_group.ip6 = mcast_group;
pico_tree_insert(&MLDParameters, &test);
fail_if(pico_mld_find_parameter(&mcast_link, &mcast_group) == NULL);
pico_tree_delete(&MLDParameters, &test);
}
END_TEST
START_TEST(tc_pico_mld_timer_expired)
{
struct mld_timer *t, *s;
t = PICO_ZALLOC(sizeof(struct mld_timer));
t->stopped = MLD_TIMER_STOPPED;
t->type = 0;
pico_string_to_ipv6("AAAA::112", t->mcast_link.addr);
pico_string_to_ipv6("AAAA::112", t->mcast_group.addr);
/* void function, just check for side effects */
pico_mld_timer_expired(0, (void *)t);
pico_tree_insert(&MLDTimers, t);
s = PICO_ZALLOC(sizeof(struct mld_timer));
memcpy(s, t, sizeof(struct mld_timer)); /* t will be freed next test */
pico_mld_timer_expired(0, (void *)t); /* will be freed */
s->stopped++;
s->start = PICO_TIME_MS() * 2;
s->type++;
pico_tree_insert(&MLDTimers, s);
t = PICO_ZALLOC(sizeof(struct mld_timer));
memcpy(t, s, sizeof(struct mld_timer)); /* s will be freed next test */
pico_mld_timer_expired(0, (void *)s); /* s will be freed */
t->mld_callback = mock_callback;
pico_mld_timer_expired(0, (void *)t); /* t will be freed */
}
END_TEST
START_TEST(tc_pico_mld_send_done)
{
struct mcast_parameters p;
fail_if(pico_mld_send_done(&p, NULL) != 0);
}
END_TEST
START_TEST(tc_mld_stsdifs)
{
struct mcast_parameters *p;
struct pico_device *dev = pico_null_create("dummy3");
struct pico_ipv6_link *link;
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv6("AAAA::113", p->mcast_link.ip6.addr);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
/* no link */
fail_if(mld_stsdifs(p) != -1);
link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6);
link->mcast_compatibility = PICO_MLDV1;
/* no timer */
fail_if(mld_stsdifs(p) != -1);
t->type = MLD_TIMER_GROUP_REPORT;
t->mcast_link = p->mcast_link.ip6;
t->mcast_group = p->mcast_group.ip6;
pico_tree_insert(&MLDTimers, t);
fail_if(mld_stsdifs(p) != 0);
/* set flag */
pico_mld_flag = 1;
fail_if(mld_stsdifs(p) != 0);
}
END_TEST
START_TEST(tc_mld_srsf)
{
struct mcast_parameters *p;
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv6("AAAA::114", p->mcast_link.ip6.addr);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
fail_if(mld_srsf(p) != -1);
}
END_TEST
START_TEST(tc_mld_srst)
{
struct mcast_parameters *p;
struct pico_device *dev = pico_null_create("dummy3");
struct pico_ipv6_link *link;
struct pico_mcast_group g;
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv6("AAAA::99", p->mcast_link.ip6.addr);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
p->MCASTFilter = &_MCASTFilter;
p->filter_mode = 0;
g.filter_mode = 0;
g.mcast_addr = p->mcast_group;
g.MCASTSources.root = &LEAF;
g.MCASTSources.compare = mcast_sources_cmp_ipv6;
pico_tree_insert(&MLDParameters, p);
/* no link */
fail_if(mld_srst(p) != -1);
link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6);
link->mcast_compatibility = PICO_MLDV1;
/* invalid proto */
fail_if(mld_srst(p) != -1);
link->mcast_compatibility = PICO_MLDV2;
pico_tree_insert(link->MCASTGroups, &g);
fail_if(mld_srst(p) != 0);
pico_tree_delete(&MLDParameters, p);
}
END_TEST
START_TEST(tc_mld_mrsrrt)
{
struct mcast_parameters *p;
struct pico_device *dev = pico_null_create("dummy3");
struct pico_ipv6_link *link;
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv6("AAAA::115", p->mcast_link.ip6.addr);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
/* no link */
fail_if(mld_mrsrrt(p) != -1);
link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6);
link->mcast_compatibility = PICO_MLDV1;
/* wrong proto */
fail_if(mld_mrsrrt(p) != -1);
link->mcast_compatibility = PICO_MLDV2;
p->f = pico_proto_ipv6.alloc(&pico_proto_ipv6, dev, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6)));
fail_if(mld_mrsrrt(p) != -1);
}
END_TEST
START_TEST(tc_pico_mld_process_in)
{
struct mcast_parameters *p;
struct pico_device *dev = pico_null_create("dummy3");
struct pico_ipv6_link *link;
uint8_t i, j, _i, _j;
int result = 0;
struct pico_mcast_group g;
struct mldv2_report *report;
/* Building example frame */
p = PICO_ZALLOC(sizeof(struct mcast_parameters));
pico_string_to_ipv6("AAAA::101", p->mcast_link.ip6.addr);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
/* no link */
fail_if(pico_mld_generate_report(p) != -1);
link = pico_ipv6_link_add(dev, p->mcast_link.ip6, p->mcast_link.ip6);
pico_string_to_ipv6("AAAA::100", p->mcast_group.ip6.addr);
fail_if(pico_mld_generate_report(p) != -1);
pico_string_to_ipv6("FF00::e007:707", p->mcast_group.ip6.addr);
link->mcast_compatibility = PICO_MLDV1;
g.mcast_addr = p->mcast_group;
g.MCASTSources.root = &LEAF;
g.MCASTSources.compare = mcast_sources_cmp_ipv6;
/* No mcastsources tree */
link->mcast_compatibility = PICO_MLDV2;
fail_if(pico_mld_generate_report(p) != -1);
pico_tree_insert(link->MCASTGroups, &g);
pico_tree_insert(&MLDParameters, p);
link->mcast_compatibility = 99;
fail_if(pico_mld_generate_report(p) != -1);
link->mcast_compatibility = PICO_MLDV1;
fail_if(pico_mld_generate_report(p) != 0);
link->mcast_compatibility = PICO_MLDV2;
for(_j = 0; _j < 3; _j++) { /* FILTER */
(_j == 2) ? (result = -1) : (result = 0);
for(_i = 0; _i < 3; _i++) { /* FILTER */
if(_i == 2) result = -1;
for(i = 0; i < 3; i++) { /* STATES */
for(j = 0; j < 6; j++) { /* EVENTS */
p->MCASTFilter = &_MCASTFilter;
p->filter_mode = _i;
g.filter_mode = _j;
if(p->event == MLD_EVENT_DELETE_GROUP || p->event == MLD_EVENT_QUERY_RECV)
p->event++;
fail_if(pico_mld_generate_report(p) != result);
p->state = i;
p->event = j;
if(result != -1 && p->f) { /* in some combinations, no frame is created */
report = (struct mldv2_report *)(p->f->transport_hdr + MLD_ROUTER_ALERT_LEN);
report->crc = short_be(pico_icmp6_checksum(p->f));
fail_if(pico_mld_process_in(p->f) != 0);
}
}
}
}
}
pico_tree_delete(&MLDParameters, p);
}
END_TEST
START_TEST(tc_mld_rtimrtct)
{
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
struct mcast_parameters p;
pico_string_to_ipv6("AAAA::102", t->mcast_link.addr);
pico_string_to_ipv6("AAAA::102", t->mcast_group.addr);
p.mcast_link.ip6 = t->mcast_link;
p.mcast_group.ip6 = t->mcast_group;
t->type = MLD_TIMER_GROUP_REPORT;
/* not in tree */
fail_if(mld_rtimrtct(&p) != -1);
pico_mld_timer_start(t);
fail_if(mld_rtimrtct(&p) != 0);
}
END_TEST
START_TEST(tc_mld_stcl)
{
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
struct mcast_parameters p;
pico_string_to_ipv6("AAAA::103", t->mcast_link.addr);
pico_string_to_ipv6("AAAA::103", t->mcast_group.addr);
p.mcast_link.ip6 = t->mcast_link;
p.mcast_group.ip6 = t->mcast_group;
t->type = MLD_TIMER_GROUP_REPORT;
/* not in tree */
fail_if(mld_stcl(&p) != -1);
pico_mld_timer_start(t);
fail_if(mld_stcl(&p) != 0);
}
END_TEST
START_TEST(tc_pico_mld_compatibility_mode)
{
struct pico_frame *f;
struct pico_device *dev = pico_null_create("dummy1");
struct pico_ip6 addr;
f = pico_proto_ipv6.alloc(&pico_proto_ipv6, NULL, sizeof(struct mldv2_report) + MLD_ROUTER_ALERT_LEN + sizeof(struct mldv2_group_record) + (0 * sizeof(struct pico_ip6)));
pico_string_to_ipv6("AAAA::104", addr.addr);
/* No link */
fail_if(pico_mld_compatibility_mode(f) != -1);
pico_ipv6_link_add(dev, addr, addr);
f->dev = dev;
/* MLDv2 query */
f->buffer_len = 28 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN;
fail_if(pico_mld_compatibility_mode(f) != 0);
/* MLDv1 query */
f->buffer_len = 24 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN;
fail_if(pico_mld_compatibility_mode(f) != 0);
/* Invalid Query */
f->buffer_len = 25 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN;
fail_if(pico_mld_compatibility_mode(f) == 0);
/* MLDv2 query + timer amready running */
f->dev = dev;
f->buffer_len = 28 + PICO_SIZE_IP6HDR + MLD_ROUTER_ALERT_LEN + PICO_SIZE_ETHHDR;
fail_if(pico_mld_compatibility_mode(f) != -1);
}
END_TEST
START_TEST(tc_pico_mld_timer_reset)
{
struct mld_timer *t = PICO_ZALLOC(sizeof(struct mld_timer));
pico_string_to_ipv6("AAAA::105", t->mcast_link.addr);
pico_string_to_ipv6("AAAA::105", t->mcast_group.addr);
t->type = 0;
fail_if(pico_mld_timer_reset(t) != -1);
}
END_TEST
START_TEST(tc_pico_mld_state_change)
{
struct pico_ip6 mcast_link, mcast_group;
struct mcast_parameters p;
pico_string_to_ipv6("AAAA::106", mcast_link.addr);
pico_string_to_ipv6("AAAA::106", mcast_group.addr);
p.mcast_link.ip6 = mcast_link;
p.mcast_group.ip6 = mcast_group;
fail_if(pico_mld_state_change(NULL, &mcast_group, 0, NULL, PICO_MLD_STATE_CREATE) != -1);
/* All host group */
pico_string_to_ipv6("FF01:0:0:0:0:0:0:1", mcast_group.addr);
fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0, NULL, PICO_MLD_STATE_CREATE) != 0);
pico_string_to_ipv6("AAAA::107", mcast_group.addr);
fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0, NULL, 99) != -1);
pico_tree_insert(&MLDParameters, &p);
fail_if(pico_mld_state_change(&mcast_link, &mcast_group, 0, NULL, 99) != -1);
pico_tree_delete(&MLDParameters, &p);
}
END_TEST
START_TEST(tc_pico_mld_analyse_packet)
{
struct pico_frame *f;
struct pico_device *dev = pico_null_create("dummy0");
struct pico_ip6 addr;
struct pico_ip6 local;
struct pico_ipv6_hdr *ip6;
struct pico_ipv6_hbhoption *hbh;
struct pico_icmp6_hdr *mld;
f = pico_proto_ipv6.alloc(&pico_proto_ipv6, dev, sizeof(struct mld_message) + MLD_ROUTER_ALERT_LEN);
pico_string_to_ipv6("AAAA::108", addr.addr);
pico_string_to_ipv6("FE80::1", local.addr);
/* No link */
fail_if(pico_mld_analyse_packet(f) != NULL);
pico_ipv6_link_add(dev, addr, addr);
ip6 = (struct pico_ipv6_hdr *) f->net_hdr;
ip6->hop = 99;
/* Incorrect hop */
fail_if(pico_mld_analyse_packet(f) != NULL);
ip6->hop = 1;
hbh = (struct pico_ipv6_hbhoption *) f->transport_hdr;
pico_mld_fill_hopbyhop(hbh);
hbh->type = 99;
/* incorrect hop by hop */
fail_if(pico_mld_analyse_packet(f) != NULL);
pico_mld_fill_hopbyhop(hbh);
ip6->src = addr;
/* Not link local */
fail_if(pico_mld_analyse_packet(f) != NULL);
memcpy(&ip6->src, PICO_IP6_ANY, sizeof(struct pico_ip6));
fail_if(pico_mld_analyse_packet(f) != NULL);
ip6->src = local;
mld = (struct pico_icmp6_hdr *) (f->transport_hdr + MLD_ROUTER_ALERT_LEN);
mld->type = 0;
/* wrong type */
fail_if(pico_mld_analyse_packet(f) != NULL);
/* all correct */
mld->type = PICO_MLD_QUERY;
fail_if(pico_mld_analyse_packet(f) == NULL);
mld->type = PICO_MLD_REPORT;
fail_if(pico_mld_analyse_packet(f) == NULL);
mld->type = PICO_MLD_DONE;
fail_if(pico_mld_analyse_packet(f) == NULL);
mld->type = PICO_MLD_REPORTV2;
fail_if(pico_mld_analyse_packet(f) == NULL);
}
END_TEST
START_TEST(tc_pico_mld_discard)
{
mld_discard(NULL);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_mld_fill_hopbyhop = tcase_create("Unit test for pico_mld_fill_hopbyhop");
TCase *TCase_pico_mld_check_hopbyhop = tcase_create("Unit test for pico_mld_check_hopbyhop");
TCase *TCase_pico_mld_report_expired = tcase_create("Unit test for pico_mld_report_expired");
TCase *TCase_mldt_type_compare = tcase_create("Unit test for mldt_type_compare");
TCase *TCase_pico_mld_analyse_packet = tcase_create("Unit test for pico_mld_analyse_packet");
TCase *TCase_pico_mld_discard = tcase_create("Unit test for pico_mld_discard");
TCase *TCase_pico_mld_compatibility_mode = tcase_create("Unit test for pico_mld_compatibility");
TCase *TCase_pico_mld_v1querier_expired = tcase_create("Unit test for pico_mld_v1querier_expired");
TCase *TCase_pico_mld_delete_parameter = tcase_create("Unit test for pico_mld_delete_parameter");
TCase *TCase_pico_mld_timer_expired = tcase_create("Unit test for pico_mld_timer_expired");
TCase *TCase_pico_mld_timer_reset = tcase_create("Unit test for pico_mld_timer_reset");
TCase *TCase_pico_mld_send_done = tcase_create("Unit test for pico_mld_send_done");
TCase *TCase_pico_mld_is_checksum_valid = tcase_create("Unit test for pico_mld_is_checksum");
TCase *TCase_pico_mld_find_parameter = tcase_create("Unit test for pico_mld_find_parameter");
TCase *TCase_pico_mld_state_change = tcase_create("Unit test for pico_mld_state_change");
TCase *TCase_mld_srst = tcase_create("Unit test for pico_mld_srst");
TCase *TCase_mld_stcl = tcase_create("Unit test for pico_mld_stcl");
TCase *TCase_pico_mld_process_in = tcase_create("Unit test for pico_mld_process_in");
TCase *TCase_pico_mld_send_report = tcase_create("Unit test for pico_mld_send_report");
TCase *TCase_mld_stsdifs = tcase_create("Unit test for mld_stsdifs");
TCase *TCase_mld_srsf = tcase_create("Unit test for mld_srsf");
TCase *TCase_mld_rtimrtct = tcase_create("Unit test for mld_rtimrtct");
TCase *TCase_mld_mrsrrt = tcase_create("Unit test for mld_mrsrrt");
tcase_add_test(TCase_pico_mld_fill_hopbyhop, tc_pico_mld_fill_hopbyhop);
suite_add_tcase(s, TCase_pico_mld_fill_hopbyhop);
tcase_add_test(TCase_pico_mld_check_hopbyhop, tc_pico_mld_check_hopbyhop);
suite_add_tcase(s, TCase_pico_mld_check_hopbyhop);
tcase_add_test(TCase_pico_mld_report_expired, tc_pico_mld_report_expired);
suite_add_tcase(s, TCase_pico_mld_report_expired);
tcase_add_test(TCase_mldt_type_compare, tc_mldt_type_compare);
suite_add_tcase(s, TCase_mldt_type_compare);
tcase_add_test(TCase_pico_mld_analyse_packet, tc_pico_mld_analyse_packet);
suite_add_tcase(s, TCase_pico_mld_analyse_packet);
tcase_add_test(TCase_pico_mld_discard, tc_pico_mld_discard);
suite_add_tcase(s, TCase_pico_mld_discard);
tcase_add_test(TCase_pico_mld_compatibility_mode, tc_pico_mld_compatibility_mode);
suite_add_tcase(s, TCase_pico_mld_compatibility_mode);
tcase_add_test(TCase_pico_mld_v1querier_expired, tc_pico_mld_v1querier_expired);
suite_add_tcase(s, TCase_pico_mld_v1querier_expired);
tcase_add_test(TCase_pico_mld_delete_parameter, tc_pico_mld_delete_parameter);
suite_add_tcase(s, TCase_pico_mld_delete_parameter);
tcase_add_test(TCase_pico_mld_timer_expired, tc_pico_mld_timer_expired);
suite_add_tcase(s, TCase_pico_mld_timer_expired);
tcase_add_test(TCase_pico_mld_timer_reset, tc_pico_mld_timer_reset);
suite_add_tcase(s, TCase_pico_mld_timer_reset);
tcase_add_test(TCase_pico_mld_send_done, tc_pico_mld_send_done);
suite_add_tcase(s, TCase_pico_mld_send_done);
tcase_add_test(TCase_pico_mld_is_checksum_valid, tc_pico_mld_is_checksum_valid);
suite_add_tcase(s, TCase_pico_mld_is_checksum_valid);
tcase_add_test(TCase_pico_mld_find_parameter, tc_pico_mld_find_parameter);
suite_add_tcase(s, TCase_pico_mld_find_parameter);
tcase_add_test(TCase_pico_mld_state_change, tc_pico_mld_state_change);
suite_add_tcase(s, TCase_pico_mld_state_change);
tcase_add_test(TCase_mld_srst, tc_mld_srst);
suite_add_tcase(s, TCase_mld_srst);
tcase_add_test(TCase_mld_stcl, tc_mld_stcl);
suite_add_tcase(s, TCase_mld_stcl);
tcase_add_test(TCase_pico_mld_process_in, tc_pico_mld_process_in);
suite_add_tcase(s, TCase_pico_mld_process_in);
tcase_add_test(TCase_pico_mld_send_report, tc_pico_mld_send_report);
suite_add_tcase(s, TCase_pico_mld_send_report);
tcase_add_test(TCase_mld_stsdifs, tc_mld_stsdifs);
suite_add_tcase(s, TCase_mld_stsdifs);
tcase_add_test(TCase_mld_srsf, tc_mld_srsf);
suite_add_tcase(s, TCase_mld_srsf);
tcase_add_test(TCase_mld_rtimrtct, tc_mld_rtimrtct);
suite_add_tcase(s, TCase_mld_rtimrtct);
tcase_add_test(TCase_mld_mrsrrt, tc_mld_mrsrrt);
suite_add_tcase(s, TCase_mld_mrsrrt);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,229 @@
#include "pico_protocol.h"
#include "pico_tree.h"
#include "stack/pico_protocol.c"
#include "check.h"
Suite *pico_suite(void);
volatile pico_err_t pico_err = 0;
static int protocol_passby = 0;
static struct pico_frame f = {
.next = NULL
};
static struct pico_queue q = {
0
};
static struct pico_tree_node NODE_IN = {
0
};
static struct pico_tree_node NODE_OUT = {
0
};
#define KEY_IN 0x0D01
#define KEY_OUT 0x0D00
START_TEST(tc_pico_proto_cmp)
{
struct pico_protocol a = {
.hash = 0
};
struct pico_protocol b = {
.hash = 1
};
fail_if(pico_proto_cmp(&a, &b) >= 0);
a.hash = 1;
fail_if(pico_proto_cmp(&a, &b) != 0);
a.hash = 2;
fail_if(pico_proto_cmp(&a, &b) <= 0);
}
END_TEST
static int modunit_proto_loop_cb_in(struct pico_protocol *self, struct pico_frame *p)
{
if (!p)
protocol_passby = -1; /* Error! */
if (!self)
protocol_passby = -1; /* Error! */
if (protocol_passby != 0) /* Ensure that we are called only once. */
protocol_passby = -1;
protocol_passby = KEY_IN;
return 1; /* One frame processed! */
}
static int modunit_proto_loop_cb_out(struct pico_protocol *self, struct pico_frame *p)
{
if (!p)
protocol_passby = -1; /* Error! */
if (!self)
protocol_passby = -1; /* Error! */
if (protocol_passby != 0) /* Ensure that we are called only once. */
protocol_passby = -1;
protocol_passby = KEY_OUT;
return 1; /* One frame processed! */
}
START_TEST(tc_proto_loop_in)
{
struct pico_protocol p = {
.process_in = modunit_proto_loop_cb_in, .q_in = &q
};
protocol_passby = 0;
pico_enqueue(p.q_in, &f);
fail_if(proto_loop_in(&p, 1) != 0);
fail_if(protocol_passby != KEY_IN);
/* Try to dequeue from empty queue, get same loop_score */
protocol_passby = 0;
fail_if(proto_loop_in(&p, 1) != 1);
fail_if(protocol_passby != 0);
}
END_TEST
START_TEST(tc_proto_loop_out)
{
struct pico_protocol p = {
.process_out = modunit_proto_loop_cb_out, .q_out = &q
};
protocol_passby = 0;
pico_enqueue(p.q_out, &f);
fail_if(proto_loop_out(&p, 1) != 0);
fail_if(protocol_passby != KEY_OUT);
/* Try to dequeue from empty queue, get same loop_score */
protocol_passby = 0;
fail_if(proto_loop_out(&p, 1) != 1);
fail_if(protocol_passby != 0);
}
END_TEST
START_TEST(tc_proto_loop)
{
struct pico_protocol p = {
.process_in = modunit_proto_loop_cb_in,
.process_out = modunit_proto_loop_cb_out,
.q_in = &q,
.q_out = &q
};
protocol_passby = 0;
pico_enqueue(p.q_in, &f);
fail_if(proto_loop(&p, 1, PICO_LOOP_DIR_IN) != 0);
fail_if(protocol_passby != KEY_IN);
protocol_passby = 0;
pico_enqueue(p.q_out, &f);
fail_if(proto_loop(&p, 1, PICO_LOOP_DIR_OUT) != 0);
fail_if(protocol_passby != KEY_OUT);
}
END_TEST
START_TEST(tc_pico_tree_node)
{
struct pico_proto_rr rr = {
0
};
rr.node_in = &NODE_IN;
rr.node_out = &NODE_OUT;
fail_unless(roundrobin_init(&rr, PICO_LOOP_DIR_IN) == &NODE_IN);
fail_unless(roundrobin_init(&rr, PICO_LOOP_DIR_OUT) == &NODE_OUT);
}
END_TEST
START_TEST(tc_roundrobin_end)
{
struct pico_proto_rr rr;
roundrobin_end(&rr, PICO_LOOP_DIR_IN, &NODE_IN);
fail_if(rr.node_in != &NODE_IN);
roundrobin_end(&rr, PICO_LOOP_DIR_OUT, &NODE_OUT);
fail_if(rr.node_out != &NODE_OUT);
}
END_TEST
START_TEST(tc_pico_protocol_generic_loop)
{
struct pico_proto_rr rr = {
0
};
int ret = 0;
rr.node_in = &NODE_IN;
rr.node_out = &NODE_OUT;
ret = pico_protocol_generic_loop(&rr, 0, PICO_LOOP_DIR_IN);
fail_if(ret != 0);
pico_protocols_loop(0);
}
END_TEST
START_TEST(tc_proto_layer_rr_reset)
{
struct pico_proto_rr rr;
rr.node_in = &NODE_IN;
rr.node_out = &NODE_OUT;
proto_layer_rr_reset(&rr);
fail_if(rr.node_in != NULL);
fail_if(rr.node_out != NULL);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("pico_protocol.c");
TCase *TCase_pico_proto_cmp = tcase_create("Unit test for pico_proto_cmp");
TCase *TCase_proto_loop_in = tcase_create("Unit test for proto_loop_in");
TCase *TCase_proto_loop_out = tcase_create("Unit test for proto_loop_out");
TCase *TCase_proto_loop = tcase_create("Unit test for proto_loop");
TCase *TCase_pico_tree_node = tcase_create("Unit test for pico_tree_node");
TCase *TCase_roundrobin_end = tcase_create("Unit test for roundrobin_end");
TCase *TCase_pico_protocol_generic_loop = tcase_create("Unit test for pico_protocol_generic_loop");
TCase *TCase_proto_layer_rr_reset = tcase_create("Unit test for proto_layer_rr_reset");
tcase_add_test(TCase_pico_proto_cmp, tc_pico_proto_cmp);
suite_add_tcase(s, TCase_pico_proto_cmp);
tcase_add_test(TCase_proto_loop_in, tc_proto_loop_in);
suite_add_tcase(s, TCase_proto_loop_in);
tcase_add_test(TCase_proto_loop_out, tc_proto_loop_out);
suite_add_tcase(s, TCase_proto_loop_out);
tcase_add_test(TCase_proto_loop, tc_proto_loop);
suite_add_tcase(s, TCase_proto_loop);
tcase_add_test(TCase_pico_tree_node, tc_pico_tree_node);
suite_add_tcase(s, TCase_pico_tree_node);
tcase_add_test(TCase_roundrobin_end, tc_roundrobin_end);
suite_add_tcase(s, TCase_roundrobin_end);
tcase_add_test(TCase_pico_protocol_generic_loop, tc_pico_protocol_generic_loop);
suite_add_tcase(s, TCase_pico_protocol_generic_loop);
tcase_add_test(TCase_proto_layer_rr_reset, tc_proto_layer_rr_reset);
suite_add_tcase(s, TCase_proto_layer_rr_reset);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,428 @@
#include "pico_sntp_client.h"
#include "modules/pico_sntp_client.c"
#include "check.h"
#include "pico_socket.h"
/* Mocking functions, variables, ... */
volatile pico_time pico_tick = 0ull;
volatile pico_err_t pico_err = 0;
Suite *pico_suite(void);
void cb_synced(pico_err_t status);
/* Used in pico_sntp_sync_start */
struct pico_socket *pico_socket_open(uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *s))
{
struct pico_socket *sock = PICO_ZALLOC(sizeof(struct pico_socket));
(void) net;
(void) proto;
(void) wakeup;
fail_unless (sock != NULL);
return sock;
}
/* Used in pico_sntp_sync_start */
int pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port)
{
(void) s;
(void) local_addr;
(void) port;
return 0;
}
/* Used in pico_sntp_sync_start */
int pico_socket_close(struct pico_socket *s)
{
(void) s;
return 0;
}
/* Used in pico_sntp_send */
int8_t pico_socket_del(struct pico_socket *s)
{
(void) s;
return 0;
}
/* Used in dnsCallback */
int pico_string_to_ipv4(const char *ipstr, uint32_t *ip)
{
(void) ipstr;
(void) ip;
return 0;
}
/* Used in dnsCallback */
int pico_string_to_ipv6(const char *ipstr, uint8_t *ip)
{
(void) ipstr;
(void) ip;
return 0;
}
/* Used in pico_sntp_sync_start_ipv4 */
int pico_ipv4_to_string(char* ipbuf, const uint32_t ip)
{
(void) ipbuf;
(void) ip;
return 0;
}
/* Used in pico_sntp_sync_start_ipv6 */
int pico_ipv6_to_string(char* ipbuf, const uint8_t ip[PICO_SIZE_IP6])
{
(void) ipbuf;
(void) ip;
return 0;
}
/* Used in pico_sntp_client_wakeup */
int pico_socket_recvfrom(struct pico_socket *s, void *buf, int len, void *orig, uint16_t *remote_port)
{
(void) s;
(void) buf;
(void) len;
(void) orig;
(void) remote_port;
return 0;
}
/* Used in pico_sntp_send */
int pico_socket_sendto(struct pico_socket *s, const void *buf, int len, void *dst, uint16_t remote_port)
{
(void) s;
(void) buf;
(void) len;
(void) dst;
(void) remote_port;
return 0;
}
/* Used in pico_sntp_sync_start_dns_ipv4, not tested */
int pico_dns_client_getaddr(const char *url, void (*callback)(char *ip, void *arg), void *arg)
{
(void) url;
(void) callback;
(void) arg;
return 0;
}
/* Used in pico_sntp_sync_start_dns_ipv6, not tested */
int pico_dns_client_getaddr6(const char *url, void (*callback)(char *, void *), void *arg)
{
(void) url;
(void) callback;
(void) arg;
return 0;
}
/* Used in pico_sntp_parse */
void cb_synced(pico_err_t status)
{
(void) status;
}
/* Used in pico_sntp_send */
static uint32_t timers_added = 0;
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
(void) expire;
(void) timer;
(void) arg;
return ++timers_added;
}
/* Used in pico_sntp_cleanup */
void pico_timer_cancel(uint32_t t)
{
IGNORE_PARAMETER(t);
}
START_TEST(tc_timestamp_convert)
{
struct pico_sntp_ts ts;
struct pico_timeval tv;
pico_time delay = 0ull;
int ret = 0;
/* Input is all zero */
ts.sec = long_be(0ul);
ts.frac = long_be(0ul);
ret = timestamp_convert(&ts, &tv, delay);
ck_assert(ret == -1);
ck_assert(tv.tv_sec == 0);
ck_assert(tv.tv_msec == 0);
/* Minimum input*/
ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
ts.frac = long_be(4310344ul); /* MIN value: 1msec */
ret = timestamp_convert(&ts, &tv, delay);
ck_assert(ret == 0);
fail_unless(tv.tv_sec == 1390000000);
fail_unless(tv.tv_msec == 1);
/* Intermediate input */
ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
ts.frac = long_be(3865470566ul); /* value: 899msec */
ret = timestamp_convert(&ts, &tv, delay);
ck_assert(ret == 0);
fail_unless(tv.tv_sec == 1390000000);
fail_unless(tv.tv_msec == 900);
/* Maximum input */
ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
ts.frac = long_be(4294967295ul); /* MAX value: 999msec */
ret = timestamp_convert(&ts, &tv, delay);
ck_assert(ret == 0);
fail_unless(tv.tv_sec == 1390000001);
fail_unless(tv.tv_msec == 0);
/* Intermediate input with delay */
ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
ts.frac = long_be(3865470566ul); /* value: 899msec */
delay = 200ull;
ret = timestamp_convert(&ts, &tv, delay);
ck_assert(ret == 0);
fail_unless(tv.tv_sec == 1390000001);
fail_unless(tv.tv_msec == 100);
}
END_TEST
START_TEST(tc_pico_sntp_cleanup)
{
struct sntp_server_ns_cookie *ck;
struct pico_socket *sock;
ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
fail_unless (ck != NULL);
ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
fail_unless (ck->hostname != NULL);
ck->stamp = 0ull;
ck->cb_synced = cb_synced;
sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
ck->sock = sock;
sock->priv = ck;
pico_sntp_cleanup(ck, PICO_ERR_NOERR);
}
END_TEST
START_TEST(tc_pico_sntp_parse)
{
/* TODO: test this: static void pico_sntp_parse(char *buf, struct sntp_server_ns_cookie *ck) */
struct sntp_server_ns_cookie *ck;
struct pico_socket *sock;
struct pico_sntp_header header = {
0
};
ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
fail_unless (ck != NULL);
ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
fail_unless (ck->hostname != NULL);
ck->stamp = 0ull;
ck->cb_synced = cb_synced;
sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
ck->sock = sock;
sock->priv = ck;
header.mode = 4; /* server mode */
header.vn = 4; /* sntp version 4 */
header.stratum = 1; /* primary reference */
header.trs_ts.sec = long_be(SNTP_UNIX_OFFSET + 1390000000ul);
header.trs_ts.frac = long_be(3865470566ul); /* value: 899msec */
fail_if(pico_sntp_parse((char *) &header, NULL) == 0);
fail_if(pico_sntp_parse((char *) &header, ck) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_client_wakeup)
{
/* TODO: test this: static void pico_sntp_client_wakeup(uint16_t ev, struct pico_socket *s) */
uint16_t event = PICO_SOCK_EV_ERR;
struct sntp_server_ns_cookie *ck;
struct pico_socket *sock;
ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
fail_unless (ck != NULL);
ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
fail_unless (ck->hostname != NULL);
ck->stamp = 0ull;
ck->cb_synced = cb_synced;
sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
ck->sock = sock;
sock->priv = ck;
ck->cb_synced = cb_synced;
printf("Started wakeup unit test\n");
pico_sntp_client_wakeup(event, sock);
}
END_TEST
START_TEST(tc_sntp_receive_timeout)
{
struct sntp_server_ns_cookie *ck;
struct pico_socket *sock;
ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
fail_unless (ck != NULL);
ck->hostname = PICO_ZALLOC(sizeof(char) * 5);
fail_unless (ck->hostname != NULL);
ck->stamp = 0ull;
ck->cb_synced = cb_synced;
sock = pico_socket_open(0, 0, &pico_sntp_client_wakeup);
ck->sock = sock;
sock->priv = ck;
sntp_receive_timeout(0ull, ck);
}
END_TEST
START_TEST(tc_pico_sntp_send)
{
/* TODO: test this: static void pico_sntp_send(struct pico_socket *sock, union pico_address *dst) */
struct pico_socket sock = {
0
};
union pico_address dst;
struct sntp_server_ns_cookie ck = {
0
};
sock.priv = &ck;
pico_sntp_send(&sock, &dst);
}
END_TEST
START_TEST(tc_dnsCallback)
{
/* TODO: test this: static void dnsCallback(char *ip, void *arg) */
char ip[] = "198.123.30.132";
struct sntp_server_ns_cookie *ck;
ck = PICO_ZALLOC(sizeof(struct sntp_server_ns_cookie));
dnsCallback(ip, ck);
}
END_TEST
START_TEST(tc_pico_sntp_sync)
{
const char *sntp_server= "ntp.nasa.gov";
fail_if(pico_sntp_sync(NULL, cb_synced) == 0);
fail_if(pico_err != PICO_ERR_EINVAL);
fail_if(pico_sntp_sync(sntp_server, NULL) == 0);
fail_if(pico_err != PICO_ERR_EINVAL);
fail_if(pico_sntp_sync(sntp_server, cb_synced) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_ip)
{
union pico_address sntp_addr = { .ip4.addr = 0ul };
fail_if(pico_sntp_sync_ip(NULL, cb_synced) == 0);
fail_if(pico_err != PICO_ERR_EINVAL);
fail_if(pico_sntp_sync_ip(&sntp_addr, NULL) == 0);
fail_if(pico_err != PICO_ERR_EINVAL);
fail_if(pico_sntp_sync_ip(&sntp_addr, cb_synced) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_start)
{
struct sntp_server_ns_cookie ck = { 0 };
union pico_address sntp_addr = { .ip4.addr= 0ul };
fail_if(pico_sntp_sync_start(&ck, &sntp_addr) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_start_dns_ipv4)
{
const char *sntp_server = "ntp.nasa.gov";
fail_if(pico_sntp_sync_start_dns_ipv4(sntp_server, cb_synced) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_start_dns_ipv6)
{
const char *sntp_server = "ntp.nasa.gov";
fail_if(pico_sntp_sync_start_dns_ipv6(sntp_server, cb_synced) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_start_ipv4)
{
union pico_address sntp_addr = { .ip4.addr = 0};
fail_if(pico_sntp_sync_start_ipv4(&sntp_addr, cb_synced) != 0);
}
END_TEST
START_TEST(tc_pico_sntp_sync_start_ipv6)
{
union pico_address sntp_addr = { .ip6.addr = { 0 } };
fail_if(pico_sntp_sync_start_ipv6(&sntp_addr, cb_synced) != 0);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_timestamp_convert = tcase_create("Unit test for pico_timeval");
TCase *TCase_pico_sntp_cleanup = tcase_create("Unit test for pico_sntp_cleanup");
TCase *TCase_pico_sntp_send = tcase_create("Unit test for pico_sntp_send");
TCase *TCase_pico_sntp_parse = tcase_create("Unit test for pico_sntp_parse");
TCase *TCase_pico_sntp_client_wakeup = tcase_create("Unit test for pico_sntp_client_wakeup");
TCase *TCase_sntp_receive_timeout = tcase_create("Unit test for sntp_receive_timeout");
TCase *TCase_dnsCallback = tcase_create("Unit test for dnsCallback");
TCase *TCase_pico_sntp_sync = tcase_create("Unit test for pico_sntp_sync");
TCase *TCase_pico_sntp_sync_ip = tcase_create("Unit test for pico_sntp_sync_ip");
TCase *TCase_pico_sntp_sync_start = tcase_create("Unit test for pico_sntp_sync_start");
TCase *TCase_pico_sntp_sync_start_dns_ipv4 = tcase_create("Unit test for pico_sntp_sync_start_dns_ipv4");
TCase *TCase_pico_sntp_sync_start_dns_ipv6 = tcase_create("Unit test for pico_sntp_sync_start_dns_ipv6");
TCase *TCase_pico_sntp_sync_start_ipv4 = tcase_create("Unit test for pico_sntp_sync_start_ipv4");
TCase *TCase_pico_sntp_sync_start_ipv6 = tcase_create("Unit test for pico_sntp_sync_start_ipv6");
tcase_add_test(TCase_timestamp_convert, tc_timestamp_convert);
suite_add_tcase(s, TCase_timestamp_convert);
tcase_add_test(TCase_pico_sntp_cleanup, tc_pico_sntp_cleanup);
suite_add_tcase(s, TCase_pico_sntp_cleanup);
tcase_add_test(TCase_pico_sntp_parse, tc_pico_sntp_parse);
suite_add_tcase(s, TCase_pico_sntp_parse);
tcase_add_test(TCase_pico_sntp_client_wakeup, tc_pico_sntp_client_wakeup);
suite_add_tcase(s, TCase_pico_sntp_client_wakeup);
tcase_add_test(TCase_sntp_receive_timeout, tc_sntp_receive_timeout);
suite_add_tcase(s, TCase_sntp_receive_timeout);
tcase_add_test(TCase_pico_sntp_send, tc_pico_sntp_send);
suite_add_tcase(s, TCase_pico_sntp_send);
tcase_add_test(TCase_dnsCallback, tc_dnsCallback);
suite_add_tcase(s, TCase_dnsCallback);
tcase_add_test(TCase_pico_sntp_sync, tc_pico_sntp_sync);
suite_add_tcase(s, TCase_pico_sntp_sync);
tcase_add_test(TCase_pico_sntp_sync_ip, tc_pico_sntp_sync_ip);
suite_add_tcase(s, TCase_pico_sntp_sync_ip);
tcase_add_test(TCase_pico_sntp_sync_start, tc_pico_sntp_sync_start);
suite_add_tcase(s, TCase_pico_sntp_sync_start);
tcase_add_test(TCase_pico_sntp_sync_start_dns_ipv4, tc_pico_sntp_sync_start_dns_ipv4);
suite_add_tcase(s, TCase_pico_sntp_sync_start_dns_ipv4);
tcase_add_test(TCase_pico_sntp_sync_start_dns_ipv6, tc_pico_sntp_sync_start_dns_ipv6);
suite_add_tcase(s, TCase_pico_sntp_sync_start_dns_ipv6);
tcase_add_test(TCase_pico_sntp_sync_start_ipv4, tc_pico_sntp_sync_start_ipv4);
suite_add_tcase(s, TCase_pico_sntp_sync_start_ipv4);
tcase_add_test(TCase_pico_sntp_sync_start_ipv6, tc_pico_sntp_sync_start_ipv6);
suite_add_tcase(s, TCase_pico_sntp_sync_start_ipv6);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,145 @@
#include "pico_config.h"
#include "pico_frame.h"
#include "pico_device.h"
#include "pico_protocol.h"
#include "pico_stack.h"
#include "pico_addressing.h"
#include "pico_dns_client.h"
#include "pico_eth.h"
#include "pico_arp.h"
#include "pico_ipv4.h"
#include "pico_ipv6.h"
#include "pico_icmp4.h"
#include "pico_igmp.h"
#include "pico_udp.h"
#include "pico_tcp.h"
#include "pico_socket.h"
#include "heap.h"
#include "stack/pico_stack.c"
#include "check.h"
Suite *pico_suite(void);
void fake_timer(pico_time __attribute__((unused)) now, void __attribute__((unused)) *n);
START_TEST(tc_pico_ll_receive)
{
/* TODO: test this: static int32_t pico_ll_receive(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_ll_check_bcast)
{
/* TODO: test this: static void pico_ll_check_bcast(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_destination_is_bcast)
{
/* TODO: test this: static int destination_is_bcast(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_destination_is_mcast)
{
/* TODO: test this: static int destination_is_mcast(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_eth)
{
/* TODO: test this: static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint8_t *pico_mcast_mac) */
}
END_TEST
START_TEST(tc_pico_ethsend_local)
{
/* TODO: test this: static int32_t pico_ethsend_local(struct pico_frame *f, struct pico_eth_hdr *hdr, int *ret) */
}
END_TEST
START_TEST(tc_pico_ethsend_bcast)
{
/* TODO: test this: static int32_t pico_ethsend_bcast(struct pico_frame *f, int *ret) */
}
END_TEST
START_TEST(tc_pico_ethsend_dispatch)
{
/* TODO: test this: static int32_t pico_ethsend_dispatch(struct pico_frame *f, int *ret) */
}
END_TEST
START_TEST(tc_calc_score)
{
/* TODO: test this: static int calc_score(int *score, int *index, int avg[][PROTO_DEF_AVG_NR], int *ret) */
}
END_TEST
#ifdef PICO_FAULTY
void fake_timer(pico_time __attribute__((unused)) now, void __attribute__((unused)) *n)
{
}
#endif
START_TEST(tc_stack_generic)
{
#ifdef PICO_FAULTY
printf("Testing with faulty memory in pico_stack_init (11)\n");
pico_set_mm_failure(13);
fail_if(pico_stack_init() != -1);
#endif
pico_stack_init();
#ifdef PICO_FAULTY
printf("Testing with faulty memory in pico_timer_add (1)\n");
pico_set_mm_failure(1);
fail_if(pico_timer_add(0, fake_timer, NULL) != 0);
#endif
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_pico_ll_receive = tcase_create("Unit test for pico_ll_receive");
TCase *TCase_pico_ll_check_bcast = tcase_create("Unit test for pico_ll_check_bcast");
TCase *TCase_destination_is_bcast = tcase_create("Unit test for destination_is_bcast");
TCase *TCase_destination_is_mcast = tcase_create("Unit test for destination_is_mcast");
TCase *TCase_pico_eth = tcase_create("Unit test for pico_eth");
TCase *TCase_pico_ethsend_local = tcase_create("Unit test for pico_ethsend_local");
TCase *TCase_pico_ethsend_bcast = tcase_create("Unit test for pico_ethsend_bcast");
TCase *TCase_pico_ethsend_dispatch = tcase_create("Unit test for pico_ethsend_dispatch");
TCase *TCase_calc_score = tcase_create("Unit test for calc_score");
TCase *TCase_stack_generic = tcase_create("GENERIC stack initialization unit test");
tcase_add_test(TCase_pico_ll_receive, tc_pico_ll_receive);
suite_add_tcase(s, TCase_pico_ll_receive);
tcase_add_test(TCase_pico_ll_check_bcast, tc_pico_ll_check_bcast);
suite_add_tcase(s, TCase_pico_ll_check_bcast);
tcase_add_test(TCase_destination_is_bcast, tc_destination_is_bcast);
suite_add_tcase(s, TCase_destination_is_bcast);
tcase_add_test(TCase_destination_is_mcast, tc_destination_is_mcast);
suite_add_tcase(s, TCase_destination_is_mcast);
tcase_add_test(TCase_pico_eth, tc_pico_eth);
suite_add_tcase(s, TCase_pico_eth);
tcase_add_test(TCase_pico_ethsend_local, tc_pico_ethsend_local);
suite_add_tcase(s, TCase_pico_ethsend_local);
tcase_add_test(TCase_pico_ethsend_bcast, tc_pico_ethsend_bcast);
suite_add_tcase(s, TCase_pico_ethsend_bcast);
tcase_add_test(TCase_pico_ethsend_dispatch, tc_pico_ethsend_dispatch);
suite_add_tcase(s, TCase_pico_ethsend_dispatch);
tcase_add_test(TCase_calc_score, tc_calc_score);
suite_add_tcase(s, TCase_calc_score);
tcase_add_test(TCase_stack_generic, tc_stack_generic);
suite_add_tcase(s, TCase_stack_generic);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,59 @@
#include "modules/pico_strings.c"
#include "check.h"
Suite *pico_suite(void);
START_TEST(tc_get_string_terminator_position)
{
char buf[6] = "unit";
get_string_terminator_position(NULL,0);
fail_if(get_string_terminator_position(buf,2) != 0);
fail_if(get_string_terminator_position(buf,6) != &buf[4]);
}
END_TEST
START_TEST(tc_pico_strncasecmp)
{
fail_if(pico_strncasecmp("unit","UNIT",4) != 0);
fail_if(pico_strncasecmp("unit1","UNIT2",5) != -1);
fail_if(pico_strncasecmp("unit2","UNIT1",5) != 1);
}
END_TEST
START_TEST(tc_num2string)
{
char buf[20];
fail_if(num2string(-1,NULL,1) != -1);
fail_if(num2string(1,NULL,1) != -1);
fail_if(num2string(1,buf,1) != -1);
fail_if(num2string(1,buf,3) != 2);
fail_if(num2string(11,buf,3) != 3);
fail_if(num2string(112,buf,4) != 4);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_get_string_terminator_position = tcase_create("Unit test for get_string_terminator_position");
TCase *TCase_num2string = tcase_create("Unit test for num2string");
TCase *TCase_pico_strncasecmp = tcase_create("Unit test for pico_strncasecmp");
tcase_add_test(TCase_get_string_terminator_position, tc_get_string_terminator_position);
suite_add_tcase(s, TCase_get_string_terminator_position);
tcase_add_test(TCase_num2string,tc_num2string);
suite_add_tcase(s, TCase_num2string);
tcase_add_test(TCase_pico_strncasecmp,tc_pico_strncasecmp);
suite_add_tcase(s, TCase_pico_strncasecmp);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,863 @@
#include "pico_tcp.h"
#include "pico_config.h"
#include "pico_eth.h"
#include "pico_socket.h"
#include "pico_stack.h"
#include "pico_socket.h"
#include "pico_queue.h"
#include "pico_tree.h"
#include "modules/pico_tcp.c"
#include "check.h"
Suite *pico_suite(void);
static uint32_t timers_added = 0;
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
IGNORE_PARAMETER(expire);
IGNORE_PARAMETER(timer);
IGNORE_PARAMETER(arg);
return ++timers_added;
}
START_TEST(tc_input_segment_compare)
{
struct tcp_input_segment A = {
.seq = 0xFFFFFFFF
};
struct tcp_input_segment B = {
.seq = 0xFFFFFFFe
};
struct tcp_input_segment a = {
.seq = 0x01
};
struct tcp_input_segment b = {
.seq = 0x02
};
fail_if(input_segment_compare(&A, &B) <= 0);
fail_if(input_segment_compare(&a, &b) >= 0);
fail_if(input_segment_compare(&A, &b) >= 0);
fail_if(input_segment_compare(&A, &A) != 0);
}
END_TEST
START_TEST(tc_tcp_input_segment)
{
/* TODO: test this: static struct tcp_input_segment *segment_from_frame(struct pico_frame *f) */
struct pico_frame *f = pico_frame_alloc(60);
struct tcp_input_segment *seg;
fail_if(!f);
f->payload = f->start;
f->payload_len = 60;
f->transport_hdr = f->payload;
f->transport_len = (uint16_t)(f->payload_len - 40);
memset(f->payload, 'c', f->payload_len);
((struct pico_tcp_hdr *)((f)->transport_hdr))->seq = long_be(0xdeadbeef);
seg = segment_from_frame(f);
fail_if(!seg);
fail_if(seg->seq != 0xdeadbeef);
fail_if(seg->payload_len != f->payload_len);
fail_if(memcmp(seg->payload, f->payload, f->payload_len) != 0);
#ifdef PICO_FAULTY
printf("Testing with faulty memory in segment_from_frame (1)\n");
pico_set_mm_failure(1);
seg = segment_from_frame(f);
fail_if(seg);
printf("Testing with faulty memory in segment_from_frame (2)\n");
pico_set_mm_failure(2);
seg = segment_from_frame(f);
fail_if(seg);
#endif
printf("Testing segment_from_frame with empty payload\n");
f->payload_len = 0;
seg = segment_from_frame(f);
fail_if(seg);
}
END_TEST
START_TEST(tc_segment_compare)
{
/* TODO: test this: static int segment_compare(void *ka, void *kb) */
struct pico_frame *a = pico_frame_alloc(40);
struct pico_frame *b = pico_frame_alloc(60);
a->transport_hdr = a->start;
b->transport_hdr = b->start;
((struct pico_tcp_hdr *)((b)->transport_hdr))->seq = long_be(0xaa00);
((struct pico_tcp_hdr *)((a)->transport_hdr))->seq = long_be(0xffffaa00);
fail_if(segment_compare(a, b) >= 0);
fail_if(segment_compare(a, a) != 0);
}
END_TEST
START_TEST(tc_tcp_discard_all_segments)
{
struct pico_socket_tcp *t = (struct pico_socket_tcp *)pico_tcp_open(PICO_PROTO_IPV4);
struct pico_frame *f = pico_frame_alloc(80);
struct tcp_input_segment *is;
fail_if(!t);
fail_if(!f);
printf("Testing enqueuing bogus frame\n");
f->buffer_len = 0;
fail_if(pico_enqueue_segment(&t->tcpq_out, f) >= 0);
f->buffer_len = 80;
f->transport_hdr = f->start;
f->transport_len = (uint16_t)(f->buffer_len - 40);
f->payload = f->start + 40;
f->payload_len = 40;
memset(f->payload, 'c', f->payload_len);
is = segment_from_frame(f);
fail_if(!is);
is->payload_len = 0;
fail_if(pico_enqueue_segment(&t->tcpq_in, is) >= 0);
is->payload_len = 40;
/* Successfull cases */
fail_if(pico_enqueue_segment(&t->tcpq_out, f) <= 0);
fail_if(pico_enqueue_segment(&t->tcpq_in, is) <= 0);
/* Fail because size exceeded. Must return 0. */
t->tcpq_out.max_size = 50;
t->tcpq_in.max_size = 50;
fail_if(pico_enqueue_segment(&t->tcpq_out, f) != 0);
fail_if(pico_enqueue_segment(&t->tcpq_in, is) != 0);
#ifdef PICO_FAULTY
/* Fail because the tree cannot allocate a new node. Should return 0 */
printf("Testing with faulty memory (1)\n");
pico_set_mm_failure(1);
fail_if(pico_enqueue_segment(&t->tcpq_out, f) > 0);
pico_set_mm_failure(1);
fail_if(pico_enqueue_segment(&t->tcpq_in, is) > 0);
printf("Testing input segment conversion with faulty mm(1)\n");
pico_set_mm_failure(1);
is = segment_from_frame(f);
fail_if(is);
printf("Testing input segment conversion with faulty mm(2)\n");
pico_set_mm_failure(2);
is = segment_from_frame(f);
fail_if(is);
#endif
/* Discard all segments */
fail_if(t->tcpq_out.size == 0);
fail_if(t->tcpq_out.frames == 0);
tcp_discard_all_segments(&t->tcpq_out);
fail_if(t->tcpq_out.size != 0);
fail_if(t->tcpq_out.frames != 0);
fail_if(t->tcpq_in.size == 0);
fail_if(t->tcpq_in.frames == 0);
fail_if(pico_tcp_queue_in_is_empty(&t->sock));
tcp_discard_all_segments(&t->tcpq_in);
fail_if(t->tcpq_in.size != 0);
fail_if(t->tcpq_in.frames != 0);
fail_unless(pico_tcp_queue_in_is_empty(&t->sock));
/* Testing next_segment with NULLS */
fail_if(next_segment(NULL, NULL) != NULL);
}
END_TEST
START_TEST(tc_release_until)
{
struct pico_socket_tcp *t = (struct pico_socket_tcp *)pico_tcp_open(PICO_PROTO_IPV6);
struct pico_frame *f;
uint32_t i = 0;
int ret = 0;
struct tcp_input_segment *is;
fail_if(!t);
ret = release_until(&t->tcpq_out, 0);
fail_unless(ret == 0);
/* Test with output queue */
for (i = 0; i < 32; i++) {
f = pico_frame_alloc(84);
fail_if(!f);
f->transport_hdr = f->start;
f->transport_len = (uint16_t)f->buffer_len;
f->payload_len = f->transport_len;
((struct pico_tcp_hdr *)((f)->transport_hdr))->seq = long_be(0xaa00 + f->buffer_len * i);
printf("inserting frame seq = %08x len = %d\n", 0xaa00 + f->buffer_len * i, f->buffer_len);
fail_if(pico_enqueue_segment(&t->tcpq_out, f) <= 0);
}
ret = release_until(&t->tcpq_out, 0xaa00 + f->buffer_len * 30);
printf("Release until %08x\n", 0xaa00 + f->buffer_len * 30);
fail_if(ret != 30);
printf("Ret is %d\n", ret);
printf("Remaining is %d\n", t->tcpq_out.frames);
fail_if(t->tcpq_out.frames != 2);
/* Test with input queue */
for (i = 0; i < 32; i++) {
f = pico_frame_alloc(84);
fail_if(!f);
f->transport_hdr = f->start;
f->transport_len = (uint16_t)f->buffer_len;
f->payload_len = f->transport_len;
f->payload = f->start;
((struct pico_tcp_hdr *)((f)->transport_hdr))->seq = long_be(0xaa00 + f->buffer_len * i);
is = segment_from_frame(f);
fail_if(!is);
printf("inserting Input frame seq = %08x len = %d\n", long_be(is->seq), is->payload_len);
fail_if(!is);
fail_if(pico_enqueue_segment(&t->tcpq_in, is) <= 0);
}
ret = release_until(&t->tcpq_in, 0xaa00 + f->buffer_len * 30);
printf("Release until %08x\n", 0xaa00 + f->buffer_len * 30);
fail_if(ret != 30);
printf("Ret is %d\n", ret);
printf("Remaining is %d\n", t->tcpq_out.frames);
fail_if(t->tcpq_out.frames != 2);
}
END_TEST
START_TEST(tc_release_all_until)
{
struct pico_socket_tcp *t = (struct pico_socket_tcp *)pico_tcp_open(PICO_PROTO_IPV4);
struct pico_frame *f;
uint32_t i = 0;
int ret = 0;
struct tcp_input_segment *is;
pico_time tm;
fail_if(!t);
ret = release_all_until(&t->tcpq_out, 0, &tm);
fail_unless(ret == 0);
/* Test with output queue */
for (i = 0; i < 32; i++) {
f = pico_frame_alloc(84);
fail_if(!f);
f->transport_hdr = f->start;
f->transport_len = (uint16_t)f->buffer_len;
f->payload_len = f->transport_len;
((struct pico_tcp_hdr *)((f)->transport_hdr))->seq = long_be(0xaa00 + f->buffer_len * i);
printf("inserting frame seq = %08x len = %d\n", 0xaa00 + f->buffer_len * i, f->buffer_len);
fail_if(pico_enqueue_segment(&t->tcpq_out, f) <= 0);
}
ret = release_all_until(&t->tcpq_out, 0xaa00 + f->buffer_len * 30, &tm);
printf("Release until %08x\n", 0xaa00 + f->buffer_len * 30);
fail_if(ret != 30);
printf("Ret is %d\n", ret);
printf("Remaining is %d\n", t->tcpq_out.frames);
fail_if(t->tcpq_out.frames != 2);
/* Test with input queue */
for (i = 0; i < 32; i++) {
f = pico_frame_alloc(84);
fail_if(!f);
f->transport_hdr = f->start;
f->transport_len = (uint16_t)f->buffer_len;
f->payload_len = f->transport_len;
f->payload = f->start;
((struct pico_tcp_hdr *)((f)->transport_hdr))->seq = long_be(0xaa00 + f->buffer_len * i);
is = segment_from_frame(f);
fail_if(!is);
printf("inserting Input frame seq = %08x len = %d\n", long_be(is->seq), is->payload_len);
fail_if(!is);
fail_if(pico_enqueue_segment(&t->tcpq_in, is) <= 0);
}
ret = release_all_until(&t->tcpq_in, 0xaa00 + f->buffer_len * 30, &tm);
printf("Release until %08x\n", 0xaa00 + f->buffer_len * 30);
fail_if(ret != 30);
printf("Ret is %d\n", ret);
printf("Remaining is %d\n", t->tcpq_out.frames);
fail_if(t->tcpq_out.frames != 2);
/* Test enqueue_segment with NULL segment */
fail_if(pico_enqueue_segment(NULL, NULL) != -1);
}
END_TEST
START_TEST(tc_tcp_send_fin)
{
/* TODO: test this: static void tcp_send_fin(struct pico_socket_tcp *t); */
}
END_TEST
START_TEST(tc_pico_tcp_process_out)
{
/* TODO: test this: static int pico_tcp_process_out(struct pico_protocol *self, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_pico_paws)
{
pico_paws();
/* Nothing to test for a random function...*/
}
END_TEST
START_TEST(tc_tcp_add_options)
{
/* TODO: test this: static void tcp_add_options(struct pico_socket_tcp *ts, struct pico_frame *f, uint16_t flags, uint16_t optsiz) */
struct pico_socket_tcp ts = { };
struct pico_frame *f = pico_frame_alloc(100);
uint16_t flags = 0;
uint16_t optsiz = 50;
uint8_t *frame_opt_buff;
int i;
struct tcp_sack_block *a, *b, *c;
uint32_t al = 0xa0,
ar = 0xaf,
bl = 0xb0,
br = 0xbf,
cl = 0xc0,
cr = 0xcf;
f->transport_hdr = f->start;
f->transport_len = (uint16_t)f->buffer_len;
f->payload_len = f->transport_len;
frame_opt_buff = f->transport_hdr + PICO_SIZE_TCPHDR;
/* Window scale only */
printf("Testing window scale option\n");
ts.wnd_scale = 66;
tcp_add_options(&ts, f, flags, optsiz);
fail_if(frame_opt_buff[0] != PICO_TCP_OPTION_WS);
fail_if(frame_opt_buff[1] != PICO_TCPOPTLEN_WS);
fail_if(frame_opt_buff[2] != 66);
for (i = 3; i < optsiz - 1; i++)
fail_if(frame_opt_buff[i] != PICO_TCP_OPTION_NOOP);
fail_if(frame_opt_buff[optsiz - 1] != PICO_TCP_OPTION_END);
/* MSS + SACK_OK + WS + TIMESTAMPS */
printf("Testing full SYN options\n");
flags = PICO_TCP_SYN;
ts.wnd_scale = 66;
ts.mss = 0xAA88;
tcp_add_options(&ts, f, flags, optsiz);
fail_if(frame_opt_buff[0] != PICO_TCP_OPTION_MSS);
fail_if(frame_opt_buff[1] != PICO_TCPOPTLEN_MSS);
fail_if(frame_opt_buff[2] != 0xAA);
fail_if(frame_opt_buff[3] != 0x88);
fail_if(frame_opt_buff[4] != PICO_TCP_OPTION_SACK_OK);
fail_if(frame_opt_buff[5] != PICO_TCPOPTLEN_SACK_OK);
fail_if(frame_opt_buff[6] != PICO_TCP_OPTION_WS);
fail_if(frame_opt_buff[7] != PICO_TCPOPTLEN_WS);
fail_if(frame_opt_buff[8] != 66);
fail_if(frame_opt_buff[9] != PICO_TCP_OPTION_TIMESTAMP);
fail_if(frame_opt_buff[10] != PICO_TCPOPTLEN_TIMESTAMP);
/* Timestamps: up to byte 18 */
for (i = 19; i < optsiz - 1; i++)
fail_if(frame_opt_buff[i] != PICO_TCP_OPTION_NOOP);
fail_if(frame_opt_buff[optsiz - 1] != PICO_TCP_OPTION_END);
/* Testing SACKs */
printf("Testing full SACK options\n");
a = PICO_ZALLOC(sizeof (struct tcp_sack_block));
b = PICO_ZALLOC(sizeof (struct tcp_sack_block));
c = PICO_ZALLOC(sizeof (struct tcp_sack_block));
a->left = al;
a->right = ar;
a->next = b;
b->left = bl;
b->right = br;
b->next = c;
c->left = cl;
c->right = cr;
c->next = NULL;
ts.sack_ok = 1;
ts.sacks = a;
flags = PICO_TCP_ACK;
tcp_add_options(&ts, f, flags, optsiz);
fail_if(frame_opt_buff[0] != PICO_TCP_OPTION_WS);
fail_if(frame_opt_buff[1] != PICO_TCPOPTLEN_WS);
fail_if(frame_opt_buff[2] != 66);
fail_if(frame_opt_buff[3] != PICO_TCP_OPTION_SACK);
fail_if(frame_opt_buff[4] != PICO_TCPOPTLEN_SACK + 6 * (sizeof(uint32_t)));
fail_if(memcmp(frame_opt_buff + 5, &al, 4) != 0);
fail_if(memcmp(frame_opt_buff + 9, &ar, 4) != 0);
fail_if(memcmp(frame_opt_buff + 13, &bl, 4) != 0);
fail_if(memcmp(frame_opt_buff + 17, &br, 4) != 0);
fail_if(memcmp(frame_opt_buff + 21, &cl, 4) != 0);
fail_if(memcmp(frame_opt_buff + 25, &cr, 4) != 0);
fail_if(ts.sacks != NULL);
for (i = 29; i < optsiz - 1; i++)
fail_if(frame_opt_buff[i] != PICO_TCP_OPTION_NOOP);
fail_if(frame_opt_buff[optsiz - 1] != PICO_TCP_OPTION_END);
}
END_TEST
START_TEST(tc_tcp_options_size_frame)
{
/* TODO: test this: static uint16_t tcp_options_size_frame(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_add_options_frame)
{
/* TODO: test this: static void tcp_add_options_frame(struct pico_socket_tcp *ts, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_send_ack)
{
/* TODO: test this: static void tcp_send_ack(struct pico_socket_tcp *t); */
}
END_TEST
START_TEST(tc_tcp_set_space)
{
/* TODO: test this: static void tcp_set_space(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_options_size)
{
/* TODO: test this: static uint16_t tcp_options_size(struct pico_socket_tcp *t, uint16_t flags) */
}
END_TEST
START_TEST(tc_tcp_process_sack)
{
/* TODO: test this: static void tcp_process_sack(struct pico_socket_tcp *t, uint32_t start, uint32_t end) */
}
END_TEST
START_TEST(tc_tcp_rcv_sack)
{
/* TODO: test this: static void tcp_rcv_sack(struct pico_socket_tcp *t, uint8_t *opt, int len) */
}
END_TEST
START_TEST(tc_tcp_parse_options)
{
/* TODO: test this: static void tcp_parse_options(struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_send)
{
/* TODO: test this: static int tcp_send(struct pico_socket_tcp *ts, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_sock_stats)
{
/* TODO: test this: static void sock_stats(uint32_t when, void *arg) */
}
END_TEST
START_TEST(tc_initconn_retry)
{
/* TODO: test this: static void initconn_retry(pico_time when, void *arg) */
}
END_TEST
START_TEST(tc_tcp_send_synack)
{
/* TODO: test this: static int tcp_send_synack(struct pico_socket *s) */
}
END_TEST
START_TEST(tc_tcp_send_empty)
{
/* TODO: test this: static void tcp_send_empty(struct pico_socket_tcp *t, uint16_t flags, int is_keepalive) */
}
END_TEST
START_TEST(tc_tcp_send_probe)
{
/* TODO: test this: static void tcp_send_probe(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_send_rst)
{
/* TODO: test this: static int tcp_send_rst(struct pico_socket *s, struct pico_frame *fr) */
}
END_TEST
START_TEST(tc_tcp_nosync_rst)
{
/* TODO: test this: static int tcp_nosync_rst(struct pico_socket *s, struct pico_frame *fr) */
}
END_TEST
START_TEST(tc_tcp_sack_prepare)
{
/* TODO: test this: static void tcp_sack_prepare(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_data_in)
{
/* TODO: test this: static int tcp_data_in(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_ack_advance_una)
{
/* TODO: test this: static int tcp_ack_advance_una(struct pico_socket_tcp *t, struct pico_frame *f, pico_time *timestamp) */
}
END_TEST
START_TEST(tc_time_diff)
{
/* TODO: test this: static uint16_t time_diff(pico_time a, pico_time b) */
}
END_TEST
START_TEST(tc_tcp_rtt)
{
/* TODO: test this: static void tcp_rtt(struct pico_socket_tcp *t, uint32_t rtt) */
}
END_TEST
START_TEST(tc_tcp_congestion_control)
{
/* TODO: test this: static void tcp_congestion_control(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_add_retransmission_timer)
{
/* TODO: test this: static void add_retransmission_timer(struct pico_socket_tcp *t, pico_time next_ts); */
}
END_TEST
START_TEST(tc_tcp_first_timeout)
{
/* TODO: test this: static void tcp_first_timeout(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_rto_xmit)
{
/* TODO: test this: static int tcp_rto_xmit(struct pico_socket_tcp *t, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_next_zerowindow_probe)
{
/* TODO: test this: static void tcp_next_zerowindow_probe(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_is_allowed_to_send)
{
/* TODO: test this: static int tcp_is_allowed_to_send(struct pico_socket_tcp *t) */
}
END_TEST
START_TEST(tc_tcp_retrans_timeout)
{
/* TODO: test this: static void tcp_retrans_timeout(pico_time val, void *sock) */
}
END_TEST
START_TEST(tc_tcp_retrans)
{
/* TODO: test this: static int tcp_retrans(struct pico_socket_tcp *t, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_ack_dbg)
{
/* TODO: test this: static void tcp_ack_dbg(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_ack)
{
/* TODO: test this: static int tcp_ack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_finwaitack)
{
/* TODO: test this: static int tcp_finwaitack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_deltcb)
{
/* TODO: test this: static void tcp_deltcb(pico_time when, void *arg) */
}
END_TEST
START_TEST(tc_tcp_finwaitfin)
{
/* TODO: test this: static int tcp_finwaitfin(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_closewaitack)
{
/* TODO: test this: static int tcp_closewaitack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_lastackwait)
{
/* TODO: test this: static int tcp_lastackwait(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_syn)
{
/* TODO: test this: static int tcp_syn(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_set_init_point)
{
/* TODO: test this: static void tcp_set_init_point(struct pico_socket *s) */
}
END_TEST
START_TEST(tc_tcp_synack)
{
/* TODO: test this: static int tcp_synack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_first_ack)
{
/* TODO: test this: static int tcp_first_ack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_closewait)
{
/* TODO: test this: static int tcp_closewait(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_fin)
{
/* TODO: test this: static int tcp_fin(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_rcvfin)
{
/* TODO: test this: static int tcp_rcvfin(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_finack)
{
/* TODO: test this: static int tcp_finack(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_force_closed)
{
/* TODO: test this: static void tcp_force_closed(struct pico_socket *s) */
}
END_TEST
START_TEST(tc_tcp_wakeup_pending)
{
/* TODO: test this: static void tcp_wakeup_pending(struct pico_socket *s, uint16_t ev) */
}
END_TEST
START_TEST(tc_tcp_rst)
{
/* TODO: test this: static int tcp_rst(struct pico_socket *s, struct pico_frame *f) */
}
END_TEST
START_TEST(tc_tcp_halfopencon)
{
/* TODO: test this: static int tcp_halfopencon(struct pico_socket *s, struct pico_frame *fr) */
}
END_TEST
START_TEST(tc_tcp_closeconn)
{
/* TODO: test this: static int tcp_closeconn(struct pico_socket *s, struct pico_frame *fr) */
}
END_TEST
START_TEST(tc_invalid_flags)
{
/* TODO: test this: static uint8_t invalid_flags(struct pico_socket *s, uint8_t flags) */
}
END_TEST
START_TEST(tc_checkLocalClosing)
{
/* TODO: test this: static int checkLocalClosing(struct pico_socket *s) */
}
END_TEST
START_TEST(tc_checkRemoteClosing)
{
/* TODO: test this: static int checkRemoteClosing(struct pico_socket *s) */
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
TCase *TCase_input_segment_compare = tcase_create("Unit test for input_segment_compare");
TCase *TCase_tcp_input_segment = tcase_create("Unit test for tcp_input_segment");
TCase *TCase_segment_compare = tcase_create("Unit test for segment_compare");
TCase *TCase_tcp_discard_all_segments = tcase_create("Unit test for tcp_discard_all_segments");
TCase *TCase_release_until = tcase_create("Unit test for release_until");
TCase *TCase_release_all_until = tcase_create("Unit test for release_all_until");
TCase *TCase_tcp_send_fin = tcase_create("Unit test for tcp_send_fin");
TCase *TCase_pico_tcp_process_out = tcase_create("Unit test for pico_tcp_process_out");
TCase *TCase_pico_paws = tcase_create("Unit test for pico_paws");
TCase *TCase_tcp_add_options = tcase_create("Unit test for tcp_add_options");
TCase *TCase_tcp_options_size_frame = tcase_create("Unit test for tcp_options_size_frame");
TCase *TCase_tcp_add_options_frame = tcase_create("Unit test for tcp_add_options_frame");
TCase *TCase_tcp_send_ack = tcase_create("Unit test for tcp_send_ack");
TCase *TCase_tcp_set_space = tcase_create("Unit test for tcp_set_space");
TCase *TCase_tcp_options_size = tcase_create("Unit test for tcp_options_size");
TCase *TCase_tcp_process_sack = tcase_create("Unit test for tcp_process_sack");
TCase *TCase_tcp_rcv_sack = tcase_create("Unit test for tcp_rcv_sack");
TCase *TCase_tcp_parse_options = tcase_create("Unit test for tcp_parse_options");
TCase *TCase_tcp_send = tcase_create("Unit test for tcp_send");
TCase *TCase_sock_stats = tcase_create("Unit test for sock_stats");
TCase *TCase_initconn_retry = tcase_create("Unit test for initconn_retry");
TCase *TCase_tcp_send_synack = tcase_create("Unit test for tcp_send_synack");
TCase *TCase_tcp_send_empty = tcase_create("Unit test for tcp_send_empty");
TCase *TCase_tcp_send_probe = tcase_create("Unit test for tcp_send_probe");
TCase *TCase_tcp_send_rst = tcase_create("Unit test for tcp_send_rst");
TCase *TCase_tcp_nosync_rst = tcase_create("Unit test for tcp_nosync_rst");
TCase *TCase_tcp_sack_prepare = tcase_create("Unit test for tcp_sack_prepare");
TCase *TCase_tcp_data_in = tcase_create("Unit test for tcp_data_in");
TCase *TCase_tcp_ack_advance_una = tcase_create("Unit test for tcp_ack_advance_una");
TCase *TCase_time_diff = tcase_create("Unit test for time_diff");
TCase *TCase_tcp_rtt = tcase_create("Unit test for tcp_rtt");
TCase *TCase_tcp_congestion_control = tcase_create("Unit test for tcp_congestion_control");
TCase *TCase_add_retransmission_timer = tcase_create("Unit test for add_retransmission_timer");
TCase *TCase_tcp_first_timeout = tcase_create("Unit test for tcp_first_timeout");
TCase *TCase_tcp_rto_xmit = tcase_create("Unit test for tcp_rto_xmit");
TCase *TCase_tcp_next_zerowindow_probe = tcase_create("Unit test for tcp_next_zerowindow_probe");
TCase *TCase_tcp_is_allowed_to_send = tcase_create("Unit test for tcp_is_allowed_to_send");
TCase *TCase_tcp_retrans_timeout = tcase_create("Unit test for tcp_retrans_timeout");
TCase *TCase_tcp_retrans = tcase_create("Unit test for tcp_retrans");
TCase *TCase_tcp_ack_dbg = tcase_create("Unit test for tcp_ack_dbg");
TCase *TCase_tcp_ack = tcase_create("Unit test for tcp_ack");
TCase *TCase_tcp_finwaitack = tcase_create("Unit test for tcp_finwaitack");
TCase *TCase_tcp_deltcb = tcase_create("Unit test for tcp_deltcb");
TCase *TCase_tcp_finwaitfin = tcase_create("Unit test for tcp_finwaitfin");
TCase *TCase_tcp_closewaitack = tcase_create("Unit test for tcp_closewaitack");
TCase *TCase_tcp_lastackwait = tcase_create("Unit test for tcp_lastackwait");
TCase *TCase_tcp_syn = tcase_create("Unit test for tcp_syn");
TCase *TCase_tcp_set_init_point = tcase_create("Unit test for tcp_set_init_point");
TCase *TCase_tcp_synack = tcase_create("Unit test for tcp_synack");
TCase *TCase_tcp_first_ack = tcase_create("Unit test for tcp_first_ack");
TCase *TCase_tcp_closewait = tcase_create("Unit test for tcp_closewait");
TCase *TCase_tcp_fin = tcase_create("Unit test for tcp_fin");
TCase *TCase_tcp_rcvfin = tcase_create("Unit test for tcp_rcvfin");
TCase *TCase_tcp_finack = tcase_create("Unit test for tcp_finack");
TCase *TCase_tcp_force_closed = tcase_create("Unit test for tcp_force_closed");
TCase *TCase_tcp_wakeup_pending = tcase_create("Unit test for tcp_wakeup_pending");
TCase *TCase_tcp_rst = tcase_create("Unit test for tcp_rst");
TCase *TCase_tcp_halfopencon = tcase_create("Unit test for tcp_halfopencon");
TCase *TCase_tcp_closeconn = tcase_create("Unit test for tcp_closeconn");
TCase *TCase_invalid_flags = tcase_create("Unit test for invalid_flags");
TCase *TCase_checkLocalClosing = tcase_create("Unit test for checkLocalClosing");
TCase *TCase_checkRemoteClosing = tcase_create("Unit test for checkRemoteClosing");
tcase_add_test(TCase_input_segment_compare, tc_input_segment_compare);
suite_add_tcase(s, TCase_input_segment_compare);
tcase_add_test(TCase_tcp_input_segment, tc_tcp_input_segment);
suite_add_tcase(s, TCase_tcp_input_segment);
tcase_add_test(TCase_segment_compare, tc_segment_compare);
suite_add_tcase(s, TCase_segment_compare);
tcase_add_test(TCase_tcp_discard_all_segments, tc_tcp_discard_all_segments);
suite_add_tcase(s, TCase_tcp_discard_all_segments);
tcase_add_test(TCase_release_until, tc_release_until);
suite_add_tcase(s, TCase_release_until);
tcase_add_test(TCase_release_all_until, tc_release_all_until);
suite_add_tcase(s, TCase_release_all_until);
tcase_add_test(TCase_tcp_send_fin, tc_tcp_send_fin);
suite_add_tcase(s, TCase_tcp_send_fin);
tcase_add_test(TCase_pico_tcp_process_out, tc_pico_tcp_process_out);
suite_add_tcase(s, TCase_pico_tcp_process_out);
tcase_add_test(TCase_pico_paws, tc_pico_paws);
suite_add_tcase(s, TCase_pico_paws);
tcase_add_test(TCase_tcp_add_options, tc_tcp_add_options);
suite_add_tcase(s, TCase_tcp_add_options);
tcase_add_test(TCase_tcp_options_size_frame, tc_tcp_options_size_frame);
suite_add_tcase(s, TCase_tcp_options_size_frame);
tcase_add_test(TCase_tcp_add_options_frame, tc_tcp_add_options_frame);
suite_add_tcase(s, TCase_tcp_add_options_frame);
tcase_add_test(TCase_tcp_send_ack, tc_tcp_send_ack);
suite_add_tcase(s, TCase_tcp_send_ack);
tcase_add_test(TCase_tcp_set_space, tc_tcp_set_space);
suite_add_tcase(s, TCase_tcp_set_space);
tcase_add_test(TCase_tcp_options_size, tc_tcp_options_size);
suite_add_tcase(s, TCase_tcp_options_size);
tcase_add_test(TCase_tcp_process_sack, tc_tcp_process_sack);
suite_add_tcase(s, TCase_tcp_process_sack);
tcase_add_test(TCase_tcp_rcv_sack, tc_tcp_rcv_sack);
suite_add_tcase(s, TCase_tcp_rcv_sack);
tcase_add_test(TCase_tcp_parse_options, tc_tcp_parse_options);
suite_add_tcase(s, TCase_tcp_parse_options);
tcase_add_test(TCase_tcp_send, tc_tcp_send);
suite_add_tcase(s, TCase_tcp_send);
tcase_add_test(TCase_sock_stats, tc_sock_stats);
suite_add_tcase(s, TCase_sock_stats);
tcase_add_test(TCase_initconn_retry, tc_initconn_retry);
suite_add_tcase(s, TCase_initconn_retry);
tcase_add_test(TCase_tcp_send_synack, tc_tcp_send_synack);
suite_add_tcase(s, TCase_tcp_send_synack);
tcase_add_test(TCase_tcp_send_empty, tc_tcp_send_empty);
suite_add_tcase(s, TCase_tcp_send_empty);
tcase_add_test(TCase_tcp_send_probe, tc_tcp_send_probe);
suite_add_tcase(s, TCase_tcp_send_probe);
tcase_add_test(TCase_tcp_send_rst, tc_tcp_send_rst);
suite_add_tcase(s, TCase_tcp_send_rst);
tcase_add_test(TCase_tcp_nosync_rst, tc_tcp_nosync_rst);
suite_add_tcase(s, TCase_tcp_nosync_rst);
tcase_add_test(TCase_tcp_sack_prepare, tc_tcp_sack_prepare);
suite_add_tcase(s, TCase_tcp_sack_prepare);
tcase_add_test(TCase_tcp_data_in, tc_tcp_data_in);
suite_add_tcase(s, TCase_tcp_data_in);
tcase_add_test(TCase_tcp_ack_advance_una, tc_tcp_ack_advance_una);
suite_add_tcase(s, TCase_tcp_ack_advance_una);
tcase_add_test(TCase_time_diff, tc_time_diff);
suite_add_tcase(s, TCase_time_diff);
tcase_add_test(TCase_tcp_rtt, tc_tcp_rtt);
suite_add_tcase(s, TCase_tcp_rtt);
tcase_add_test(TCase_tcp_congestion_control, tc_tcp_congestion_control);
suite_add_tcase(s, TCase_tcp_congestion_control);
tcase_add_test(TCase_add_retransmission_timer, tc_add_retransmission_timer);
suite_add_tcase(s, TCase_add_retransmission_timer);
tcase_add_test(TCase_tcp_first_timeout, tc_tcp_first_timeout);
suite_add_tcase(s, TCase_tcp_first_timeout);
tcase_add_test(TCase_tcp_rto_xmit, tc_tcp_rto_xmit);
suite_add_tcase(s, TCase_tcp_rto_xmit);
tcase_add_test(TCase_tcp_next_zerowindow_probe, tc_tcp_next_zerowindow_probe);
suite_add_tcase(s, TCase_tcp_next_zerowindow_probe);
tcase_add_test(TCase_tcp_is_allowed_to_send, tc_tcp_is_allowed_to_send);
suite_add_tcase(s, TCase_tcp_is_allowed_to_send);
tcase_add_test(TCase_tcp_retrans_timeout, tc_tcp_retrans_timeout);
suite_add_tcase(s, TCase_tcp_retrans_timeout);
tcase_add_test(TCase_tcp_retrans, tc_tcp_retrans);
suite_add_tcase(s, TCase_tcp_retrans);
tcase_add_test(TCase_tcp_ack_dbg, tc_tcp_ack_dbg);
suite_add_tcase(s, TCase_tcp_ack_dbg);
tcase_add_test(TCase_tcp_ack, tc_tcp_ack);
suite_add_tcase(s, TCase_tcp_ack);
tcase_add_test(TCase_tcp_finwaitack, tc_tcp_finwaitack);
suite_add_tcase(s, TCase_tcp_finwaitack);
tcase_add_test(TCase_tcp_deltcb, tc_tcp_deltcb);
suite_add_tcase(s, TCase_tcp_deltcb);
tcase_add_test(TCase_tcp_finwaitfin, tc_tcp_finwaitfin);
suite_add_tcase(s, TCase_tcp_finwaitfin);
tcase_add_test(TCase_tcp_closewaitack, tc_tcp_closewaitack);
suite_add_tcase(s, TCase_tcp_closewaitack);
tcase_add_test(TCase_tcp_lastackwait, tc_tcp_lastackwait);
suite_add_tcase(s, TCase_tcp_lastackwait);
tcase_add_test(TCase_tcp_syn, tc_tcp_syn);
suite_add_tcase(s, TCase_tcp_syn);
tcase_add_test(TCase_tcp_set_init_point, tc_tcp_set_init_point);
suite_add_tcase(s, TCase_tcp_set_init_point);
tcase_add_test(TCase_tcp_synack, tc_tcp_synack);
suite_add_tcase(s, TCase_tcp_synack);
tcase_add_test(TCase_tcp_first_ack, tc_tcp_first_ack);
suite_add_tcase(s, TCase_tcp_first_ack);
tcase_add_test(TCase_tcp_closewait, tc_tcp_closewait);
suite_add_tcase(s, TCase_tcp_closewait);
tcase_add_test(TCase_tcp_fin, tc_tcp_fin);
suite_add_tcase(s, TCase_tcp_fin);
tcase_add_test(TCase_tcp_rcvfin, tc_tcp_rcvfin);
suite_add_tcase(s, TCase_tcp_rcvfin);
tcase_add_test(TCase_tcp_finack, tc_tcp_finack);
suite_add_tcase(s, TCase_tcp_finack);
tcase_add_test(TCase_tcp_force_closed, tc_tcp_force_closed);
suite_add_tcase(s, TCase_tcp_force_closed);
tcase_add_test(TCase_tcp_wakeup_pending, tc_tcp_wakeup_pending);
suite_add_tcase(s, TCase_tcp_wakeup_pending);
tcase_add_test(TCase_tcp_rst, tc_tcp_rst);
suite_add_tcase(s, TCase_tcp_rst);
tcase_add_test(TCase_tcp_halfopencon, tc_tcp_halfopencon);
suite_add_tcase(s, TCase_tcp_halfopencon);
tcase_add_test(TCase_tcp_closeconn, tc_tcp_closeconn);
suite_add_tcase(s, TCase_tcp_closeconn);
tcase_add_test(TCase_invalid_flags, tc_invalid_flags);
suite_add_tcase(s, TCase_invalid_flags);
tcase_add_test(TCase_checkLocalClosing, tc_checkLocalClosing);
suite_add_tcase(s, TCase_checkLocalClosing);
tcase_add_test(TCase_checkRemoteClosing, tc_checkRemoteClosing);
suite_add_tcase(s, TCase_checkRemoteClosing);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,375 @@
#include <pico_defines.h>
#include <pico_stack.h>
#include <pico_socket.h>
#include <pico_tftp.h>
#include "modules/pico_tftp.c"
#include "check.h"
Suite *pico_suite(void);
int tftp_user_cb(struct pico_tftp_session *session, uint16_t err, uint8_t *block, int32_t len, void *arg);
/* MOCKS */
static int called_pico_socket_close = 0;
static uint16_t expected_opcode = 0;
static int called_user_cb = 0;
static int called_sendto = 0;
static uint32_t called_pico_timer_add = 0;
static int called_pico_timer_cancel = 0;
static struct pico_socket example_socket;
static struct pico_tftp_session example_session;
int pico_socket_close(struct pico_socket *s)
{
fail_if(s != example_session.socket);
called_pico_socket_close++;
return 0;
}
int pico_socket_sendto(struct pico_socket *s, const void *buf, const int len, void *dst, uint16_t remote_port)
{
const struct pico_tftp_hdr *h = (const struct pico_tftp_hdr *)buf;
fail_if(s != &example_socket);
fail_if(short_be(h->opcode) != expected_opcode);
fail_if(len <= 0);
(void)dst;
(void)remote_port;
called_sendto++;
return 0;
}
int tftp_user_cb(struct pico_tftp_session *session, uint16_t err, uint8_t *block, int32_t len, void *arg)
{
(void)session;
(void)err;
(void)block;
(void)len;
(void)arg;
called_user_cb++;
return 0;
}
uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
{
(void)expire;
(void)timer;
(void)arg;
return ++called_pico_timer_add;
}
void pico_timer_cancel(uint32_t t)
{
(void)t;
called_pico_timer_cancel++;
}
/* TESTS */
/* START_TEST(tc_check_opcode) */
/* { */
/* / * TODO: test this: static int check_opcode(struct pico_tftp_hdr *th) * / */
/* struct pico_tftp_hdr th; */
/* th.opcode = 0; */
/* fail_unless(check_opcode(&th) == -1); */
/* th.opcode = short_be(PICO_TFTP_RRQ); */
/* fail_unless(check_opcode(&th) == 0); */
/* th.opcode = short_be(0xFF); */
/* fail_unless(check_opcode(&th) == -1); */
/* } */
/* END_TEST */
START_TEST(tc_find_session_by_socket)
{
tftp_sessions = (struct pico_tftp_session *)PICO_ZALLOC(sizeof(struct pico_tftp_session));
tftp_sessions->socket = &example_socket;
tftp_sessions->next = (struct pico_tftp_session *)PICO_ZALLOC(sizeof(struct pico_tftp_session));
tftp_sessions->socket = NULL;
tftp_sessions->next = NULL;
fail_if(find_session_by_socket(&example_socket) != tftp_sessions->next);
}
END_TEST
START_TEST(tc_tftp_finish)
{
tftp_sessions = 0;
/* Test case: client */
example_session.socket = &example_socket;
called_pico_socket_close = 0;
tftp_finish(&example_session);
fail_if(!called_pico_socket_close);
/* Test eval_finish() len is 5*/
example_session.socket = &example_socket;
called_pico_socket_close = 0;
tftp_eval_finish(&example_session, 5);
fail_if(example_session.state != TFTP_STATE_CLOSING);
fail_if(!called_pico_socket_close);
/* Test eval_finish() len is PICO_TFTP_TOTAL_BLOCK_SIZE */
example_session.socket = &example_socket;
called_pico_socket_close = 0;
tftp_eval_finish(&example_session, PICO_TFTP_TOTAL_BLOCK_SIZE);
fail_if(called_pico_socket_close);
}
END_TEST
START_TEST(tc_tftp_send_ack)
{
example_session.socket = &example_socket;
#ifdef PICO_FAULTY
/* send_ack must not segfault when out of memory */
pico_set_mm_failure(1);
tftp_send_ack(&example_session);
fail_if(called_sendto > 0);
#endif
expected_opcode = PICO_TFTP_ACK;
tftp_send_ack(&example_session);
fail_if(called_sendto < 1);
}
END_TEST
START_TEST(tc_tftp_send_req)
{
/* Not needed. The tftp_send_rx_req and tftp_send_tx_req cover this. */
}
END_TEST
START_TEST(tc_tftp_send_rx_req)
{
char filename[14] = "some filename";
example_session.socket = &example_socket;
called_user_cb = 0;
called_pico_socket_close = 0;
called_sendto = 0;
#ifdef PICO_FAULTY
example_session.callback = tftp_user_cb;
/* send_req must call error cb when out of memory */
pico_set_mm_failure(1);
tftp_send_rx_req(&example_session, NULL, 0, filename);
fail_if(called_user_cb < 1);
fail_if(called_sendto > 0);
#endif
expected_opcode = PICO_TFTP_RRQ;
tftp_send_rx_req(&example_session, NULL, 0, NULL);
fail_if(called_sendto > 0); /* Calling with filename = NULL: not good */
tftp_send_rx_req(&example_session, NULL, 0, filename);
fail_if(called_sendto < 0);
}
END_TEST
START_TEST(tc_tftp_send_tx_req)
{
char filename[14] = "some filename";
example_session.socket = &example_socket;
called_user_cb = 0;
called_pico_socket_close = 0;
called_sendto = 0;
#ifdef PICO_FAULTY
example_session.callback = tftp_user_cb;
/* send_req must call error cb when out of memory */
pico_set_mm_failure(1);
tftp_send_tx_req(&example_session, NULL, 0, filename);
fail_if(called_user_cb < 1);
fail_if(called_sendto > 0);
#endif
expected_opcode = PICO_TFTP_WRQ;
tftp_send_tx_req(&example_session, NULL, 0, NULL);
fail_if(called_sendto > 0); /* Calling with filename = NULL: not good */
tftp_send_tx_req(&example_session, NULL, 0, filename);
fail_if(called_sendto < 0);
}
END_TEST
START_TEST(tc_tftp_send_error)
{
char longtext[1024];
example_session.socket = &example_socket;
called_user_cb = 0;
called_pico_socket_close = 0;
/* Sending empty msg */
called_sendto = 0;
expected_opcode = PICO_TFTP_ERROR;
tftp_send_error(&example_session, NULL, 0, 0, NULL);
fail_if(called_sendto < 1);
/* Sending some msg */
called_sendto = 0;
expected_opcode = PICO_TFTP_ERROR;
tftp_send_error(&example_session, NULL, 0, 0, "some text here");
fail_if(called_sendto < 1);
/* sending some very long msg */
memset(longtext, 'a', 1023);
longtext[1023] = (char)0;
called_sendto = 0;
expected_opcode = PICO_TFTP_ERROR;
tftp_send_error(&example_session, NULL, 0, 0, longtext);
fail_if(called_sendto < 1);
}
END_TEST
START_TEST(tc_tftp_send_data)
{
example_session.state = 0;
example_session.socket = &example_socket;
called_sendto = 0;
expected_opcode = PICO_TFTP_DATA;
tftp_send_data(&example_session, (const uint8_t*)"buffer", strlen("buffer"));
fail_if(called_sendto < 1);
fail_if(example_session.state != TFTP_STATE_WAIT_LAST_ACK);
}
END_TEST
START_TEST(tc_pico_tftp_abort)
{
int ret;
server.listen_socket = NULL;
/*first case: no session and no listening socket*/
ret = pico_tftp_abort(NULL, TFTP_ERR_EUSR, "test");
fail_if(ret != -1);
/*second case: no session but listening socket*/
server.listen_socket = example_session.socket = &example_socket;
pico_tftp_abort(NULL, TFTP_ERR_EUSR, "test");
fail_if(ret != -1);
/*tirdh case: session non into list*/
ret = pico_tftp_abort(&example_session, TFTP_ERR_EUSR, "test");
fail_if(ret != -1);
}
END_TEST
/* Receiving functions */
START_TEST(tc_tftp_data)
{
/* TODO: test this: static void tftp_data(uint8_t *block, uint32_t len, union pico_address *a, uint16_t port) */
}
END_TEST
START_TEST(tc_tftp_ack)
{
/* TODO: test this: static void tftp_ack(uint8_t *block, uint32_t len, union pico_address *a, uint16_t port) */
}
END_TEST
START_TEST(tc_tftp_timeout)
{
/* TODO: test this: static void tftp_timeout(pico_time t) */
}
END_TEST
START_TEST(tc_tftp_req)
{
/* TODO: test this: static void tftp_req(uint8_t *block, uint32_t len, union pico_address *a, uint16_t port) */
}
END_TEST
START_TEST(tc_tftp_data_err)
{
/* TODO: test this: static void tftp_data_err(uint8_t *block, uint32_t len, union pico_address *a, uint16_t port) */
}
END_TEST
START_TEST(tc_tftp_fsm_timeout)
{
/* TODO: test this: static void tftp_fsm_timeout(pico_time now, void *arg) */
}
END_TEST
START_TEST(tc_tftp_receive)
{
/* TODO: test this: static void tftp_receive(uint8_t *block, uint32_t r, union pico_address *a, uint16_t port) */
}
END_TEST
START_TEST(tc_tftp_cb)
{
/* TODO: test this: static void tftp_cb(uint16_t ev, struct pico_socket *s) */
}
END_TEST
START_TEST(tc_tftp_socket_open)
{
/* TODO: test this: static int tftp_socket_open(uint16_t family, union pico_address *a, uint16_t port) */
fail_if(tftp_socket_open(0xFFFF, 21) != NULL);
fail_if(tftp_socket_open(0xFFFF, 0xFFFF) != NULL);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("PicoTCP");
/* TCase *TCase_check_opcode = tcase_create("Unit test for check_opcode"); */
TCase *TCase_find_session_by_socket = tcase_create("Unit test for find_session_by_socket");
TCase *TCase_tftp_finish = tcase_create("Unit test for tftp_finish");
TCase *TCase_tftp_send_ack = tcase_create("Unit test for tftp_send_ack");
TCase *TCase_tftp_send_req = tcase_create("Unit test for tftp_send_req");
TCase *TCase_tftp_send_rx_req = tcase_create("Unit test for tftp_send_rx_req");
TCase *TCase_tftp_send_tx_req = tcase_create("Unit test for tftp_send_tx_req");
TCase *TCase_tftp_send_error = tcase_create("Unit test for tftp_send_error");
TCase *TCase_tftp_send_data = tcase_create("Unit test for tftp_send_data");
TCase *Tcase_pico_tftp_abort = tcase_create("Unit test for pico_tftp_abort");
TCase *TCase_tftp_data = tcase_create("Unit test for tftp_data");
TCase *TCase_tftp_ack = tcase_create("Unit test for tftp_ack");
TCase *TCase_tftp_timeout = tcase_create("Unit test for tftp_timeout");
TCase *TCase_tftp_req = tcase_create("Unit test for tftp_req");
TCase *TCase_tftp_data_err = tcase_create("Unit test for tftp_data_err");
TCase *TCase_tftp_fsm_timeout = tcase_create("Unit test for tftp_fsm_timeout");
TCase *TCase_tftp_receive = tcase_create("Unit test for tftp_receive");
TCase *TCase_tftp_cb = tcase_create("Unit test for tftp_cb");
TCase *TCase_tftp_socket_open = tcase_create("Unit test for tftp_socket_open");
/* tcase_add_test(TCase_check_opcode, tc_check_opcode); */
/* suite_add_tcase(s, TCase_check_opcode); */
tcase_add_test(TCase_find_session_by_socket, tc_find_session_by_socket);
suite_add_tcase(s, TCase_find_session_by_socket);
tcase_add_test(TCase_tftp_finish, tc_tftp_finish);
suite_add_tcase(s, TCase_tftp_finish);
tcase_add_test(TCase_tftp_send_ack, tc_tftp_send_ack);
suite_add_tcase(s, TCase_tftp_send_ack);
tcase_add_test(TCase_tftp_send_req, tc_tftp_send_req);
suite_add_tcase(s, TCase_tftp_send_req);
tcase_add_test(TCase_tftp_send_rx_req, tc_tftp_send_rx_req);
suite_add_tcase(s, TCase_tftp_send_rx_req);
tcase_add_test(TCase_tftp_send_tx_req, tc_tftp_send_tx_req);
suite_add_tcase(s, TCase_tftp_send_tx_req);
tcase_add_test(TCase_tftp_send_error, tc_tftp_send_error);
suite_add_tcase(s, TCase_tftp_send_error);
tcase_add_test(TCase_tftp_send_data, tc_tftp_send_data);
suite_add_tcase(s, TCase_tftp_send_data);
tcase_add_test(TCase_tftp_data, tc_tftp_data);
suite_add_tcase(s, Tcase_pico_tftp_abort);
tcase_add_test(Tcase_pico_tftp_abort, tc_pico_tftp_abort);
suite_add_tcase(s, TCase_tftp_data);
tcase_add_test(TCase_tftp_ack, tc_tftp_ack);
suite_add_tcase(s, TCase_tftp_ack);
tcase_add_test(TCase_tftp_timeout, tc_tftp_timeout);
suite_add_tcase(s, TCase_tftp_timeout);
tcase_add_test(TCase_tftp_req, tc_tftp_req);
suite_add_tcase(s, TCase_tftp_req);
tcase_add_test(TCase_tftp_data_err, tc_tftp_data_err);
suite_add_tcase(s, TCase_tftp_data_err);
tcase_add_test(TCase_tftp_fsm_timeout, tc_tftp_fsm_timeout);
suite_add_tcase(s, TCase_tftp_fsm_timeout);
tcase_add_test(TCase_tftp_receive, tc_tftp_receive);
suite_add_tcase(s, TCase_tftp_receive);
tcase_add_test(TCase_tftp_cb, tc_tftp_cb);
suite_add_tcase(s, TCase_tftp_cb);
tcase_add_test(TCase_tftp_socket_open, tc_tftp_socket_open);
suite_add_tcase(s, TCase_tftp_socket_open);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,84 @@
#include "pico_frame.h"
#include "pico_queue.h"
#include "stack/pico_frame.c"
#include "pico_stack.h"
#include "check.h"
Suite *pico_suite(void);
struct pico_queue q1 = {
0
}, q2 = {
0
};
START_TEST(tc_q)
{
struct pico_frame *f0 = pico_frame_alloc(100);
struct pico_frame *f1 = pico_frame_alloc(100);
struct pico_frame *f2 = pico_frame_alloc(100);
struct pico_frame *f3 = pico_frame_alloc(100);
struct pico_frame *f4 = pico_frame_alloc(100);
pico_queue_protect(&q1);
q1.max_frames = 4;
q2.max_size = 4 * 100;
fail_if (pico_enqueue(&q1, pico_frame_copy(f0)) < 0);
fail_if (pico_enqueue(&q1, pico_frame_copy(f1)) < 0);
fail_if (pico_enqueue(&q1, pico_frame_copy(f2)) < 0);
fail_if (pico_enqueue(&q1, pico_frame_copy(f3)) < 0);
fail_if (pico_enqueue(&q1, pico_frame_copy(f4)) >= 0);
fail_if (pico_enqueue(&q2, pico_frame_copy(f0)) < 0);
fail_if (pico_enqueue(&q2, pico_frame_copy(f1)) < 0);
fail_if (pico_enqueue(&q2, pico_frame_copy(f2)) < 0);
fail_if (pico_enqueue(&q2, pico_frame_copy(f3)) < 0);
fail_if (pico_enqueue(&q2, pico_frame_copy(f4)) >= 0);
fail_if((pico_dequeue(&q1))->buffer != f0->buffer);
fail_if((pico_dequeue(&q1))->buffer != f1->buffer);
fail_if((pico_dequeue(&q1))->buffer != f2->buffer);
fail_if((pico_dequeue(&q1))->buffer != f3->buffer);
fail_if(pico_queue_peek(&q1) != NULL);
fail_if(pico_dequeue(&q1) != NULL);
fail_if(q1.size != 0);
fail_if(q1.frames != 0);
pico_queue_empty(&q2);
fail_if(q2.size != 0);
fail_if(q2.frames != 0);
fail_if(pico_queue_peek(&q2) != NULL);
fail_if(pico_dequeue(&q2) != NULL);
pico_queue_deinit(&q1);
pico_queue_deinit(&q2);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("Packet Queues");
TCase *TCase_q = tcase_create("Unit test for pico_queue.c");
tcase_add_test(TCase_q, tc_q);
suite_add_tcase(s, TCase_q);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,59 @@
#include "pico_tcp.c"
#include <check.h>
Suite *pico_suite(void);
START_TEST(tc_seq_compare)
{
uint32_t big_a = 0xFFFFFF0alu;
uint32_t big_b = 0xFFFFFF0blu;
uint32_t small_a = 0xalu;
uint32_t small_b = 0xblu;
uint32_t under_thresh = 0x7ffffffflu;
uint32_t over_thresh = 0x80000000lu;
uint32_t zero = 0lu;
fail_if(pico_seq_compare(small_a, small_b) >= 0);
fail_if(pico_seq_compare(small_b, small_a) <= 0);
fail_if(pico_seq_compare(over_thresh, under_thresh) <= 0);
fail_if(pico_seq_compare(under_thresh, over_thresh) >= 0);
fail_if(pico_seq_compare(small_a, big_b) <= 0);
fail_if(pico_seq_compare(big_b, small_a) >= 0);
fail_if(pico_seq_compare(small_a, zero) <= 0);
fail_if(pico_seq_compare(zero, small_a) >= 0);
fail_if(pico_seq_compare(big_a, zero) >= 0);
fail_if(pico_seq_compare(zero, big_a) <= 0);
fail_if(pico_seq_compare(big_a, big_b) >= 0);
fail_if(pico_seq_compare(big_b, big_a) <= 0);
fail_if(pico_seq_compare(big_a, big_a) != 0);
fail_if(pico_seq_compare(zero, zero) != 0);
}
END_TEST
Suite *pico_suite(void)
{
Suite *s = suite_create("pico tcp sequence numbers");
TCase *TCase_seq_compare = tcase_create("Unit test for pico_seq_compare");
tcase_add_test(TCase_seq_compare, tc_seq_compare);
suite_add_tcase(s, TCase_seq_compare);
return s;
}
int main(void)
{
int fails;
Suite *s = pico_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
fails = srunner_ntests_failed(sr);
srunner_free(sr);
return fails;
}

View File

@ -0,0 +1,213 @@
#include "pico_ethernet.c"
static struct pico_frame *init_frame(struct pico_device *dev)
{
struct pico_frame *f = pico_frame_alloc(PICO_SIZE_ETHHDR + PICO_SIZE_ARPHDR);
f->net_hdr = f->buffer + PICO_SIZE_ETHHDR;
f->datalink_hdr = f->buffer;
f->dev = dev;
return f;
}
START_TEST (arp_update_max_arp_reqs_test)
{
pico_stack_init();
max_arp_reqs = 0;
usleep((PICO_ARP_INTERVAL + 1) * 1000);
pico_stack_tick();
fail_unless(max_arp_reqs > 0);
max_arp_reqs = PICO_ARP_MAX_RATE;
usleep((PICO_ARP_INTERVAL + 1) * 1000);
pico_stack_tick();
fail_unless(max_arp_reqs == PICO_ARP_MAX_RATE);
}
END_TEST
START_TEST (arp_compare_test)
{
struct pico_arp a, b;
char ipstr[] = "192.168.1.1";
memset(&a, 0, sizeof(a));
pico_string_to_ipv4(ipstr, &b.ipv4.addr);
fail_unless(arp_compare(&a, &b) == -1);
fail_unless(arp_compare(&b, &a) == 1);
fail_unless(arp_compare(&a, &a) == 0);
}
END_TEST
START_TEST (arp_lookup_test)
{
struct pico_ip4 ip;
struct pico_eth *eth = NULL;
char ipstr[] = "192.168.1.1";
struct pico_arp entry;
eth = pico_arp_lookup(&ip);
fail_unless(eth == NULL);
pico_string_to_ipv4(ipstr, &ip.addr);
entry.ipv4 = ip;
pico_stack_init();
fail_unless(pico_arp_add_entry(&entry) == 0);
entry.arp_status = PICO_ARP_STATUS_STALE;
eth = pico_arp_lookup(&ip);
fail_unless(eth == NULL);
pico_tree_delete(&arp_tree, &entry);
}
END_TEST
START_TEST (arp_expire_test)
{
struct pico_arp entry;
entry.arp_status = PICO_ARP_STATUS_REACHABLE;
entry.timestamp = 0;
arp_expire(PICO_ARP_TIMEOUT, &entry);
fail_unless(entry.arp_status == PICO_ARP_STATUS_STALE);
}
END_TEST
START_TEST(tc_pico_arp_queue)
{
struct pico_ip4 addr = {
.addr = 0xaabbccdd
};
int i;
struct pico_frame *f = pico_frame_alloc(sizeof(struct pico_ipv4_hdr));
struct pico_ipv4_hdr *h = (struct pico_ipv4_hdr *) f->buffer;
fail_if(!f);
f->net_hdr = (uint8_t *)h;
h->dst.addr = addr.addr;
for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) {
fail_if(frames_queued[i] != NULL);
}
pico_arp_unreachable(&addr);
for (i = 0; i < PICO_ND_MAX_FRAMES_QUEUED; i++) {
fail_if(frames_queued[i] != NULL);
}
pico_arp_postpone(f);
fail_if(frames_queued[0]->buffer != f->buffer);
pico_arp_unreachable(&addr);
PICO_FREE(f);
}
END_TEST
START_TEST (arp_receive_test)
{
struct mock_device *mock;
struct pico_frame *f = NULL;
struct pico_arp_hdr *ah = NULL;
struct pico_eth_hdr *eh = NULL;
uint8_t macaddr1[6] = {
0, 0, 0, 0xa, 0xb, 0xf
};
uint8_t macaddr2[6] = {
0, 0, 0, 0xc, 0xd, 0xf
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 ip1 = {
.addr = long_be(0x0A2800AA)
};
struct pico_ip4 ip2 = {
.addr = long_be(0x0A2800AB)
};
pico_stack_init();
/* Create mock device */
mock = pico_mock_create(macaddr1);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_ipv4_link_add(mock->dev, ip1, netmask), "add link to mock device failed");
/* Normal ARP request */
f = init_frame(mock->dev);
fail_if(!f, "FRAME INIT failed");
eh = (struct pico_eth_hdr *) f->datalink_hdr;
ah = (struct pico_arp_hdr *) f->net_hdr;
memcpy(eh->saddr, macaddr2, PICO_SIZE_ETH);
memcpy(eh->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH);
eh->proto = PICO_IDETH_ARP;
ah->htype = PICO_ARP_HTYPE_ETH;
ah->ptype = PICO_IDETH_IPV4;
ah->hsize = PICO_SIZE_ETH;
ah->psize = PICO_SIZE_IP4;
ah->opcode = PICO_ARP_REQUEST;
memcpy(ah->s_mac, macaddr2, PICO_SIZE_ETH);
ah->src.addr = ip2.addr;
ah->dst.addr = ip1.addr;
fail_unless(pico_arp_receive(f) == 0);
/* net_hdr is a nullpointer */
f = init_frame(mock->dev);
fail_if(!f, "FRAME INIT failed");
f->net_hdr = NULL;
fail_unless(pico_arp_receive(f) == -1);
/* wrong hardware type */
f = init_frame(mock->dev);
fail_if(!f, "FRAME INIT failed");
ah = (struct pico_arp_hdr *) f->net_hdr;
ah->htype = 0;
fail_unless(pico_arp_receive(f) == -1);
/* wrong protocol type */
f = init_frame(mock->dev);
fail_if(!f, "FRAME INIT failed");
ah = (struct pico_arp_hdr *) f->net_hdr;
ah->ptype = 0;
fail_unless(pico_arp_receive(f) == -1);
/* source mac address is multicast */
f = init_frame(mock->dev);
fail_if(!f, "FRAME INIT failed");
ah = (struct pico_arp_hdr *) f->net_hdr;
ah->s_mac[0] = 0x01;
fail_unless(pico_arp_receive(f) == -1);
pico_ipv4_link_del(mock->dev, ip1);
}
END_TEST
START_TEST (arp_get_test)
{
struct pico_frame *f = NULL;
struct mock_device *mock;
struct pico_ipv4_hdr *hdr = NULL;
struct pico_eth *eth = NULL;
uint8_t macaddr[6] = {
0, 0, 0xa, 0xa, 0xb, 0xf
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 ip = {
.addr = long_be(0x0A28000B)
};
mock = pico_mock_create(macaddr);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_ipv4_link_add(mock->dev, ip, netmask), "add link to mock device failed");
f = pico_frame_alloc(PICO_SIZE_ETHHDR + sizeof(struct pico_ipv4_hdr));
f->net_hdr = f->start + PICO_SIZE_ETHHDR;
f->datalink_hdr = f->start;
f->dev = mock->dev;
hdr = (struct pico_ipv4_hdr *) f->net_hdr;
hdr->dst.addr = ip.addr;
eth = pico_arp_get(f);
fail_unless(eth == &mock->dev->eth->mac);
pico_ipv4_link_del(mock->dev, ip);
}
END_TEST

View File

@ -0,0 +1,554 @@
static struct pico_dhcp_client_cookie*dhcp_client_ptr;
void callback_dhcpclient(void*cli, int code);
int generate_dhcp_msg(uint8_t *buf, uint32_t *len, uint8_t type);
void callback_dhcpclient(void*cli, int code)
{
struct pico_ip4 gateway;
char gw_txt_addr[30];
IGNORE_PARAMETER(cli);
if(code == PICO_DHCP_SUCCESS) {
gateway = pico_dhcp_get_gateway(&dhcp_client_ptr);
pico_ipv4_to_string(gw_txt_addr, gateway.addr);
}
printf("callback happened with code %d!\n", code);
}
int generate_dhcp_msg(uint8_t *buf, uint32_t *len, uint8_t type)
{
if(type == DHCP_MSG_TYPE_DISCOVER) {
uint8_t buffer[] = {
0x01, 0x01, 0x06, 0x00, 0x0c, 0x10,
0x53, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x0a, 0x0b, 0x0f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x01, 0x37, 0x07, 0x01,
0x1c, 0x02, 0x03, 0x0c, 0x3a, 0x3b, 0x39, 0x02, 0x02, 0x40, 0xff, 0x00
};
*len = sizeof(buffer);
memcpy(&(buf[0]), buffer, *len);
}else if(type == DHCP_MSG_TYPE_OFFER) {
return 1;
}else if(type == DHCP_MSG_TYPE_REQUEST) {
uint32_t i = 0;
uint8_t buffer1[] = {
/* 0x63,0x82,0x53,0x63,// MAGIC COOCKIE */
/* 0x35,0x01,0x03, // DHCP REQUEST */
/* 0x36,0x04,0x00,0x00,0x00,0x00 // SERVER ID */
0x32, 0x04, buf[0x3a], buf[0x3b], buf[0x3c], buf[0x3e], /* requested ip */
0x37, 0x04, 0x01, 0x03, 0x06, 0x2a, /* Parameter list */
0x3d, 0x07, 0x01, buf[0x06], buf[0x07], buf[0x08], buf[0x09], buf[0x0a], buf[0x0b], /* Client id */
0xff
};
buf[0x02a] = 0x01; /* change to boot request */
buf[0x11c] = 0x03; /* request */
memcpy(&(buf[0x123]), &(buffer1[0]), sizeof(buffer1));
*len = sizeof(buffer1) + 0x123;
for(i = *len; i < 0x150; i++) {
buf[i + 10] = 0x00;
}
return 0;
}else if(type == DHCP_MSG_TYPE_ACK) {
return 1;
}
return 0;
}
START_TEST (test_dhcp_server_api)
{
/************************************************************************
* Check if dhcp recv works correctly if
* MAC address of client is not in arp table yet
* Status : Done
************************************************************************/
struct mock_device *mock;
uint8_t macaddr1[6] = {
0xc1, 0, 0, 0xa, 0xb, 0xf
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 serverip = {
.addr = long_be(0x0A28000A)
};
uint8_t buf[600] = {
0
};
/* Declaration test 1 */
struct pico_dhcp_server_setting s1 = {
0
};
/* Declaration test 2 */
struct pico_dhcp_server_setting s2 = {
0
};
printf("*********************** starting %s * \n", __func__);
/* Create mock device */
mock = pico_mock_create(macaddr1);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
fail_if(pico_ipv4_link_add(mock->dev, serverip, netmask), "add link to mock device failed");
/* test 0 */
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Test 0 statements */
fail_unless(pico_dhcp_server_initiate(NULL), "DHCP_SERVER> initiate succeeded after pointer to dev == NULL");
fail_unless(pico_err == PICO_ERR_EINVAL, "DHCP_SERVER> initiate succeeded without PICO_ERR_EINVAL after wrong parameter");
/* test 1 */
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Store data in settings */
s1.server_ip.addr = long_be(0x0A28000F); /* make sure this IP is not assigned */
/* Test 1 statements */
fail_unless(pico_dhcp_server_initiate(&s1), "DHCP_SERVER> initiate succeeded after pointer to dev == NULL");
fail_unless(pico_err == PICO_ERR_EINVAL, "DHCP_SERVER> initiate succeeded without PICO_ERR_EINVAL after wrong parameter");
/* test 2 */
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Store data in settings */
s2.server_ip = serverip;
/* Test 2 statements */
fail_if(pico_dhcp_server_initiate(&s2), "DHCP_SERVER> failed after correct parameter");
}
END_TEST
START_TEST (test_dhcp)
{
/************************************************************************
* Check if all states (offer, bound) are changed correctly
* and if response messages are replied correctly
* Status : Done
*************************************************************************/
struct mock_device*mock;
struct pico_dhcp_server_setting s = {
0
};
struct pico_ip4 xid = {
.addr = long_be(0x00003d1d)
};
uint8_t macaddr1[6] = {
0xc1, 0, 0, 0xa, 0xb, 0xf
};
uint8_t macaddr2[6] = {
0xc6, 0, 0, 0xa, 0xb, 0xf
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 serverip = {
.addr = long_be(0x0A28000A)
};
struct pico_socket sock = { };
struct pico_dhcp_server_negotiation *dn = NULL;
struct pico_ip4 *stored_ipv4 = NULL;
uint32_t len = 0;
int network_read = 0;
uint8_t *buf;
uint8_t printbufactive = 0;
buf = PICO_ZALLOC(600);
printf("*********************** starting %s * \n", __func__);
/*Insert custom values in buffer*/
fail_if(generate_dhcp_msg(buf, &len, DHCP_MSG_TYPE_DISCOVER), "DHCP_SERVER->failed to generate buffer");
memcpy(&(buf[4]), &(xid.addr), sizeof(struct pico_ip4));
memcpy(&(buf[28]), &(macaddr1[0]), sizeof(struct pico_ip4));
printbuf(&(buf[0]), len, "DHCP-DISCOVER packet", printbufactive);
/*Initiate test setup*/
pico_stack_init();
/* Create mock device */
mock = pico_mock_create(macaddr2);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
fail_if(pico_ipv4_link_add(mock->dev, serverip, netmask), "add link to mock device failed");
s.server_ip = serverip;
fail_if(pico_dhcp_server_initiate(&s), "DHCP_SERVER> server initiation failed");
dn = pico_dhcp_server_find_negotiation(xid.addr);
fail_unless(dn == NULL, "DCHP SERVER -> negotiation data available befor discover msg recvd");
/* simulate reception of a DISCOVER packet */
sock.local_addr.ip4 = serverip;
pico_dhcp_server_recv(&sock, buf, len);
tick_it(3);
/* check if negotiation data is stored */
dn = pico_dhcp_server_find_negotiation(xid.addr);
fail_if(dn == NULL, "DCHP SERVER -> no negotiation stored after discover msg recvd");
/* check if new ip is in ARP cache */
stored_ipv4 = pico_arp_reverse_lookup(&dn->hwaddr);
fail_if(stored_ipv4 == NULL, "DCHP SERVER -> new address is not inserted in ARP");
fail_unless(stored_ipv4->addr == dn->ciaddr.addr, "DCHP SERVER -> new ip not stored in negotiation data");
/* check if state is changed and reply is received */
network_read = pico_mock_network_read(mock, buf, BUFLEN);
fail_unless(network_read > 0, "received msg on network of %u bytes", network_read);
printbuf(&(buf[0]), (uint32_t)network_read, "DHCP-OFFER msg", printbufactive);
fail_unless(buf[0x011c] == 0x02, "No DHCP offer received after discovery");
fail_unless(dn->state == PICO_DHCP_STATE_OFFER, "DCHP SERVER -> negotiation state not changed to OFFER");
/*change offer to request*/
fail_if(generate_dhcp_msg(buf, &len, DHCP_MSG_TYPE_REQUEST), "DHCP_SERVER->failed to generate buffer");
printbuf(&(buf[0x2a]), len - 0x2a, "request buffer", printbufactive);
/* simulate reception of a offer packet */
pico_dhcp_server_recv(&sock, &(buf[0x2a]), len - 0x2a);
fail_unless(dn->state == PICO_DHCP_STATE_BOUND, "DCHP SERVER -> negotiation state not changed to BOUND");
tick_it(3);
/* check if state is changed and reply is received */
do {
network_read = pico_mock_network_read(mock, buf, BUFLEN);
} while (buf[0] == 0x33);
printf("Received message: %d bytes\n", network_read);
fail_unless(network_read > 0, "received msg on network of %d bytes", network_read);
printbuf(&(buf[0]), (uint32_t)network_read, "DHCP-ACK msg", printbufactive);
fail_unless(buf[0x11c] == 0x05, "No DHCP ACK received after discovery");
}
END_TEST
START_TEST (test_dhcp_server_ipninarp)
{
/************************************************************************
* Check if dhcp recv works correctly if
* MAC address of client is not in arp table yet
* Status : Done
*************************************************************************/
struct mock_device*mock;
struct pico_dhcp_server_setting s = {
0
};
struct pico_ip4 xid = {
.addr = long_be(0x00003d1d)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 serverip = {
.addr = long_be(0x0A28000A)
};
struct pico_socket sock = { };
struct pico_dhcp_server_negotiation *dn = NULL;
struct pico_ip4 *stored_ipv4 = NULL;
unsigned char macaddr1[6] = {
0xc1, 0, 0, 0xa, 0xb, 0xf
};
uint32_t len = 0;
uint8_t buf[600] = {
0
};
uint8_t printbufactive = 0;
printf("*********************** starting %s * \n", __func__);
/*Insert custom values in buffer*/
fail_if(generate_dhcp_msg(buf, &len, DHCP_MSG_TYPE_DISCOVER), "DHCP_SERVER->failed to generate buffer");
memcpy(&(buf[4]), &(xid.addr), sizeof(struct pico_ip4));
memcpy(&(buf[28]), &(macaddr1[0]), sizeof(struct pico_ip4));
printbuf(&(buf[0]), len, "DHCP-DISCOVER packet", printbufactive);
/*Initiate test setup*/
pico_stack_init();
/* Create mock device */
mock = pico_mock_create(macaddr1);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
fail_if(pico_ipv4_link_add(mock->dev, serverip, netmask), "add link to mock device failed");
s.server_ip = serverip;
fail_if(pico_dhcp_server_initiate(&s), "DHCP_SERVER> server initiation failed");
dn = pico_dhcp_server_find_negotiation(xid.addr);
fail_unless(dn == NULL, "DCHP SERVER -> negotiation data available before discover msg recvd");
/* simulate reception of a DISCOVER packet */
sock.local_addr.ip4 = serverip;
pico_dhcp_server_recv(&sock, buf, len);
/* check if negotiation data is stored */
dn = pico_dhcp_server_find_negotiation(xid.addr);
fail_if(dn == NULL, "DCHP SERVER -> no negotiation stored after discover msg recvd");
/* check if new ip is in ARP cache */
stored_ipv4 = pico_arp_reverse_lookup(&dn->hwaddr);
fail_if(stored_ipv4 == NULL, "DCHP SERVER -> new address is not inserted in ARP");
fail_unless(stored_ipv4->addr == dn->ciaddr.addr, "DCHP SERVER -> new ip not stored in negotiation data");
/* check if new ip is in ARP cache */
fail_if(pico_arp_reverse_lookup(&dn->hwaddr) == NULL, "DCHP SERVER -> new address is not inserted in ARP");
}
END_TEST
START_TEST (test_dhcp_server_ipinarp)
{
/************************************************************************
* Check if dhcp recv works correctly if
* MAC address of client is allready in arp table
* Status : Done
*************************************************************************/
struct mock_device*mock;
struct pico_dhcp_server_setting s = {
0
};
struct pico_ip4 ipv4address = {
.addr = long_be(0x0a280067)
};
struct pico_ip4 xid = {
.addr = long_be(0x00003d1d)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct pico_ip4 serverip = {
.addr = long_be(0x0A28000A)
};
struct pico_socket sock = { };
struct pico_ip4 *stored_ipv4 = NULL;
struct pico_dhcp_server_negotiation *dn = NULL;
struct pico_eth *arp_resp = NULL;
unsigned char macaddr1[6] = {
0xc1, 0, 0, 0xa, 0xb, 0xf
};
uint32_t len = 0;
uint8_t buf[600] = {
0
};
printf("*********************** starting %s * \n", __func__);
/*Insert custom values in buffer*/
fail_if(generate_dhcp_msg(buf, &len, DHCP_MSG_TYPE_DISCOVER), "DHCP_SERVER->failed to generate buffer");
memcpy(&(buf[28]), &(macaddr1[0]), sizeof(struct pico_ip4));
memcpy(&(buf[4]), &(xid.addr), sizeof(struct pico_ip4));
/* Create mock device */
mock = pico_mock_create(macaddr1);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_ipv4_link_add(mock->dev, serverip, netmask), "add link to mock device failed");
s.server_ip = serverip;
/*Initiate test setup*/
pico_stack_init();
pico_arp_create_entry(&(macaddr1[0]), ipv4address, s.dev);
fail_if(pico_dhcp_server_initiate(&s), "DHCP_SERVER> server initiation failed");
/* simulate reception of a DISCOVER packet */
sock.local_addr.ip4 = serverip;
pico_dhcp_server_recv(&sock, buf, len);
/* check if negotiation data is stored */
dn = pico_dhcp_server_find_negotiation(xid.addr);
fail_if(dn == NULL, "DCHP SERVER -> no negotiation stored after discover msg recvd");
/* check if new ip is in ARP cache */
stored_ipv4 = pico_arp_reverse_lookup(&dn->hwaddr);
fail_if(stored_ipv4 == NULL, "DCHP SERVER -> new address is not inserted in ARP");
fail_unless(stored_ipv4->addr == dn->ciaddr.addr, "DCHP SERVER -> new ip not stored in negotiation data");
/* check if new ip is in ARP cache */
arp_resp = pico_arp_lookup(&ipv4address);
fail_if(arp_resp == NULL, "DCHP SERVER -> address unavailable in arp cache");
}
END_TEST
#if 0
START_TEST (test_dhcp_client)
{
struct mock_device*mock;
uint32_t dhcp_hdr_offset = PICO_SIZE_ETHHDR + PICO_SIZE_IP4HDR + PICO_UDPHDR_SIZE;
unsigned char macaddr1[6] = {
0xc1, 0, 0, 0xa, 0xb, 0xf
};
struct pico_ip4 address = {
0
};
struct pico_ip4 yiaddr = {
.addr = long_be(0xC0A8000A)
};
struct pico_ip4 gateway = {
0
};
struct pico_ip4 router = {
.addr = long_be(0xC0A800FE)
};
uint8_t buf[BUFLEN] = {
0
};
uint8_t offer_buf1[] = {
0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8, 0x00, 0x01
};
uint8_t offer_buf2[] = {
0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, 0x3a, 0x04, 0x00, 0x00, 0x07, 0x08, 0x3b, 0x04, 0x00, 0x00, 0x0c, 0x4e, 0x33, 0x04, 0x00, 0x00, 0x0e, 0x10, 0x36, 0x04, 0xc0, 0xa8, 0x00, 0x01, 0xff
};
uint8_t routeropt_buf[] = {
PICO_DHCPOPT_ROUTER, 0x04, 0xC0, 0xA8, 0x00, 0xFE, 0xFF
};
int type = 0;
uint8_t printbufactive = 0;
uint32_t len = 0;
uint32_t xid = 0;
struct pico_dhcp_client_cookie *cli = NULL;
pico_stack_init();
/* Create mock device */
mock = pico_mock_create(macaddr1);
fail_if(!mock, "MOCK DEVICE creation failed");
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
/* initiate negotiation -> change state to */
pico_dhcp_initiate_negotiation(mock->dev, &callback_dhcpclient, &xid);
cli = get_cookie_by_xid(xid);
dhcp_client_ptr = cli;
fail_if(cli == NULL, "initiate fail");
fail_unless(cli->state == DHCPSTATE_DISCOVER, "Not in discover state after init negotiate");
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
/* push discover msg on network */
tick_it(3);
/* read discover message from network */
len = pico_mock_network_read(mock, buf, BUFLEN );
fail_unless(len, "No msg received on network!");
printbuf(&(buf[0]), len, "DHCP-DISCOVER packet", printbufactive);
fail_unless(buf[0x011c] == 0x01, "No DHCP Discover received after initiate negotiation");
mock_print_protocol(buf);
fail_if(pico_mock_network_read(mock, buf, BUFLEN), "data on network that shouldn't be there");
/* check API access functions */
address = pico_dhcp_get_address(cli);
fail_unless(address.addr == 0, "Client address gets value at init -> should get it from dhcp server");
gateway = pico_dhcp_get_gateway(cli);
fail_unless(gateway.addr == 0, "Gateway gets value at init -> should get it from dhcp server ");
/* Change received discovery msg to offer offer msg */
buf[0x2a] = 0x02;
memcpy(&(buf[0x3a]), &(offer_buf1[0]), sizeof(offer_buf1));
memcpy(&(buf[0x3a]), &(yiaddr.addr), sizeof(struct pico_ip4));
memcpy(&(buf[0x116]), &(offer_buf2[0]), sizeof(offer_buf2));
memcpy(&(buf[0x13b]), &(routeropt_buf[0]), sizeof(routeropt_buf));
memcpy(&(buf[0x13d]), &(router.addr), sizeof(struct pico_ip4));
printbuf(&(buf[dhcp_hdr_offset]), len - dhcp_hdr_offset, "DHCP-OFFER message", printbufactive);
/* generate dhcp type from msg */
type = pico_dhcp_verify_and_identify_type(&(buf[dhcp_hdr_offset]), len - dhcp_hdr_offset, cli);
fail_if(type == 0, "unkown DHCP type");
/* simulate reception of a DHCP server offer */
pico_dhcp_state_machine(type, cli, &(buf[dhcp_hdr_offset]), len - dhcp_hdr_offset);
fail_if(cli->state == DHCPSTATE_DISCOVER, "still in discover state after dhcp server offer");
fail_unless(cli->state == DHCPSTATE_REQUEST, "not in REQUEST state after dhcp server offer");
address = pico_dhcp_get_address(cli);
fail_unless(address.addr == yiaddr.addr, "Client address incorrect => yiaddr or pico_dhcp_get_address incorrect");
gateway = pico_dhcp_get_gateway(cli);
fail_unless(gateway.addr == router.addr, "Gateway incorrect! => routeroption or pico_dhcp_get_gateway incorrect");
tick_it(3);
len = pico_mock_network_read(mock, buf, BUFLEN);
fail_unless(len, "received msg on network of %d bytes", len);
printbuf(&(buf[0]), len, "DHCP-REQUEST packet", printbufactive);
fail_unless(buf[0x011c] == 0x03, "No DHCP request received after offer");
}
END_TEST
#endif
START_TEST (test_dhcp_client_api)
{
/************************************************************************
* Check API of pico_dhcp_initiate_negotiation
* Status : Done
************************************************************************/
/* Declaration test 0 */
uint32_t xid0 = 0;
struct pico_dhcp_client_cookie *cli0 = NULL;
/* Declaration test 1 */
uint32_t xid1 = 0;
struct pico_dhcp_client_cookie *cli1 = NULL;
printf("*********************** starting %s * \n", __func__);
/* test 0 */
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Test 0 statements */
pico_dhcp_initiate_negotiation(NULL, NULL, &xid0);
cli0 = pico_dhcp_client_find_cookie(xid0);
fail_unless(cli0 == NULL, "DHCP_CLIENT> initiate succeeded after pointer to dev == NULL");
fail_unless(pico_err == PICO_ERR_EINVAL, "DHCP_SERVER> initiate succeeded without PICO_ERR_EINVAL after wrong parameter");
/* test 1 */
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Test 1 statements */
pico_dhcp_initiate_negotiation(NULL, &callback_dhcpclient, &xid1);
cli1 = pico_dhcp_client_find_cookie(xid1);
fail_unless(cli1 == NULL, "DHCP_CLIENT> initiate succeeded after pointer to dev == NULL");
fail_unless(pico_err == PICO_ERR_EINVAL, "DHCP_SERVER> initiate succeeded without PICO_ERR_EINVAL after wrong parameter");
#if 0
/* not testable since we do not have a stub for the pico_socket_sendto */
/* Declaration test 2 */
uint32_t xid2 = 0;
struct pico_dhcp_client_cookie *cli2 = NULL;
struct pico_device *dev2;
struct mock_device *mock2 = NULL;
/* test 2 */
/* Create device */
dev2 = pico_null_create("dummy");
mock2 = pico_mock_create(NULL);
fail_if(mock2 == NULL, "No device created");
/* Clear error code */
pico_err = PICO_ERR_NOERR;
/* Test 2 statements */
xid2 = pico_dhcp_initiate_negotiation(dev2, &callback_dhcpclient);
cli2 = get_cookie_by_xid(xid2);
fail_if(cli2 == NULL, "DHCP_CLIENT: error initiating: %s", strerror(pico_err));
xid2 = pico_dhcp_initiate_negotiation(mock2->dev, &callback_dhcpclient);
cli2 = get_cookie_by_xid(xid2);
fail_if(cli2 == NULL, "DHCP_CLIENT: error initiating: %s", strerror(pico_err));
xid2 = pico_dhcp_initiate_negotiation(dev2, &callback_dhcpclient);
cli2 = get_cookie_by_xid(xid2);
fail_if(cli2 == NULL, "DHCP_CLIENT: error initiating: %s", strerror(pico_err));
#endif
}
END_TEST

View File

@ -0,0 +1,88 @@
void cb_dns(char *ip, void *arg);
void cb_dns(char *ip, void *arg)
{
if (!ip) {
/* Error occured */
printf("DNS error getaddr\n");
return;
}
/* Do something */
printf("DNS -> %s\n", ip);
PICO_FREE(ip);
if (arg)
PICO_FREE(arg);
}
START_TEST (test_dns)
{
int ret;
char url[] = "www.google.com";
char ip[] = "8.8.4.4";
struct pico_ip4 ns;
ns.addr = long_be(0x0a00280a); /* 10.40.0.10 */
pico_stack_init();
printf("START DNS TEST\n");
/* testing nameserver API */
ret = pico_dns_client_nameserver(NULL, PICO_DNS_NS_ADD);
fail_if(ret == 0, "dns> dns_client_nameserver add error");
ret = pico_dns_client_nameserver(NULL, PICO_DNS_NS_DEL);
fail_if(ret == 0, "dns> dns_client_nameserver del error");
ret = pico_dns_client_nameserver(NULL, 99);
fail_if(ret == 0, "dns> dns_client_nameserver wrong code");
ret = pico_dns_client_nameserver(NULL, 0xFF);
fail_if(ret == 0, "dns> dns_client_nameserver wrong code");
ret = pico_dns_client_nameserver(&ns, PICO_DNS_NS_DEL); /* delete non added ns */
fail_if(ret == 0, "dns> dns_client_nameserver del error");
ret = pico_dns_client_nameserver(&ns, 99);
fail_if(ret == 0, "dns> dns_client_nameserver wrong code");
ret = pico_dns_client_nameserver(&ns, PICO_DNS_NS_ADD); /* add correct one */
fail_if(ret < 0, "dns> dns_client_nameserver add error: %s", strerror(pico_err));
ret = pico_dns_client_nameserver(&ns, 99);
fail_if(ret == 0, "dns> dns_client_nameserver wrong code");
ret = pico_dns_client_nameserver(&ns, PICO_DNS_NS_DEL);
fail_if(ret < 0, "dns> dns_client_nameserver del error: %s", strerror(pico_err));
ret = pico_dns_client_nameserver(&ns, PICO_DNS_NS_ADD); /* add correct one */
fail_if(ret < 0, "dns> dns_client_nameserver add error: %s", strerror(pico_err));
ret = pico_dns_client_nameserver(&ns, PICO_DNS_NS_ADD); /* add correct one again */
fail_if(ret < 0, "dns> dns_client_nameserver add double failed");
/* testing getaddr API */
/* not testable since we do not have a stub for the pico_socket_send */
/* ret = pico_dns_client_getaddr(url, cb_dns, NULL); / * ask correct one * / */
/* fail_if(ret < 0, "dns> dns_client_getaddr: %s",strerror(pico_err)); */
ret = pico_dns_client_getaddr(NULL, cb_dns, NULL);
fail_if(ret == 0, "dns> dns_client_getaddr: no url");
ret = pico_dns_client_getaddr(url, NULL, NULL);
fail_if(ret == 0, "dns> dns_client_getaddr: no cb");
/* testing getname API */
/* not testable since we do not have a stub for the pico_socket_send */
/* ret = pico_dns_client_getname(ip, cb_dns, NULL); / * ask correct one * / */
/* fail_if(ret < 0, "dns> dns_client_getname: %s",strerror(pico_err)); */
ret = pico_dns_client_getname(NULL, cb_dns, NULL);
fail_if(ret == 0, "dns> dns_client_getname: no ip");
ret = pico_dns_client_getname(ip, NULL, NULL);
fail_if(ret == 0, "dns> dns_client_getname: no cb");
}
END_TEST

View File

@ -0,0 +1,401 @@
#include "pico_icmp4.h"
#define NUM_PING 1
int ping_test_var = 0;
void cb_ping(struct pico_icmp4_stats *s);
void icmp4_unreach_socket_cb(uint16_t ev, struct pico_socket *s);
void cb_ping(struct pico_icmp4_stats *s)
{
char host[30];
pico_ipv4_to_string(host, s->dst.addr);
if (s->err == 0) {
dbg("%lu bytes from %s: icmp_req=%lu ttl=64 time=%lu ms\n", s->size, host, s->seq, s->time);
if (s->seq == NUM_PING) {
ping_test_var++;
}
fail_if (s->seq > NUM_PING);
} else {
dbg("PING %lu to %s: Error %d\n", s->seq, host, s->err);
exit(1);
}
}
START_TEST (test_icmp4_ping)
{
struct pico_ip4 local = {
0
};
struct pico_ip4 remote = {
0
};
struct pico_ip4 netmask = {
0
};
struct mock_device *mock = NULL;
char local_address[] = {
"192.168.1.102"
};
char remote_address[] = {
"192.168.1.103"
};
uint16_t interval = 1000;
uint16_t timeout = 5000;
uint8_t size = 48;
int bufferlen = 80;
uint8_t buffer[bufferlen];
int len;
uint8_t temp_buf[4];
printf("*********************** starting %s * \n", __func__);
pico_string_to_ipv4(local_address, &(local.addr));
pico_string_to_ipv4("255.255.255.0", &(netmask.addr));
pico_string_to_ipv4(remote_address, &(remote.addr));
pico_string_to_ipv4("255.255.255.0", &(netmask.addr));
pico_stack_init();
mock = pico_mock_create(NULL);
fail_if(mock == NULL, "No device created");
pico_ipv4_link_add(mock->dev, local, netmask);
fail_if(pico_icmp4_ping(local_address, NUM_PING, interval, timeout, size, cb_ping) < 0);
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
fail_if(ping_test_var != 1);
pico_icmp4_ping(remote_address, NUM_PING, interval, timeout, size, cb_ping);
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
/* get the packet from the mock_device */
memset(buffer, 0, (size_t)bufferlen);
len = pico_mock_network_read(mock, buffer, bufferlen);
fail_if(len < 20);
/* inspect it */
fail_unless(mock_ip_protocol(mock, buffer, len) == 1);
fail_unless(mock_icmp_type(mock, buffer, len) == 8);
fail_unless(mock_icmp_code(mock, buffer, len) == 0);
fail_unless(pico_checksum(buffer + 20, (uint32_t)(len - 20)) == 0);
/* cobble up a reply */
buffer[20] = 0; /* type 0 : reply */
memcpy(temp_buf, buffer + 12, 4);
memcpy(buffer + 12, buffer + 16, 4);
memcpy(buffer + 16, temp_buf, 4);
/* using the mock-device because otherwise I have to put everything in a pico_frame correctly myself. */
pico_mock_network_write(mock, buffer, len);
/* check if it is received */
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
fail_unless(ping_test_var == 2);
/* repeat but make it an invalid reply... */
pico_icmp4_ping(remote_address, NUM_PING, interval, timeout, size, cb_ping);
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
/* get the packet from the mock_device */
memset(buffer, 0, (size_t)bufferlen);
len = pico_mock_network_read(mock, buffer, bufferlen);
/* inspect it */
fail_unless(mock_ip_protocol(mock, buffer, len) == 1);
fail_unless(mock_icmp_type(mock, buffer, len) == 8);
fail_unless(mock_icmp_code(mock, buffer, len) == 0);
fail_unless(pico_checksum(buffer + 20, (uint32_t)(len - 20)) == 0);
/* cobble up a reply */
buffer[20] = 0; /* type 0 : reply */
memcpy(temp_buf, buffer + 12, 4);
memcpy(buffer + 12, buffer + 16, 4);
memcpy(buffer + 16, temp_buf, 4);
buffer[26] = (uint8_t)~buffer[26]; /* flip some bits in the sequence number, to see if the packet gets ignored properly */
/* using the mock-device because otherwise I have to put everything in a pico_frame correctly myself. */
pico_mock_network_write(mock, buffer, len);
/* check if it is received */
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
fail_unless(ping_test_var == 2);
}
END_TEST
START_TEST (test_icmp4_incoming_ping)
{
int bufferlen = 76;
uint8_t buffer[76] = {
0x45, 0x00, 0x00, 0x4c,
0x91, 0xc3, 0x40, 0x00,
0x40, 0x01, 0x24, 0xd0,
0xc0, 0xa8, 0x01, 0x66,
0xc0, 0xa8, 0x01, 0x64,
0x08, 0x00, 0x66, 0x3c,
0x91, 0xc2, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
int buffer2len = 76;
int len;
int cntr = 0;
uint8_t buffer2[bufferlen];
struct pico_ip4 local = {
.addr = long_be(0xc0a80164)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct mock_device*mock;
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer;
printf("*********************** starting %s * \n", __func__);
pico_stack_init();
mock = pico_mock_create(NULL);
fail_if(mock == NULL, "No device created");
pico_ipv4_link_add(mock->dev, local, netmask);
hdr->crc = 0;
hdr->crc = short_be(pico_checksum(hdr, PICO_SIZE_IP4HDR));
pico_mock_network_write(mock, buffer, bufferlen);
/* check if it is received */
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, buffer2len);
/* inspect it */
while(cntr < len) {
printf("0x%02x ", buffer2[cntr]);
cntr++;
if(cntr % 4 == 0)
printf("\n");
}
fail_unless(len == buffer2len, "ping reply lenght does not match, expected len: %d, got: %d", buffer2len, len);
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 0);
fail_unless(mock_icmp_code(mock, buffer2, len) == 0);
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
}
END_TEST
START_TEST (test_icmp4_unreachable_send)
{
struct pico_ip4 local = {
.addr = long_be(0x0a280064)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct mock_device*mock;
int len = 0;
int bufferlen = 80;
uint8_t buffer2[bufferlen];
uint8_t buffer[32] = {
0x45, 0x00, 0x00, 0x20, 0x91, 0xc0, 0x40, 0x00,
0x40, 0x11, 0x94, 0xb4, 0x0a, 0x28, 0x00, 0x05,
0x0a, 0x28, 0x00, 0x04, 0x15, 0xb3, 0x15, 0xb3,
0x00, 0x0c, 0x00, 0x00, 'e', 'l', 'l', 'o'
};
/* fake packet with bad upper-layer-protocol */
uint8_t buffer3[20] = {
0x45, 0x00, 0x00, 0x14, 0x91, 0xc0, 0x40, 0x00,
0x40, 0xff, 0x94, 0xb4, 0x0a, 0x28, 0x00, 0x05,
0x0a, 0x28, 0x00, 0x04
};
struct pico_frame*f = PICO_ZALLOC(sizeof(struct pico_frame));
printf("*********************** starting %s * \n", __func__);
f->net_hdr = buffer;
f->buffer = buffer;
pico_stack_init();
mock = pico_mock_create(NULL);
fail_if(mock == NULL, "No device created");
pico_ipv4_link_add(mock->dev, local, netmask);
fail_if(pico_icmp4_dest_unreachable(f));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, bufferlen);
fail_unless(len == 56, "len is indeed %d\n", len);
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
fail_unless(mock_icmp_code(mock, buffer2, len) == 1); /* host unreachable */
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
fail_if(pico_icmp4_port_unreachable(f));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, bufferlen);
fail_unless(len == 56);
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
fail_unless(mock_icmp_code(mock, buffer2, len) == 3); /* port unreachable */
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
fail_if(pico_icmp4_proto_unreachable(f));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, bufferlen);
fail_unless(len == 56);
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
fail_unless(mock_icmp_code(mock, buffer2, len) == 2); /* proto unreachable */
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
fail_if(pico_icmp4_ttl_expired(f));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, bufferlen);
fail_unless(len == 56);
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 11); /* ttl expired */
fail_unless(mock_icmp_code(mock, buffer2, len) == 0);
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
f->net_hdr = buffer3;
f->buffer = buffer3;
fail_if(pico_icmp4_proto_unreachable(f));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
len = pico_mock_network_read(mock, buffer2, bufferlen);
fail_unless(len == 48); /* Buffer 3 is shorter, reply is shorter too... */
fail_unless(mock_ip_protocol(mock, buffer2, len) == 1);
fail_unless(mock_icmp_type(mock, buffer2, len) == 3); /* destination unreachable */
fail_unless(mock_icmp_code(mock, buffer2, len) == 2); /* proto unreachable */
fail_unless(pico_checksum(buffer2 + 20, (uint32_t)(len - 20)) == 0);
}
END_TEST
int icmp4_socket_unreach_status = 0;
void icmp4_unreach_socket_cb(uint16_t ev, struct pico_socket *s)
{
IGNORE_PARAMETER(s);
if (ev == PICO_SOCK_EV_ERR) {
icmp4_socket_unreach_status = 1;
}
}
START_TEST (test_icmp4_unreachable_recv)
{
struct pico_ip4 local = {
.addr = long_be(0x0a280064)
};
struct pico_ip4 remote = {
.addr = long_be(0x0a280065)
};
struct pico_ip4 netmask = {
.addr = long_be(0xffffff00)
};
struct mock_device*mock;
struct pico_socket*sock;
uint16_t port = short_be(7777);
/* put a host unreachable in the queue, run a few stack ticks */
uint8_t buffer[] = {
0x45, 0x00, 0x00, 0x20,
0x91, 0xc0, 0x40, 0x00,
0x40, 0x01, 0x94, 0xb4,
0x0a, 0x28, 0x00, 0x65,
0x0a, 0x28, 0x00, 0x64,
0x03, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
};
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer;
printf("*********************** starting %s * \n", __func__);
pico_stack_init();
mock = pico_mock_create(NULL);
fail_if(mock == NULL, "No device created");
pico_ipv4_link_add(mock->dev, local, netmask);
/* open a socket */
sock = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &icmp4_unreach_socket_cb);
fail_if(sock == NULL);
fail_if(pico_socket_bind(sock, &local, &port));
pico_socket_connect(sock, &remote, port);
pico_socket_write(sock, "fooo", 4);
/* see if my callback was called with the proper code */
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
/* filling in the IP header and first 8 bytes */
hdr->crc = 0;
hdr->crc = short_be(pico_checksum(hdr, PICO_SIZE_IP4HDR));
printf("read %d bytes\n", pico_mock_network_read(mock, buffer + 28, 28));
printf("wrote %d bytes\n", pico_mock_network_write(mock, buffer, 56));
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
fail_unless(icmp4_socket_unreach_status == 1);
}
END_TEST

View File

@ -0,0 +1,852 @@
START_TEST (test_ipv4)
{
#define IP_TST_SIZ 256
uint32_t i;
struct pico_device *dev[IP_TST_SIZ];
char devname[8];
struct pico_ip4 a[IP_TST_SIZ], d[IP_TST_SIZ], *source[IP_TST_SIZ], nm16, nm32, gw[IP_TST_SIZ], r[IP_TST_SIZ], ret;
struct pico_ipv4_link *l[IP_TST_SIZ];
char ipstr[] = "192.168.1.1";
struct pico_ip4 ipaddr;
struct pico_frame *f_NULL = NULL;
struct pico_ip4 *dst_NULL = NULL;
pico_stack_init();
nm16.addr = long_be(0xFFFF0000);
nm32.addr = long_be(0xFFFFFFFF);
/*link_add*/
for (i = 0; i < IP_TST_SIZ; i++) {
snprintf(devname, 8, "nul%d", i);
dev[i] = pico_null_create(devname);
a[i].addr = long_be(0x0a000001u + (i << 16));
d[i].addr = long_be(0x0a000002u + (i << 16));
fail_if(pico_ipv4_link_add(dev[i], a[i], nm16) != 0, "Error adding link");
}
/*link_find + link_get + route_add*/
for (i = 0; i < IP_TST_SIZ; i++) {
gw[i].addr = long_be(0x0a0000f0u + (i << 16));
r[i].addr = long_be(0x0c00001u + (i << 16));
fail_unless(pico_ipv4_link_find(&a[i]) == dev[i], "Error finding link");
l[i] = pico_ipv4_link_get(&a[i]);
fail_if(l[i] == NULL, "Error getting link");
fail_if(pico_ipv4_route_add(r[i], nm32, gw[i], 1, l[i]) != 0, "Error adding route");
fail_if(pico_ipv4_route_add(d[i], nm32, gw[i], 1, l[i]) != 0, "Error adding route");
}
/*get_gateway + source_find*/
for (i = 0; i < IP_TST_SIZ; i++) {
ret = pico_ipv4_route_get_gateway(&r[i]);
fail_if(ret.addr != gw[i].addr, "Error get gateway: returned wrong route");
source[i] = pico_ipv4_source_find(&d[i]);
fail_if(source[i]->addr != a[i].addr, "Error find source: returned wrong route");
}
/*route_del + link_del*/
for (i = 0; i < IP_TST_SIZ; i++) {
fail_if(pico_ipv4_route_del(r[i], nm32, 1) != 0, "Error deleting route");
fail_if(pico_ipv4_link_del(dev[i], a[i]) != 0, "Error deleting link");
}
/*string_to_ipv4 + ipv4_to_string*/
pico_string_to_ipv4(ipstr, &(ipaddr.addr));
fail_if(ipaddr.addr != long_be(0xc0a80101), "Error string to ipv4");
memset(ipstr, 0, 12);
pico_ipv4_to_string(ipstr, ipaddr.addr);
fail_if(strncmp(ipstr, "192.168.1.1", 11) != 0, "Error ipv4 to string");
/*valid_netmask*/
fail_if(pico_ipv4_valid_netmask(long_be(nm32.addr)) != 32, "Error checking netmask");
/*is_unicast*/
fail_if((pico_ipv4_is_unicast(long_be(0xc0a80101))) != 1, "Error checking unicast");
fail_if((pico_ipv4_is_unicast(long_be(0xe0000001))) != 0, "Error checking unicast");
/*rebound*/
fail_if(pico_ipv4_rebound(f_NULL) != -1, "Error rebound frame");
/*frame_push*/
fail_if(pico_ipv4_frame_push(f_NULL, dst_NULL, PICO_PROTO_TCP) != -1, "Error push frame");
}
END_TEST
START_TEST (test_nat_enable_disable)
{
struct pico_ipv4_link link = {
.address = {.addr = long_be(0x0a320001)}
}; /* 10.50.0.1 */
struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, NULL, PICO_UDPHDR_SIZE);
struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr;
struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr;
const char *raw_data = "ello";
net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */
net->tos = 0;
net->len = short_be(32); /* hdr + data (bytes) */
net->id = short_be(0x91c0);
net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */
net->ttl = 64;
net->proto = 17; /* UDP */
net->crc = 0;
net->src.addr = long_be(0x0a280008); /* 10.40.0.8 */
net->dst.addr = long_be(0x0a320001); /* 10.50.0.1 */
udp->trans.sport = short_be(5555);
udp->trans.dport = short_be(6667);
udp->len = 12;
udp->crc = 0;
f->payload = f->transport_hdr + PICO_UDPHDR_SIZE;
memcpy(f->payload, raw_data, 4);
printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT ENABLE/DISABLE TEST\n");
pico_stack_init();
fail_if(pico_ipv4_nat_enable(&link));
fail_unless(nat_link->address.addr == link.address.addr);
fail_unless(pico_ipv4_nat_is_enabled(&link.address));
fail_if(pico_ipv4_nat_outbound(f, &net->dst));
pico_ipv4_nat_table_cleanup(pico_tick, NULL);
fail_if(pico_ipv4_nat_disable());
fail_if(pico_ipv4_nat_is_enabled(&link.address));
}
END_TEST
START_TEST (test_nat_translation)
{
struct pico_ipv4_link link = {
.address = {.addr = long_be(0x0a320001)}
}; /* 10.50.0.1 */
struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, NULL, PICO_UDPHDR_SIZE);
struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr;
struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr;
struct pico_ip4 src_ori = {
.addr = long_be(0x0a280008)
}; /* 10.40.0.8 */
struct pico_ip4 dst_ori = {
.addr = long_be(0x0a320009)
}; /* 10.50.0.9 */
struct pico_ip4 nat = {
.addr = long_be(0x0a320001)
}; /* 10.50.0.9 */
const char *raw_data = "ello";
uint16_t sport_ori = short_be(5555);
uint16_t dport_ori = short_be(6667);
uint16_t nat_port = 0;
net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */
net->tos = 0;
net->len = short_be(32); /* hdr + data (bytes) */
net->id = short_be(0x91c0);
net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */
net->ttl = 64;
net->proto = 17; /* UDP */
net->crc = 0;
net->src = src_ori;
net->dst = dst_ori;
udp->trans.sport = sport_ori;
udp->trans.dport = dport_ori;
udp->len = 12;
udp->crc = 0;
f->payload = f->transport_hdr + PICO_UDPHDR_SIZE;
memcpy(f->payload, raw_data, 4);
printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT TRANSLATION TEST\n");
pico_stack_init();
fail_if(pico_ipv4_nat_enable(&link));
/* perform outbound translation, check if source IP got translated */
fail_if(pico_ipv4_nat_outbound(f, &nat_link->address));
fail_if(net->src.addr != link.address.addr, "source address not translated");
/* perform outbound translation of same packet, check if source IP and PORT got translated the same as previous packet */
nat_port = udp->trans.sport;
net->src = src_ori; /* restore original src */
udp->trans.sport = sport_ori; /* restore original sport */
fail_if(pico_ipv4_nat_outbound(f, &nat_link->address));
fail_if(net->src.addr != link.address.addr, "source address not translated");
fail_if(udp->trans.sport != nat_port, "frames with the same source IP, source PORT and PROTO did not get translated the same");
/* perform outbound translation of packet with changed source PORT, check if source PORT got translated differently as previous packet */
nat_port = udp->trans.sport;
net->src = src_ori; /* restore original src */
udp->trans.sport = short_be(5556); /* change sport */
fail_if(pico_ipv4_nat_outbound(f, &nat_link->address));
fail_if(net->src.addr != link.address.addr, "source address not translated");
fail_if(udp->trans.sport == short_be(sport_ori), "two frames with different sport get translated the same");
/* perform inbound translation of previous packet, check if destination IP and PORT got translated to the original source IP and PORT */
nat_port = udp->trans.sport;
net->src = dst_ori;
net->dst = nat;
udp->trans.sport = sport_ori;
udp->trans.dport = nat_port;
fail_if(pico_ipv4_nat_inbound(f, &nat_link->address));
fail_if(net->dst.addr != src_ori.addr, "destination address not translated correctly");
fail_if(udp->trans.dport != short_be(5556), "ports not translated correctly");
pico_ipv4_nat_table_cleanup(pico_tick, NULL);
fail_if(pico_ipv4_nat_disable());
}
END_TEST
START_TEST (test_nat_port_forwarding)
{
struct pico_ipv4_link link = {
.address = {.addr = long_be(0x0a320001)}
}; /* 10.50.0.1 */
struct pico_frame *f = pico_ipv4_alloc(&pico_proto_ipv4, NULL, PICO_UDPHDR_SIZE);
struct pico_ipv4_hdr *net = (struct pico_ipv4_hdr *)f->net_hdr;
struct pico_udp_hdr *udp = (struct pico_udp_hdr *)f->transport_hdr;
struct pico_ip4 src_addr = {
.addr = long_be(0x0a280008)
}; /* 10.40.0.8 */
struct pico_ip4 dst_addr = {
.addr = long_be(0x0a320009)
}; /* 10.50.0.9 */
struct pico_ip4 nat_addr = {
.addr = long_be(0x0a320001)
}; /* 10.50.0.9 */
const char *raw_data = "ello";
uint16_t sport_ori = short_be(5555);
uint16_t fport_pub = short_be(80);
uint16_t fport_priv = short_be(8080);
net->vhl = 0x45; /* version = 4, hdr len = 5 (32-bit words) */
net->tos = 0;
net->len = short_be(32); /* hdr + data (bytes) */
net->id = short_be(0x91c0);
net->frag = short_be(0x4000); /* don't fragment flag, offset = 0 */
net->ttl = 64;
net->proto = 17; /* UDP */
net->crc = 0;
net->src = dst_addr;
net->dst = nat_addr;
udp->trans.sport = sport_ori;
udp->trans.dport = fport_pub;
udp->len = 12;
udp->crc = 0;
f->payload = f->transport_hdr + PICO_UDPHDR_SIZE;
memcpy(f->payload, raw_data, 4);
printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NAT PORT FORWARD TEST\n");
pico_stack_init();
fail_if(pico_ipv4_nat_enable(&link));
fail_if(pico_ipv4_port_forward(nat_addr, fport_pub, src_addr, fport_priv, 17, PICO_NAT_PORT_FORWARD_ADD));
fail_if(pico_ipv4_nat_inbound(f, &nat_link->address));
fail_if(net->dst.addr != src_addr.addr, "destination address not translated correctly");
fail_if(udp->trans.dport != fport_priv, "destination port not translated correctly");
fail_if(pico_ipv4_port_forward(nat_addr, fport_pub, src_addr, fport_priv, 17, PICO_NAT_PORT_FORWARD_DEL));
pico_ipv4_nat_table_cleanup(pico_tick, NULL);
}
END_TEST
START_TEST (test_ipfilter)
{
struct pico_device *dev = NULL;
uint8_t proto = 0, tos = 0;
uint16_t sport = 0, dport = 0;
int8_t priority = 0;
int ret = 0;
struct pico_ip4 src_addr = {
0
};
struct pico_ip4 saddr_netmask = {
0
};
struct pico_ip4 dst_addr = {
0
};
struct pico_ip4 daddr_netmask = {
0
};
enum filter_action action = 1;
uint32_t filter_id1;
/* 192.168.1.2:16415 -> 192.168.1.109:1222 [sending a TCP syn] */
uint8_t ipv4_buf[] = {
0x00, 0x02, 0xf7, 0xf1, 0x79, 0x33, 0xe0, 0xdb, 0x55,
0xd4, 0xb6, 0x27, 0x08, 0x00, 0x45, 0x00, 0x00, 0x28,
0x00, 0x01, 0x00, 0x00, 0x40, 0x06, 0xf7, 0x0f, 0xc0,
0xa8, 0x01, 0x02, 0xc0, 0xa8, 0x01, 0x6d, 0x40, 0x1f,
0x04, 0xc6, 0x00, 0xb1, 0x56, 0x5a, 0x00, 0x00, 0x00,
0x00, 0x50, 0x02, 0x20, 0x00, 0x70, 0x32, 0x00, 0x00
};
struct pico_frame *f;
printf("IP Filter> Adding a new filter...\n");
filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, action);
fail_if(filter_id1 <= 0, "Error adding filter\n");
printf("filter_id1 = %d\n", filter_id1);
printf("IP Filter> Trying to add the same filter...\n");
filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, action);
fail_if(ret > 0, "Error adding filter\n");
printf("IP Filter> Deleting added filter...\n");
ret = pico_ipv4_filter_del(filter_id1);
fail_if(ret != 0, "Error deleting the filter\n");
printf("IP Filter> Trying to delete the same filter\n");
ret = pico_ipv4_filter_del(filter_id1);
fail_if(ret != -1, "Deleting non existing filter failed\n");
f = (struct pico_frame *)PICO_ZALLOC(200);
f->buffer = PICO_ZALLOC(20);
f->usage_count = PICO_ZALLOC(sizeof(uint32_t));
f->buffer = ipv4_buf;
f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */
f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */
/* adding exact filter */
pico_string_to_ipv4("192.168.1.109", &src_addr.addr);
pico_string_to_ipv4("255.255.255.255", &saddr_netmask.addr);
sport = 1222u;
filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_REJECT);
fail_if(filter_id1 <= 0, "Error adding exact filter\n");
printf("Filter is added\n");
sync();
sleep(1);
ret = ipfilter(f);
fail_if(ret != 1, "Frame wasn't filtered\n");
printf("IP Filter> Deleting added filter...\n");
ret = pico_ipv4_filter_del(filter_id1);
fail_if(ret != 0, "Error deleting the filter\n");
printf("IP Filter> Adding masked filter...\n");
pico_string_to_ipv4("192.168.1.7", &src_addr.addr);
pico_string_to_ipv4("255.255.255.0", &saddr_netmask.addr);
sport = 1222u;
filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_DROP);
fail_if(filter_id1 <= 0, "Error adding masked filter\n");
f = (struct pico_frame *)PICO_ZALLOC(200);
f->buffer = PICO_ZALLOC(20);
f->usage_count = PICO_ZALLOC(sizeof(uint32_t));
f->buffer = ipv4_buf;
f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */
f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */
ret = ipfilter(f);
fail_if(ret != 1, "Mask filter failed to filter\n");
printf("IP Filter> Deleting added filter...\n");
ret = pico_ipv4_filter_del(filter_id1);
fail_if(ret != 0, "Error deleting the filter\n");
printf("IP Filter> Adding bad filter..\n");
pico_string_to_ipv4("191.1.1.7", &src_addr.addr);
pico_string_to_ipv4("255.255.255.0", &saddr_netmask.addr);
sport = 1991u;
filter_id1 = pico_ipv4_filter_add(dev, proto, &src_addr, &saddr_netmask, &dst_addr, &daddr_netmask, sport, dport, priority, tos, FILTER_DROP);
fail_if(filter_id1 <= 0, "Error adding bad filter\n");
f = (struct pico_frame *)PICO_ZALLOC(200);
f->buffer = PICO_ZALLOC(20);
f->usage_count = PICO_ZALLOC(sizeof(uint32_t));
f->buffer = ipv4_buf;
f->net_hdr = ipv4_buf + 14u; /* shifting to IP layer */
f->transport_hdr = ipv4_buf + 34u; /* shifting to Transport layer */
ret = ipfilter(f);
fail_if(ret != 0, "Filter shouldn't have filtered this frame\n");
printf("IP Filter> Deleting added filter...\n");
ret = pico_ipv4_filter_del(filter_id1);
fail_if(ret != 0, "Error deleting the filter\n");
}
END_TEST
#ifdef PICO_SUPPORT_MCAST
START_TEST (test_igmp_sockopts)
{
int i = 0, j = 0, k = 0, ret = 0;
struct pico_socket *s, *s1 = NULL;
struct pico_device *dev = NULL;
union pico_address *source = NULL;
union pico_address inaddr_dst = {
0
}, inaddr_incorrect = {
0
}, inaddr_uni = {
0
}, inaddr_null = {
0
}, netmask = {
0
};
union pico_address inaddr_link[2] = {0};
union pico_address inaddr_mcast[8] = {0};
union pico_address inaddr_source[8] = {0};
struct pico_ip_mreq _mreq = {0}, mreq[16] = {0};
struct pico_ip_mreq_source mreq_source[128] = {0};
struct pico_tree_node *index = NULL;
int ttl = 64;
int getttl = 0;
int loop = 9;
int getloop = 0;
union pico_address mcast_def_link = {
0
};
pico_stack_init();
printf("START IGMP SOCKOPTS TEST\n");
pico_string_to_ipv4("224.7.7.7", &inaddr_dst.ip4.addr);
pico_string_to_ipv4("10.40.0.2", &inaddr_uni.ip4.addr);
pico_string_to_ipv4("224.8.8.8", &inaddr_incorrect.ip4.addr);
pico_string_to_ipv4("0.0.0.0", &inaddr_null.ip4.addr);
pico_string_to_ipv4("10.40.0.1", &inaddr_link[0].ip4.addr); /* 0 */
pico_string_to_ipv4("10.50.0.1", &inaddr_link[1].ip4.addr); /* 1 */
pico_string_to_ipv4("232.1.1.0", &inaddr_mcast[0].ip4.addr); /* 0 */
pico_string_to_ipv4("232.2.2.1", &inaddr_mcast[1].ip4.addr); /* 1 */
pico_string_to_ipv4("232.3.3.2", &inaddr_mcast[2].ip4.addr); /* 2 */
pico_string_to_ipv4("232.4.4.3", &inaddr_mcast[3].ip4.addr); /* 3 */
pico_string_to_ipv4("232.5.5.4", &inaddr_mcast[4].ip4.addr); /* 4 */
pico_string_to_ipv4("232.6.6.5", &inaddr_mcast[5].ip4.addr); /* 5 */
pico_string_to_ipv4("232.7.7.6", &inaddr_mcast[6].ip4.addr); /* 6 */
pico_string_to_ipv4("232.8.8.7", &inaddr_mcast[7].ip4.addr); /* 7 */
pico_string_to_ipv4("10.40.1.0", &inaddr_source[0].ip4.addr); /* 0 */
pico_string_to_ipv4("10.40.1.1", &inaddr_source[1].ip4.addr); /* 1 */
pico_string_to_ipv4("10.40.1.2", &inaddr_source[2].ip4.addr); /* 2 */
pico_string_to_ipv4("10.40.1.3", &inaddr_source[3].ip4.addr); /* 3 */
pico_string_to_ipv4("10.40.1.4", &inaddr_source[4].ip4.addr); /* 4 */
pico_string_to_ipv4("10.40.1.5", &inaddr_source[5].ip4.addr); /* 5 */
pico_string_to_ipv4("10.40.1.6", &inaddr_source[6].ip4.addr); /* 6 */
pico_string_to_ipv4("10.40.1.7", &inaddr_source[7].ip4.addr); /* 7 */
/* 00 01 02 03 04 05 06 07 | 10 11 12 13 14 15 16 17 */
for (i = 0; i < 16; i++) {
mreq[i].mcast_link_addr = inaddr_link[i / 8];
mreq[i].mcast_group_addr = inaddr_mcast[i % 8];
}
/* 000 001 002 003 004 005 006 007 | 010 011 012 013 014 015 016 017 */
for (i = 0; i < 16; i++) {
for (j = 0; j < 8; j++) {
/* printf(">>>>> mreq_source[%d]: link[%d] mcast[%d] source[%d]\n", (i*8)+j, i/8, i%8, j); */
mreq_source[(i * 8) + j].mcast_link_addr = inaddr_link[i / 8];
mreq_source[(i * 8) + j].mcast_group_addr = inaddr_mcast[i % 8];
mreq_source[(i * 8) + j].mcast_source_addr = inaddr_source[j];
}
}
dev = pico_null_create("dummy0");
netmask.ip4.addr = long_be(0xFFFF0000);
ret = pico_ipv4_link_add(dev, inaddr_link[0].ip4, netmask.ip4);
fail_if(ret < 0, "link add failed");
dev = pico_null_create("dummy1");
netmask.ip4.addr = long_be(0xFFFF0000);
ret = pico_ipv4_link_add(dev, inaddr_link[1].ip4, netmask.ip4);
fail_if(ret < 0, "link add failed");
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, NULL);
fail_if(s == NULL, "UDP socket open failed");
s1 = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, NULL);
fail_if(s1 == NULL, "UDP socket open failed");
/* argument validation tests */
printf("IGMP SETOPTION ARGUMENT VALIDATION TEST\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_TTL, &ttl);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_TTL, &getttl);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
fail_if(getttl != ttl, "setoption ttl != getoption ttl\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
fail_if(ret == 0, "PICO_IP_MULTICAST_LOOP succeeded with invalid (not 0 or 1) loop value\n");
loop = 0;
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed disabling\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_LOOP, &getloop);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed getting value\n");
fail_if(getloop != loop, "setoption loop != getoption loop\n");
_mreq.mcast_group_addr = inaddr_dst;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "supported PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "supported PICO_IP_DROP_MEMBERSHIP failed\n");
_mreq.mcast_group_addr = inaddr_dst;
_mreq.mcast_link_addr = inaddr_null;
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed with valid NULL (use default) link address\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed with valid NULL (use default) link address\n");
_mreq.mcast_group_addr = inaddr_uni;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (unicast) group address\n");
_mreq.mcast_group_addr = inaddr_null;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (NULL) group address\n");
_mreq.mcast_group_addr = inaddr_dst;
_mreq.mcast_link_addr = inaddr_uni;
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid link address\n");
_mreq.mcast_group_addr = inaddr_incorrect;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (not added) group address\n");
_mreq.mcast_group_addr = inaddr_uni;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) group address\n");
_mreq.mcast_group_addr = inaddr_null;
_mreq.mcast_link_addr = inaddr_link[0];
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (NULL) group address\n");
_mreq.mcast_group_addr = inaddr_dst;
_mreq.mcast_link_addr = inaddr_uni;
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) link address\n");
/* flow validation tests */
printf("IGMP SETOPTION FLOW VALIDATION TEST\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed with err %s\n", strerror(pico_err));
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* stress tests */
printf("IGMP SETOPTION STRESS TEST\n");
for (k = 0; k < 2; k++) {
/* ADD for even combinations of group and link, ADD_SOURCE for uneven */
for (i = 0; i < 16; i++) {
if (i % 2) {
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[i]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
}
} else {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
}
}
}
/* UNBLOCK and DROP for even combinations, DROP_SOURCE for uneven */
for (i = 0; i < 16; i++) {
if (i % 2) {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[i]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
} else {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
}
}
}
/* everything should be cleanup up, next iteration will fail if not */
}
/* filter validation tests */
printf("IGMP SETOPTION FILTER VALIDATION TEST\n");
/* INCLUDE + INCLUDE expected filter: source of 0 and 1*/
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (INCLUDE + INCLUDE) too many elements\n");
source = index->keyValue;
if (source->ip4.addr == mreq_source[0].mcast_source_addr.ip4.addr) { /* OK */
}
else if (source->ip4.addr == mreq_source[1].mcast_source_addr.ip4.addr) { /* OK */
}
else {
fail("MCASTFilter (INCLUDE + INCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* INCLUDE + EXCLUDE expected filter: source of 2 */
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[2]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 1)
fail("MCASTFilter (INCLUDE + EXCLUDE) too many elements\n");
source = index->keyValue;
if (source->ip4.addr == mreq_source[2].mcast_source_addr.ip4.addr) { /* OK */
}
else {
fail("MCASTFilter (INCLUDE + EXCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* EXCLUDE + INCLUDE expected filter: source of 0 and 1 */
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (EXCLUDE + INCLUDE) too many elements\n");
source = index->keyValue;
if (source->ip4.addr == mreq_source[0].mcast_source_addr.ip4.addr) { /* OK */
}
else if (source->ip4.addr == mreq_source[1].mcast_source_addr.ip4.addr) { /* OK */
}
else {
fail("MCASTFilter (EXCLUDE + INCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* EXCLUDE + EXCLUDE expected filter: source of 3 and 4 */
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[5]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[6]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (EXCLUDE + EXCLUDE) too many elements\n");
source = index->keyValue;
if (source->ip4.addr == mreq_source[3].mcast_source_addr.ip4.addr) { /* OK */
}
else if (source->ip4.addr == mreq_source[4].mcast_source_addr.ip4.addr) { /* OK */
}
else {
fail("MCASTFilter (EXCLUDE + EXCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_close(s);
fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
ret = pico_socket_close(s1);
fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
}
END_TEST
#endif
START_TEST (test_slaacv4)
{
uint32_t tmp;
struct pico_device *dev;
struct mock_device *mock;
char ip_addr[20];
uint8_t macaddr1[6] = {
0xc3, 0, 0, 0xa, 0xc, 0xf
};
/* verify min boundary*/
tmp = SLAACV4_CREATE_IPV4(0);
pico_ipv4_to_string(ip_addr, tmp);
printf("IP address generated by slaac: %s\n", ip_addr);
fail_if(long_be(tmp) < (long_be(SLAACV4_NETWORK) | SLAACV4_MINRANGE));
/* verify max boundary*/
tmp = SLAACV4_CREATE_IPV4(0x00FD);
fail_if(long_be(tmp) > (long_be(SLAACV4_NETWORK) | 0x0000FEFF));
/* verify case where dev->eth is NULL */
dev = pico_null_create("dummy");
tmp = pico_slaacv4_getip(dev, 0);
fail_if(long_be(tmp) != (long_be(SLAACV4_NETWORK) | SLAACV4_MINRANGE));
/* verify nominal case; two runs of slaacv4_get_ip need to return same value */
mock = pico_mock_create(macaddr1);
tmp = pico_slaacv4_getip(mock->dev, 0);
fail_if(tmp != pico_slaacv4_getip(mock->dev, 0));
}
END_TEST

View File

@ -0,0 +1,760 @@
#ifdef PICO_SUPPORT_IPV6
START_TEST (test_ipv6)
{
char ipstr[40] = {
0
};
char ipstr0[] = "2001:0db8:130f:0000:0000:09c0:876a:130b";
char ipstr0_t[] = "2001:0db8:130f:0000:0000:09c0:876a:130b";
char ipstr1[] = "2001:db8:130f:0000:0000:09c0:876a:130b";
char ipstr1_t[] = "2001:0db8:130f:0000:0000:09c0:876a:130b";
char ipstr2[] = "2001:b8:130f:0000:0000:09c0:876a:130b";
char ipstr2_t[] = "2001:00b8:130f:0000:0000:09c0:876a:130b";
char ipstr3[] = "2001:8:130f:0000:0000:09c0:876a:130b";
char ipstr3_t[] = "2001:0008:130f:0000:0000:09c0:876a:130b";
char ipstr4[] = "2001:8:130f:0:0:09c0:876a:130b";
char ipstr4_t[] = "2001:0008:130f:0000:0000:09c0:876a:130b";
char ipstr5[] = "2001::8:130f:09c0:876a:130b";
char ipstr5_t[] = "2001:0000:0000:0008:130f:09c0:876a:130b";
char ipstr6[] = "2001::8:09c0:876a:130b";
char ipstr6_t[] = "2001:0000:0000:0000:0008:09c0:876a:130b";
char ipstr7[] = "2001::8:876a:130b";
char ipstr7_t[] = "2001:0000:0000:0000:0000:0008:876a:130b";
char ipstr8[] = "2001::876a:130b";
char ipstr8_t[] = "2001:0000:0000:0000:0000:0000:876a:130b";
char ipstr9[] = "ff01::1";
char ipstr9_t[] = "ff01:0000:0000:0000:0000:0000:0000:0001";
char ipstr10[] = "::1";
char ipstr10_t[] = "0000:0000:0000:0000:0000:0000:0000:0001";
char ipstr11[] = "fe80::";
char ipstr11_t[] = "fe80:0000:0000:0000:0000:0000:0000:0000";
char ipstr12[] = "::";
char ipstr12_t[] = "0000:0000:0000:0000:0000:0000:0000:0000";
char ipstr13[] = "2001:8:130f::09c0::130b"; /* invalid */
char ipstr14[] = "2001:8:xxxx::09c0:130b"; /* invalid */
char ipstr15[] = "2001:8:$$$$::09c0:130b"; /* invalid */
char ipstr16[] = "2001:8:!@#$::%^&*:()0b"; /* invalid */
char ipstr17[] = "2001:1"; /* invalid */
char ipstr18[] = "20010db8:130f:0000:0000:09c0:876a:130b"; /* invalid */
char ipstr19[] = "20010db8130f0000000009c0876a130b"; /* invalid */
char ipstr20[] = "2001;0db8;130f;0000;0000;09c0;876a;130b"; /* invalid */
uint8_t iphex0[PICO_SIZE_IP6] = {
0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex1[PICO_SIZE_IP6] = {
0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex2[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex3[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x08, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex4[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x08, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex5[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x13, 0x0f, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex6[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex7[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex8[PICO_SIZE_IP6] = {
0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x6a, 0x13, 0x0b
};
uint8_t iphex9[PICO_SIZE_IP6] = {
0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
uint8_t iphex10[PICO_SIZE_IP6] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
uint8_t iphex11[PICO_SIZE_IP6] = {
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t iphex12[PICO_SIZE_IP6] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
struct pico_ip6 iphex_a = {{ 0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }};
struct pico_ip6 iphex_r = {{ 0x40, 0x02, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }};
struct pico_ip6 iphex_gw = {{ 0x20, 0x01, 0x0d, 0xb8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f }};
struct pico_ip6 nm64 = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
struct pico_ip6 nm128 = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }};
struct pico_ip6 ipaddr = {{0}};
struct pico_ip6 _gw, r[IP_TST_SIZ], a[IP_TST_SIZ], gw[IP_TST_SIZ], *source[IP_TST_SIZ];
struct pico_device *dev[IP_TST_SIZ];
struct pico_ipv6_link *l[IP_TST_SIZ];
struct pico_ipv6_link *_link = NULL;
struct pico_ipv6_route *_route = NULL;
char devname[8];
int ret = 0;
int i = 0;
pico_stack_init();
/* pico_string_to_ipv6 and pico_ipv6_to_string */
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr0);
pico_string_to_ipv6(ipstr0, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex0, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr0_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr1);
pico_string_to_ipv6(ipstr1, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex1, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr1_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr2);
pico_string_to_ipv6(ipstr2, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex2, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr2_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr3);
pico_string_to_ipv6(ipstr3, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex3, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr3_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr4);
pico_string_to_ipv6(ipstr4, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex4, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr4_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr5);
pico_string_to_ipv6(ipstr5, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex5, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr5_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr6);
pico_string_to_ipv6(ipstr6, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex6, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr6_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr7);
pico_string_to_ipv6(ipstr7, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex7, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr7_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr8);
pico_string_to_ipv6(ipstr8, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex8, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr8_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr9);
pico_string_to_ipv6(ipstr9, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex9, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr9_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr10);
pico_string_to_ipv6(ipstr10, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex10, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr10_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr11);
pico_string_to_ipv6(ipstr11, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex11, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr11_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 valid conversion of %s\n", ipstr12);
pico_string_to_ipv6(ipstr12, ipaddr.addr);
fail_if(memcmp(ipaddr.addr, iphex12, PICO_SIZE_IP6), "Error string to ipv6");
pico_ipv6_to_string(ipstr, ipaddr.addr);
printf("pico_ipv6_to_string valid conversion to %s\n", ipstr);
fail_if(strncmp(ipstr, ipstr12_t, 40) != 0, "Error ipv6 to string");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr13);
ret = pico_string_to_ipv6(ipstr13, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr14);
ret = pico_string_to_ipv6(ipstr14, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr15);
ret = pico_string_to_ipv6(ipstr15, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr16);
ret = pico_string_to_ipv6(ipstr16, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr17);
ret = pico_string_to_ipv6(ipstr17, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr18);
ret = pico_string_to_ipv6(ipstr18, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr19);
ret = pico_string_to_ipv6(ipstr19, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
printf("pico_string_to_ipv6 invalid conversion of %s\n", ipstr20);
ret = pico_string_to_ipv6(ipstr20, ipaddr.addr);
fail_if(ret == 0, "Error string to ipv6");
/*link_add*/
for (i = 0; i < 10; ++i) {
snprintf(devname, 8, "nul%d", i);
dev[i] = pico_null_create(devname);
a[i] = iphex_a;
a[i].addr[4] = (uint8_t)(a[i].addr[4] + i);
fail_if(pico_ipv6_link_add(dev[i], a[i], nm64) == NULL, "Error adding link");
}
/*link_find + link_get + route_add*/
for (i = 0; i < 10; ++i) {
gw[i] = iphex_gw;
gw[i].addr[4] = (uint8_t)(gw[i].addr[4] + i);
fail_unless(pico_ipv6_link_find(&a[i]) == dev[i], "Error finding link");
l[i] = pico_ipv6_link_get(&a[i]);
fail_if(l[i] == NULL, "Error getting link");
r[i] = iphex_r;
r[i].addr[4] = (uint8_t)(r[i].addr[4] + i);
fail_if(pico_ipv6_route_add(r[i], nm128, a[i], 1, l[i]) != 0, "Error adding route");
}
/*get_gateway*/
for (i = 0; i < 10; i++) {
_gw = pico_ipv6_route_get_gateway(&r[i]);
fail_if(memcmp(_gw.addr, a[i].addr, PICO_SIZE_IP6) != 0, "Error get gateway: returned wrong route");
source[i] = pico_ipv6_source_find(&r[i]);
fail_if(memcmp(source[i]->addr, a[i].addr, PICO_SIZE_IP6) != 0, "Error find source: returned wrong route");
}
/*route_del + link_del*/
for (i = 0; i < 10; i++) {
fail_if(pico_ipv6_route_del(r[i], nm128, a[i], 1, l[i]) != 0, "Error deleting route");
fail_if(pico_ipv6_link_del(dev[i], a[i]) != 0, "Error deleting link");
}
/* add 2 links to dev[0] */
_link = pico_ipv6_link_add(dev[0], a[0], nm64);
fail_if (!_link, "Error adding link");
_link = pico_ipv6_link_add(dev[0], a[1], nm64);
fail_if (!_link, "Error adding link");
/* add 2 routes to each of the links */
ret = pico_ipv6_route_add(r[0], nm128, a[0], 1, l[0]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[1], nm128, a[0], 1, l[0]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[2], nm128, a[1], 1, l[1]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[3], nm128, a[1], 1, l[1]);
fail_if(ret != 0, "Error adding route");
/* add 2 links to dev[1] */
_link = pico_ipv6_link_add(dev[1], a[8], nm64);
fail_if (!_link, "Error adding link");
_link = pico_ipv6_link_add(dev[1], a[9], nm64);
fail_if (!_link, "Error adding link");
/* add 2 routes to each of the links */
ret = pico_ipv6_route_add(r[6], nm128, a[8], 1, l[8]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[7], nm128, a[8], 1, l[8]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[8], nm128, a[9], 1, l[9]);
fail_if(ret != 0, "Error adding route");
ret = pico_ipv6_route_add(r[9], nm128, a[9], 1, l[9]);
fail_if(ret != 0, "Error adding route");
/* destroy device, should clean up all links and routes */
pico_device_destroy(dev[0]);
_link = pico_ipv6_link_get(&a[0]);
fail_if(_link != NULL, "Error destroying device");
_link = pico_ipv6_link_get(&a[1]);
fail_if(_link != NULL, "Error destroying device");
_link = pico_ipv6_link_get(&a[8]);
fail_if(_link == NULL, "Error destroying device");
_link = pico_ipv6_link_get(&a[9]);
fail_if(_link == NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[0]);
fail_if(_route != NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[1]);
fail_if(_route != NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[2]);
fail_if(_route != NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[3]);
fail_if(_route != NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[6]);
fail_if(_route == NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[7]);
fail_if(_route == NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[8]);
fail_if(_route == NULL, "Error destroying device");
_route = pico_ipv6_route_find(&r[9]);
fail_if(_route == NULL, "Error destroying device");
}
END_TEST
#ifdef PICO_SUPPORT_MCAST
START_TEST (test_mld_sockopts)
{
int i = 0, j = 0, k = 0, ret = 0;
struct pico_socket *s, *s1 = NULL;
struct pico_device *dev = NULL;
union pico_address *source = NULL;
union pico_address inaddr_dst = {
0
}, inaddr_incorrect = {
0
}, inaddr_uni = {
0
}, inaddr_null = {
0
};
struct pico_ip6 netmask = {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
union pico_address inaddr_link[2] = {0};
union pico_address inaddr_mcast[8] = {0};
union pico_address inaddr_source[8] = {0};
struct pico_ip_mreq _mreq = {0}, mreq[16] = {0};
struct pico_ip_mreq_source mreq_source[128] = {0};
struct pico_tree_node *index = NULL;
struct pico_ipv6_link *ret_link = NULL;
int ttl = 64;
int getttl = 0;
int loop = 9;
int getloop = 0;
struct pico_ip6 mcast_def_link = {
0
};
pico_stack_init();
printf("START MLD SOCKOPTS TEST\n");
pico_string_to_ipv6("ff00:0:0:0:0:0:e007:707", inaddr_dst.ip6.addr);
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:2", inaddr_uni.ip6.addr);
pico_string_to_ipv6("ff00:0:0:0:0:0:e008:808", inaddr_incorrect.ip6.addr);
pico_string_to_ipv6("::", inaddr_null.ip6.addr);
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:0001", inaddr_link[0].ip6.addr); /* 0 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a32:0001", inaddr_link[1].ip6.addr); /* 1 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e801:100", inaddr_mcast[0].ip6.addr); /* 0 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e802:201", inaddr_mcast[1].ip6.addr); /* 1 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:302", inaddr_mcast[2].ip6.addr); /* 2 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:403", inaddr_mcast[3].ip6.addr); /* 3 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:504", inaddr_mcast[4].ip6.addr); /* 4 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:605", inaddr_mcast[5].ip6.addr); /* 5 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:706", inaddr_mcast[6].ip6.addr); /* 6 */
pico_string_to_ipv6("ff00:0:0:0:0:0:e803:807", inaddr_mcast[7].ip6.addr); /* 7 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:100", inaddr_source[0].ip6.addr); /* 0 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:101", inaddr_source[1].ip6.addr); /* 1 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:102", inaddr_source[2].ip6.addr); /* 2 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:103", inaddr_source[3].ip6.addr); /* 3 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:104", inaddr_source[4].ip6.addr); /* 4 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:105", inaddr_source[5].ip6.addr); /* 5 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:106", inaddr_source[6].ip6.addr); /* 6 */
pico_string_to_ipv6("fe80:0:0:0:0:0:a28:107", inaddr_source[7].ip6.addr); /* 7 */
/* 00 01 02 03 04 05 06 07 | 10 11 12 13 14 15 16 17 */
for (i = 0; i < 16; i++) {
mreq[i].mcast_link_addr = inaddr_link[i / 8];
mreq[i].mcast_group_addr = inaddr_mcast[i % 8];
}
/* 000 001 002 003 004 005 006 007 | 010 011 012 013 014 015 016 017 */
for (i = 0; i < 16; i++) {
for (j = 0; j < 8; j++) {
/* printf(">>>>> mreq_source[%d]: link[%d] mcast[%d] source[%d]\n", (i*8)+j, i/8, i%8, j); */
mreq_source[(i * 8) + j].mcast_link_addr = inaddr_link[i / 8];
mreq_source[(i * 8) + j].mcast_group_addr = inaddr_mcast[i % 8];
mreq_source[(i * 8) + j].mcast_source_addr = inaddr_source[j];
}
}
dev = pico_null_create("dummy0");
ret_link = pico_ipv6_link_add(dev, inaddr_link[0].ip6, netmask);
fail_if(ret_link == NULL, "link add failed");
dev = pico_null_create("dummy1");
ret_link = pico_ipv6_link_add(dev, inaddr_link[1].ip6, netmask);
fail_if(ret_link == NULL, "link add failed");
s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, NULL);
fail_if(s == NULL, "UDP socket open failed");
s1 = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, NULL);
fail_if(s1 == NULL, "UDP socket open failed");
/* argument validation tests */
printf("MLD SETOPTION ARGUMENT VALIDATION TEST\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_IF, &mcast_def_link);
fail_if(ret == 0, "unsupported PICO_IP_MULTICAST_IF succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_TTL, &ttl);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_TTL, &getttl);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_TTL failed\n");
fail_if(getttl != ttl, "setoption ttl != getoption ttl\n");
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
fail_if(ret == 0, "PICO_IP_MULTICAST_LOOP succeeded with invalid (not 0 or 1) loop value\n");
loop = 0;
ret = pico_socket_setoption(s, PICO_IP_MULTICAST_LOOP, &loop);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed disabling\n");
ret = pico_socket_getoption(s, PICO_IP_MULTICAST_LOOP, &getloop);
fail_if(ret < 0, "supported PICO_IP_MULTICAST_LOOP failed getting value\n");
fail_if(getloop != loop, "setoption loop != getoption loop\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "supported PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "supported PICO_IP_DROP_MEMBERSHIP failed\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_null.ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed with valid NULL (use default) link address\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed with valid NULL (use default) link address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (unicast) group address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_null.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid (NULL) group address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded with invalid link address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_incorrect.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (not added) group address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) group address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_null.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_link[0].ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (NULL) group address\n");
memcpy(&_mreq.mcast_group_addr, &inaddr_dst.ip6, sizeof(struct pico_ip6));
memcpy(&_mreq.mcast_link_addr, &inaddr_uni.ip6, sizeof(struct pico_ip6));
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &_mreq);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded with invalid (unicast) link address\n");
/* flow validation tests */
printf("MLD SETOPTION FLOW VALIDATION TEST\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed with err %s\n", strerror(pico_err));
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_DROP_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret == 0, "PICO_IP_ADD_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_UNBLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_BLOCK_SOURCE succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret == 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP succeeded\n");
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* stress tests */
printf("MLD SETOPTION STRESS TEST\n");
for (k = 0; k < 2; k++) {
/* ADD for even combinations of group and link, ADD_SOURCE for uneven */
for (i = 0; i < 16; i++) {
if (i % 2) {
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[i]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
}
} else {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
}
}
}
/* UNBLOCK and DROP for even combinations, DROP_SOURCE for uneven */
for (i = 0; i < 16; i++) {
if (i % 2) {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_UNBLOCK_SOURCE, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_UNBLOCK_SOURCE failed\n");
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[i]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
} else {
for (j = 0; j < 8; j++) {
ret = pico_socket_setoption(s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source[(i * 8) + j]);
fail_if(ret < 0, "PICO_IP_DROP_SOURCE_MEMBERSHIP failed\n");
}
}
}
/* everything should be cleanup up, next iteration will fail if not */
}
/* filter validation tests */
printf("MLD SETOPTION FILTER VALIDATION TEST\n");
/* INCLUDE + INCLUDE expected filter: source of 0 and 1*/
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (INCLUDE + INCLUDE) too many elements\n");
source = index->keyValue;
if (memcmp(&source->ip6, &mreq_source[0].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else if (memcmp(&source->ip6, &mreq_source[1].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else {
fail("MCASTFilter (INCLUDE + INCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* INCLUDE + EXCLUDE expected filter: source of 2 */
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[2]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 1)
fail("MCASTFilter (INCLUDE + EXCLUDE) too many elements\n");
source = index->keyValue;
if (memcmp(&source->ip6, &mreq_source[2].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else {
fail("MCASTFilter (INCLUDE + EXCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* EXCLUDE + INCLUDE expected filter: source of 0 and 1 */
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_ADD_SOURCE_MEMBERSHIP failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (EXCLUDE + INCLUDE) too many elements\n");
source = index->keyValue;
if (memcmp(&source->ip6, &mreq_source[0].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else if (memcmp(&source->ip6, &mreq_source[1].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else {
fail("MCASTFilter (EXCLUDE + INCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
/* EXCLUDE + EXCLUDE expected filter: source of 3 and 4 */
ret = pico_socket_setoption(s, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[0]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[1]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_ADD_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_ADD_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[3]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[4]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[5]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
ret = pico_socket_setoption(s1, PICO_IP_BLOCK_SOURCE, &mreq_source[6]);
fail_if(ret < 0, "PICO_IP_BLOCK_SOURCE failed\n");
i = 0;
pico_tree_foreach(index, &MCASTFilter)
{
if (++i > 2)
fail("MCASTFilter (EXCLUDE + EXCLUDE) too many elements\n");
source = index->keyValue;
if (memcmp(&source->ip6, &mreq_source[3].mcast_source_addr, sizeof(struct pico_ip6) == 0)) { /* OK */
}
else if (memcmp(&source->ip6, &mreq_source[4].mcast_source_addr, sizeof(struct pico_ip6)) == 0) { /* OK */
}
else {
fail("MCASTFilter (EXCLUDE + EXCLUDE) incorrect\n");
}
}
ret = pico_socket_setoption(s, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_setoption(s1, PICO_IP_DROP_MEMBERSHIP, &mreq[0]);
fail_if(ret < 0, "PICO_IP_DROP_MEMBERSHIP failed\n");
ret = pico_socket_close(s);
fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
ret = pico_socket_close(s1);
fail_if(ret < 0, "socket close failed: %s\n", strerror(pico_err));
}
END_TEST
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
#define BUFLEN (576 + 14 + 20 + 8)
int mock_print_protocol(uint8_t *buf);
int printbuf(uint8_t *buf, uint32_t len, const char *str, uint8_t printbufactive);
int tick_it(uint32_t nticks);
int mock_print_protocol(uint8_t *buf)
{
uint8_t pnr = buf[0x17]; /* protocol number */
printf("transport protocol: %s\n",
(pnr == PICO_PROTO_ICMP4 ? "icmp4" :
(pnr == PICO_PROTO_IGMP ? "igmp" :
(pnr == PICO_PROTO_TCP ? "tcp" :
(pnr == PICO_PROTO_UDP ? "udp" :
(pnr == PICO_PROTO_ICMP6 ? "icmp6" :
"unknown proto"))))));
return 0;
}
int printbuf(uint8_t *buf, uint32_t len, const char *str, uint8_t printbufactive)
{
uint8_t printMethod = 0;
uint32_t cntr = 0;
uint32_t cntr2 = 0;
if((printbufactive) && (printMethod == 0)) {
printf("\n%s:\n", str);
for(cntr = 0; cntr < len; cntr++) {
if((cntr % 8) == 0 && cntr != 0)
printf(" ");
if((cntr % 16) == 0 && cntr != 0)
printf("\n");
if((cntr % 16) == 0)
printf("%03x0 ", cntr2++);
printf("%02x ", buf[cntr]);
}
printf("\n");
}else if((printbufactive) && (printMethod == 1)) {
printf("\n%s:\n", str);
printf("Buf = {");
for(cntr = 0; cntr < len; cntr++) {
if(cntr != 0)
printf(",");
if((cntr % 16 == 0) && (cntr != 0))
printf("\n");
printf("0x%02x", buf[cntr]);
}
printf("}\n");
}
return 0;
}
#define BUFLEN (576 + 14 + 20 + 8)
#define DHCP_MSG_TYPE_DISCOVER (1)
#define DHCP_MSG_TYPE_OFFER (2)
#define DHCP_MSG_TYPE_REQUEST (3)
#define DHCP_MSG_TYPE_ACK (4)
int tick_it(uint32_t nticks)
{
uint32_t i = 0;
for (i = 0; i < nticks; i++) {
pico_stack_tick();
}
return 0;
}

View File

@ -0,0 +1,93 @@
/* RB tree unit test */
typedef struct
{
int value;
}elem;
int compare(void *a, void *b);
int compare(void *a, void *b)
{
return ((elem *)a)->value - ((elem *)b)->value;
}
static PICO_TREE_DECLARE(test_tree, compare);
static PICO_TREE_DECLARE(test_tree2, compare);
#define RBTEST_SIZE 20000
START_TEST (test_rbtree2)
{
struct pico_tree_node *s;
elem *e;
int i, last;
struct timeval start, end;
gettimeofday(&start, 0);
srand48(RBTEST_SIZE); /* use test-size as salt */
for (i = 0; i < (RBTEST_SIZE >> 1); i++)
{
e = malloc(sizeof(elem));
e->value = (int)lrand48() % RBTEST_SIZE;
if (pico_tree_findKey(&test_tree2, e)) {
free(e);
} else {
pico_tree_insert(&test_tree2, e);
}
}
gettimeofday(&end, 0);
printf("Rbtree test 2 inserted %d entries in %d milliseconds\n", RBTEST_SIZE,
(int)((end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000));
last = 0;
pico_tree_foreach(s, &test_tree2){
fail_if (last > ((elem *)(s->keyValue))->value, "error");
last = ((elem *)(s->keyValue))->value;
}
gettimeofday(&end, 0);
printf("Rbtree test 2 duration with %d entries: %d milliseconds\n", RBTEST_SIZE,
(int)((end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000));
printf("Test finished.\n");
}
END_TEST
START_TEST (test_rbtree)
{
struct pico_tree_node *s, *tmp;
elem t, *e;
int i;
struct timeval start, end;
printf("Started test...\n");
gettimeofday(&start, 0);
for (i = 0; i < (RBTEST_SIZE >> 1); i++) {
e = malloc(sizeof(elem));
e->value = i;
pico_tree_insert(&test_tree, e);
/* RB_INSERT(rbtree, &RBTREE, e); */
e = malloc(sizeof(elem));
e->value = (RBTEST_SIZE - 1) - i;
pico_tree_insert(&test_tree, e);
}
i = 0;
pico_tree_foreach(s, &test_tree){
fail_if (i++ != ((elem *)(s->keyValue))->value, "error");
}
t.value = RBTEST_SIZE >> 2;
e = pico_tree_findKey(&test_tree, &t);
fail_if(!e, "Search failed...");
fail_if(e->value != t.value, "Wrong element returned...");
pico_tree_foreach_reverse_safe(s, &test_tree, tmp){
fail_if(!s, "Reverse safe returned null");
e = (elem *)pico_tree_delete(&test_tree, s->keyValue);
free(e);
}
fail_if(!pico_tree_empty(&test_tree), "Not empty");
gettimeofday(&end, 0);
printf("Rbtree test duration with %d entries: %d milliseconds\n", RBTEST_SIZE,
(int)((end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000));
printf("Test finished...\n");
}
END_TEST

View File

@ -0,0 +1,521 @@
int pico_aodv_init(void)
{
return 0;
}
START_TEST (test_socket)
{
int ret = 0;
uint16_t port_be = 0, porta, proto, port_got;
char buf[] = "test";
struct pico_socket *sk_tcp, *sk_udp, *s, *sl, *sa;
struct pico_device *dev;
struct pico_ip4 inaddr_dst, inaddr_link, inaddr_incorrect, inaddr_uni, inaddr_null, netmask, orig, inaddr_got;
int getnodelay = -1;
int nodelay = -1;
int count = 0;
uint32_t getsocket_buffer = 0;
uint32_t socket_buffer = 0;
pico_stack_init();
printf("START SOCKET TEST\n");
pico_string_to_ipv4("224.7.7.7", &inaddr_dst.addr);
pico_string_to_ipv4("10.40.0.2", &inaddr_link.addr);
pico_string_to_ipv4("224.8.8.8", &inaddr_incorrect.addr);
pico_string_to_ipv4("0.0.0.0", &inaddr_null.addr);
pico_string_to_ipv4("10.40.0.3", &inaddr_uni.addr);
dev = pico_null_create("dummy");
netmask.addr = long_be(0xFFFF0000);
ret = pico_ipv4_link_add(dev, inaddr_link, netmask);
fail_if(ret < 0, "socket> error adding link");
/* socket_open passing wrong parameters */
s = pico_socket_open(PICO_PROTO_IPV4, 99, NULL);
fail_if(s != NULL, "Error got socket wrong parameters");
s = pico_socket_open(PICO_PROTO_IPV4, 0xFFFF, NULL);
fail_if(s != NULL, "Error got socket");
s = pico_socket_open(99, PICO_PROTO_UDP, NULL);
fail_if(s != NULL, "Error got socket");
s = pico_socket_open(0xFFFF, PICO_PROTO_UDP, NULL);
fail_if(s != NULL, "Error got socket");
sk_tcp = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, NULL);
fail_if(sk_tcp == NULL, "socket> tcp socket open failed");
port_be = short_be(5555);
/* socket_bind passing wrong parameters */
ret = pico_socket_bind(NULL, &inaddr_link, &port_be);
fail_if(ret == 0, "socket> tcp socket bound wrong parameter");
ret = pico_socket_bind(sk_tcp, NULL, &port_be);
fail_if(ret == 0, "socket> tcp socket bound wrong parameter");
ret = pico_socket_bind(sk_tcp, &inaddr_link, NULL);
fail_if(ret == 0, "socket> tcp socket bound wrong parameter");
/* socket_getname passing wrong parameters */
ret = pico_socket_getname(NULL, &inaddr_link, &port_be, &proto);
fail_if(ret == 0, "socket> tcp socket getname with wrong parameter");
ret = pico_socket_getname(sk_tcp, NULL, &port_be, &proto);
fail_if(ret == 0, "socket> tcp socket getname with wrong parameter");
ret = pico_socket_getname(sk_tcp, &inaddr_link, NULL, &proto);
fail_if(ret == 0, "socket> tcp socket getname with wrong parameter");
ret = pico_socket_getname(sk_tcp, &inaddr_link, &port_be, NULL);
fail_if(ret == 0, "socket> tcp socket getname with wrong parameter");
/* socket_bind passing correct parameters */
ret = pico_socket_bind(sk_tcp, &inaddr_link, &port_be);
fail_if(ret < 0, "socket> tcp socket bind failed");
count = pico_count_sockets(PICO_PROTO_TCP);
printf("Count: %d\n", count);
fail_unless(count == 1);
count = pico_count_sockets(0);
printf("Count: %d\n", count);
fail_unless(count == 1);
sk_udp = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, NULL);
fail_if(sk_udp == NULL, "socket> udp socket open failed");
port_be = short_be(5555);
ret = pico_socket_bind(sk_udp, &inaddr_link, &port_be);
fail_if(ret < 0, "socket> udp socket bind failed");
fail_if (pico_count_sockets(PICO_PROTO_UDP) != 1);
fail_if (pico_count_sockets(0) != 2);
ret = pico_socket_getname(sk_udp, &inaddr_got, &port_got, &proto);
fail_if(ret < 0, "socket> udp socket getname failed");
fail_if(inaddr_got.addr != inaddr_link.addr, "Getname: Address is different");
fail_if(port_be != port_got, "Getname: Port is different");
fail_if(proto != PICO_PROTO_IPV4, "Getname: proto is wrong");
/* socket_close passing wrong parameter */
ret = pico_socket_close(NULL);
fail_if(ret == 0, "Error socket close with wrong parameters");
/* socket_connect passing wrong parameters */
ret = pico_socket_connect(sk_udp, NULL, port_be);
fail_if(ret == 0, "Error socket connect with wrong parameters");
ret = pico_socket_connect(NULL, &inaddr_dst, port_be);
fail_if(ret == 0, "Error socket connect with wrong parameters");
/* socket_connect passing correct parameters */
ret = pico_socket_connect(sk_udp, &inaddr_dst, port_be);
fail_if(ret < 0, "Error socket connect");
ret = pico_socket_connect(sk_tcp, &inaddr_dst, port_be);
fail_if(ret < 0, "Error socket connect");
/* testing listening socket */
sl = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, NULL);
fail_if(sl == NULL, "socket> tcp socket open failed");
port_be = short_be(6666);
ret = pico_socket_bind(sl, &inaddr_link, &port_be);
fail_if(ret < 0, "socket> tcp socket bind failed");
/* socket_listen passing wrong parameters */
ret = pico_socket_listen(sl, 0);
fail_if(ret == 0, "Error socket tcp socket listen done, wrong parameter");
ret = pico_socket_listen(NULL, 10);
fail_if(ret == 0, "Error socket tcp socket listen done, wrong parameter");
/* socket_listen passing correct parameters */
ret = pico_socket_listen(sl, 10);
fail_if(ret < 0, "socket> tcp socket listen failed: %s", strerror(pico_err));
/* socket_accept passing wrong parameters */
sa = pico_socket_accept(sl, &orig, NULL);
fail_if(sa != NULL, "Error socket tcp socket accept wrong argument");
sa = pico_socket_accept(sl, NULL, &porta);
fail_if(sa != NULL, "Error socket tcp socket accept wrong argument");
/* socket_accept passing correct parameters */
sa = pico_socket_accept(sl, &orig, &porta);
fail_if(sa == NULL && pico_err != PICO_ERR_EAGAIN, "socket> tcp socket accept failed: %s", strerror(pico_err));
ret = pico_socket_close(sl);
fail_if(ret < 0, "socket> tcp socket close failed: %s\n", strerror(pico_err));
/* testing socket read/write */
/* socket_write passing wrong parameters */
ret = pico_socket_write(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket write succeeded, wrong argument\n");
ret = pico_socket_write(sk_tcp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket write succeeded, wrong argument\n");
ret = pico_socket_write(sk_tcp, (void *)buf, 0);
fail_if(ret > 0, "Error socket write succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_write(sk_tcp, (void *)buf, sizeof(buf));
fail_if(ret < 0, "socket> tcp socket write failed: %s\n", strerror(pico_err));
/* socket_read passing wrong parameters */
ret = pico_socket_read(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket read succeeded, wrong argument\n");
ret = pico_socket_read(sk_tcp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket read succeeded, wrong argument\n");
ret = pico_socket_read(sk_tcp, (void *)buf, 0);
fail_if(ret > 0, "Error socket read succeeded, wrong argument\n");
/* socket_read passing correct parameters */
ret = pico_socket_read(sk_tcp, (void *)buf, sizeof(buf));
fail_if(ret < 0, "socket> tcp socket read failed, ret = %d: %s\n", ret, strerror(pico_err)); /* tcp_recv returns 0 when no frame !? */
/* send/recv */
/* socket_send passing wrong parameters */
ret = pico_socket_send(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket send succeeded, wrong argument\n");
ret = pico_socket_send(sk_tcp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket send succeeded, wrong argument\n");
ret = pico_socket_send(sk_tcp, (void *)buf, 0);
fail_if(ret > 0, "Error socket send succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_send(sk_tcp, (void *)buf, sizeof(buf));
fail_if(ret <= 0, "socket> tcp socket send failed: %s\n", strerror(pico_err));
/* socket_recv passing wrong parameters */
ret = pico_socket_recv(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket recv succeeded, wrong argument\n");
ret = pico_socket_recv(sk_tcp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket recv succeeded, wrong argument\n");
ret = pico_socket_recv(sk_tcp, (void *)buf, 0);
fail_if(ret > 0, "Error socket recv succeeded, wrong argument\n");
/* socket_recv passing correct parameters */
ret = pico_socket_recv(sk_tcp, (void *)buf, sizeof(buf));
fail_if(ret < 0, "socket> tcp socket recv failed, ret = %d: %s\n", ret, strerror(pico_err)); /* tcp_recv returns 0 when no frame !? */
/* sendto/recvfrom */
/* socket_sendto passing wrong parameters */
ret = pico_socket_sendto(NULL, (void *)buf, sizeof(buf), &inaddr_dst, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_tcp, NULL, sizeof(buf), &inaddr_dst, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_tcp, (void *)buf, 0, &inaddr_dst, port_be);
fail_if(ret > 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_tcp, (void *)buf, sizeof(buf), NULL, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_tcp, (void *)buf, sizeof(buf), &inaddr_dst, 0xFFFF);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_sendto(sk_tcp, (void *)buf, sizeof(buf), &inaddr_dst, short_be(5555));
fail_if(ret <= 0, "socket> udp socket sendto failed, ret = %d: %s\n", ret, strerror(pico_err));
/* socket_recvfrom passing wrong parameters */
ret = pico_socket_recvfrom(NULL, (void *)buf, sizeof(buf), &orig, &porta);
fail_if(ret >= 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_tcp, NULL, sizeof(buf), &orig, &porta);
fail_if(ret >= 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_tcp, (void *)buf, 0, &orig, &porta);
fail_if(ret > 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_tcp, (void *)buf, sizeof(buf), NULL, &porta);
fail_if(ret > 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_tcp, (void *)buf, sizeof(buf), &orig, NULL);
fail_if(ret > 0, "Error socket recvfrom succeeded, wrong argument\n");
/* socket_recvfrom passing correct parameters */
ret = pico_socket_recvfrom(sk_tcp, (void *)buf, sizeof(buf), &orig, &porta);
fail_if(ret != 0, "socket> tcp socket recvfrom failed, ret = %d: %s\n", ret, strerror(pico_err)); /* tcp_recv returns -1 when no frame !? */
/* testing socket read/write */
/* socket_write passing wrong parameters */
ret = pico_socket_write(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket write succeeded, wrong argument\n");
ret = pico_socket_write(sk_udp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket write succeeded, wrong argument\n");
ret = pico_socket_write(sk_udp, (void *)buf, 0);
fail_if(ret > 0, "Error socket write succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_write(sk_udp, (void *)buf, sizeof(buf));
fail_if(ret < 0, "socket> tcp socket write failed: %s\n", strerror(pico_err));
/* socket_read passing wrong parameters */
ret = pico_socket_read(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket read succeeded, wrong argument\n");
ret = pico_socket_read(sk_udp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket read succeeded, wrong argument\n");
ret = pico_socket_read(sk_udp, (void *)buf, 0);
fail_if(ret > 0, "Error socket read succeeded, wrong argument\n");
ret = pico_socket_read(sk_udp, (void *)buf, 0xFFFF + 1);
fail_if(ret >= 0, "Error socket read succeeded while len was > 0xFFFF");
/* socket_read passing correct parameters */
ret = pico_socket_read(sk_udp, (void *)buf, sizeof(buf));
fail_if(ret != 0, "socket> udp socket read failed, ret = %d: %s\n", ret, strerror(pico_err));
/* send/recv */
/* socket_send passing wrong parameters */
ret = pico_socket_send(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket send succeeded, wrong argument\n");
ret = pico_socket_send(sk_udp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket send succeeded, wrong argument\n");
ret = pico_socket_send(sk_udp, (void *)buf, 0);
fail_if(ret > 0, "Error socket send succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_send(sk_udp, (void *)buf, sizeof(buf));
fail_if(ret <= 0, "socket> tcp socket send failed: %s\n", strerror(pico_err));
/* socket_recv passing wrong parameters */
ret = pico_socket_recv(NULL, (void *)buf, sizeof(buf));
fail_if(ret == 0, "Error socket recv succeeded, wrong argument\n");
ret = pico_socket_recv(sk_udp, NULL, sizeof(buf));
fail_if(ret == 0, "Error socket recv succeeded, wrong argument\n");
ret = pico_socket_recv(sk_udp, (void *)buf, 0);
fail_if(ret > 0, "Error socket recv succeeded, wrong argument\n");
ret = pico_socket_recv(sk_udp, (void *)buf, 0xFFFF + 1);
fail_if(ret >= 0, "Error socket recv succeeded while len was > 0xFFFF");
/* socket_recv passing correct parameters */
ret = pico_socket_recv(sk_udp, (void *)buf, sizeof(buf));
fail_if(ret != 0, "socket> udp socket recv failed, ret = %d: %s\n", ret, strerror(pico_err));
/* sendto/recvfrom */
/* socket_sendto passing wrong parameters */
ret = pico_socket_sendto(NULL, (void *)buf, sizeof(buf), &inaddr_dst, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_udp, NULL, sizeof(buf), &inaddr_dst, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_udp, (void *)buf, 0, &inaddr_dst, port_be);
fail_if(ret > 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_udp, (void *)buf, sizeof(buf), NULL, port_be);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
ret = pico_socket_sendto(sk_udp, (void *)buf, sizeof(buf), &inaddr_dst, 0xFFFF);
fail_if(ret >= 0, "Error socket sendto succeeded, wrong argument\n");
/* socket_write passing correct parameters */
ret = pico_socket_sendto(sk_udp, (void *)buf, sizeof(buf), &inaddr_dst, short_be(5555));
fail_if(ret <= 0, "socket> udp socket sendto failed, ret = %d: %s\n", ret, strerror(pico_err));
/* socket_recvfrom passing wrong parameters */
ret = pico_socket_recvfrom(NULL, (void *)buf, sizeof(buf), &orig, &porta);
fail_if(ret >= 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_udp, NULL, sizeof(buf), &orig, &porta);
fail_if(ret >= 0, "Error socket recvfrom succeeded, wrong argument\n");
ret = pico_socket_recvfrom(sk_udp, (void *)buf, 0xFFFF + 1, &orig, &porta);
fail_if(ret >= 0, "Error socket recvfrom succeeded while len was > 0xFFFF");
/* socket_recvfrom passing correct parameters */
ret = pico_socket_recvfrom(sk_udp, (void *)buf, 0, &orig, &porta);
fail_if(ret != 0, "socket> udp socket recvfrom failed, ret = %d: %s\n", ret, strerror(pico_err));
ret = pico_socket_recvfrom(sk_udp, (void *)buf, sizeof(buf), &orig, &porta);
fail_if(ret != 0, "socket> udp socket recvfrom failed, ret = %d: %s\n", ret, strerror(pico_err));
/* temporary fix, until Nagle problems are analyzed and fixed */
{
nodelay = 0;
ret = pico_socket_setoption(sk_tcp, PICO_TCP_NODELAY, &nodelay);
}
/* setoption/getoption */
ret = pico_socket_getoption(sk_tcp, PICO_TCP_NODELAY, &getnodelay);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_TCP_NODELAY failed (err = %s)\n", strerror(pico_err));
fail_if(getnodelay != 0, "socket> socket_setoption: default PICO_TCP_NODELAY != 0 (nagle disabled by default)\n");
nodelay = 1;
ret = pico_socket_setoption(sk_tcp, PICO_TCP_NODELAY, &nodelay);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_TCP_NODELAY failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_TCP_NODELAY, &getnodelay);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_TCP_NODELAY failed\n");
fail_if(getnodelay == 0, "socket> socket_setoption: PICO_TCP_NODELAY is off (expected: on!)\n");
nodelay = 0;
ret = pico_socket_setoption(sk_tcp, PICO_TCP_NODELAY, &nodelay);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_TCP_NODELAY failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_TCP_NODELAY, &getnodelay);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_TCP_NODELAY failed\n");
fail_if(getnodelay != 0, "socket> socket_setoption: PICO_TCP_NODELAY is on (expected: off!)\n");
/* Set/get recv buffer (TCP) */
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != PICO_DEFAULT_SOCKETQ,
"socket> socket_setoption: default PICO_SOCKET_OPT_SNDBUF != DEFAULT\n");
socket_buffer = PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_tcp, PICO_SOCKET_OPT_RCVBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_RCVBUF is != than expected\n");
socket_buffer = 2 * PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_tcp, PICO_SOCKET_OPT_RCVBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_RCVBUF is != than expected\n");
/* Set/get send buffer (TCP) */
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != PICO_DEFAULT_SOCKETQ,
"socket> socket_setoption: default PICO_SOCKET_OPT_SNDBUF != DEFAULT got: %d exp: %d\n", getsocket_buffer, PICO_DEFAULT_SOCKETQ);
socket_buffer = PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_tcp, PICO_SOCKET_OPT_SNDBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_SNDBUF is != than expected\n");
socket_buffer = 2 * PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_tcp, PICO_SOCKET_OPT_SNDBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
ret = pico_socket_getoption(sk_tcp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_SNDBUF is != than expected\n");
/* Set/get recv buffer (UDP) */
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != PICO_DEFAULT_SOCKETQ,
"socket> socket_setoption: default PICO_SOCKET_OPT_SNDBUF != DEFAULT\n");
socket_buffer = PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_udp, PICO_SOCKET_OPT_RCVBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_RCVBUF is != than expected\n");
socket_buffer = 2 * PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_udp, PICO_SOCKET_OPT_RCVBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_RCVBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_RCVBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_RCVBUF is != than expected\n");
/* Set/get send buffer (UDP) */
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != PICO_DEFAULT_SOCKETQ,
"socket> socket_setoption: default PICO_SOCKET_OPT_SNDBUF != DEFAULT\n");
socket_buffer = PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_udp, PICO_SOCKET_OPT_SNDBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_SNDBUF is != than expected\n");
socket_buffer = 2 * PICO_DEFAULT_SOCKETQ;
ret = pico_socket_setoption(sk_udp, PICO_SOCKET_OPT_SNDBUF, &socket_buffer);
fail_if(ret < 0, "socket> socket_setoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
ret = pico_socket_getoption(sk_udp, PICO_SOCKET_OPT_SNDBUF, &getsocket_buffer);
fail_if(ret < 0, "socket> socket_getoption: supported PICO_SOCKET_OPT_SNDBUF failed\n");
fail_if(getsocket_buffer != socket_buffer, "UDP socket> socket_setoption: PICO_SOCKET_OPT_SNDBUF is != than expected\n");
/* Close sockets, eventually. */
ret = pico_socket_close(sk_tcp);
fail_if(ret < 0, "socket> tcp socket close failed: %s\n", strerror(pico_err));
ret = pico_socket_close(sk_udp);
fail_if(ret < 0, "socket> udp socket close failed: %s\n", strerror(pico_err));
}
END_TEST
#ifdef PICO_SUPPORT_CRC_FAULTY_UNIT_TEST
START_TEST (test_crc_check)
{
uint8_t buffer[64] = {
0x45, 0x00, 0x00, 0x40, /* start of IP hdr */
0x91, 0xc3, 0x40, 0x00,
0x40, 0x11, 0x24, 0xcf, /* last 2 bytes are CRC */
0xc0, 0xa8, 0x01, 0x66,
0xc0, 0xa8, 0x01, 0x64, /* end of IP hdr */
0x15, 0xb3, 0x1F, 0x90, /* start of UDP/TCP hdr */
0x00, 0x2c, 0x27, 0x22, /* end of UDP hdr */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x0b, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, /* end of TCP hdr */
0x01, 0x23, 0x45, 0x67, /* start of data */
0x89, 0xab, 0xcd, 0xef,
0xc0, 0xca, 0xc0, 0x1a
};
struct pico_frame *f = NULL;
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) buffer;
struct pico_udp_hdr *udp_hdr = NULL;
struct pico_tcp_hdr *tcp_hdr = NULL;
uint32_t *f_usage_count = NULL;
uint8_t *f_buffer = NULL;
int ret = -1;
printf("START CRC TEST\n");
pico_stack_init();
/* IPv4 CRC unit tests */
/* Allocated memory will not be freed when pico_ipv4_crc_check fails */
f = calloc(1, sizeof(struct pico_frame));
f_usage_count = calloc(1, sizeof(uint32_t));
f_buffer = calloc(1, sizeof(uint8_t));
f->net_hdr = buffer;
f->net_len = PICO_SIZE_IP4HDR;
f->transport_hdr = buffer + PICO_SIZE_IP4HDR;
f->transport_len = sizeof(buffer) - PICO_SIZE_IP4HDR;
f->usage_count = f_usage_count;
f->buffer = f_buffer;
*(f->usage_count) = 512;
hdr->crc = 0;
printf(">>>>>>>>>>>>>>>>>>>>> CRC VALUE = %X\n", pico_checksum(hdr, PICO_SIZE_IP4HDR));
hdr->crc = short_be(0x24CF); /* Make check pass */
ret = pico_ipv4_crc_check(f);
fail_if(ret == 0, "correct IPv4 checksum got rejected\n");
hdr->crc = short_be(0x8899); /* Make check fail */
ret = pico_ipv4_crc_check(f);
fail_if(ret == 1, "incorrect IPv4 checksum got accepted\n");
/* UDP CRC unit tests */
/* Allocated memory will be freed when pico_transport_crc_check fails */
f = calloc(1, sizeof(struct pico_frame));
f_usage_count = calloc(1, sizeof(uint32_t));
f_buffer = calloc(1, sizeof(uint8_t));
f->net_hdr = buffer;
f->transport_hdr = buffer + PICO_SIZE_IP4HDR;
f->transport_len = sizeof(buffer) - PICO_SIZE_IP4HDR;
f->usage_count = f_usage_count;
f->buffer = f_buffer;
*(f->usage_count) = 1;
hdr->proto = 0x11; /* UDP */
hdr->crc = short_be(0x24cf); /* Set IPv4 CRC correct */
udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
/* udp_hdr->crc = 0; */
/* printf(">>>>>>>>>>>>>>>>>>>>> UDP CRC VALUE = %X\n", pico_udp_checksum_ipv4(f)); */
ret = pico_transport_crc_check(f);
fail_if(ret == 0, "correct UDP checksum got rejected\n");
udp_hdr->crc = 0;
ret = pico_transport_crc_check(f);
fail_if(ret == 0, "UDP checksum of 0 did not get ignored\n");
udp_hdr->crc = short_be(0x8899); /* Make check fail */
ret = pico_transport_crc_check(f);
fail_if(ret == 1, "incorrect UDP checksum got accepted\n");
/* TCP CRC unit tests */
/* Allocated memory will be freed when pico_transport_crc_check fails */
f = calloc(1, sizeof(struct pico_frame));
f_usage_count = calloc(1, sizeof(uint32_t));
f_buffer = calloc(1, sizeof(uint8_t));
f->net_hdr = buffer;
f->transport_hdr = buffer + PICO_SIZE_IP4HDR;
f->transport_len = sizeof(buffer) - PICO_SIZE_IP4HDR;
f->usage_count = f_usage_count;
f->buffer = f_buffer;
*(f->usage_count) = 1;
hdr->proto = 0x06; /* TCP */
hdr->crc = short_be(0x24cf); /* Set IPv4 CRC correct */
tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
tcp_hdr->seq = long_be(0x002c2722); /* Set sequence number correct */
/* tcp_hdr = 0; */
/* printf(">>>>>>>>>>>>>>>>>>>>> TCP CRC VALUE = %X\n", pico_tcp_checksum_ipv4(f)); */
tcp_hdr->crc = short_be(0x0016); /* Set correct TCP CRC */
ret = pico_transport_crc_check(f);
fail_if(ret == 0, "correct TCP checksum got rejected\n");
tcp_hdr->crc = short_be(0x8899); /* Make check fail */
ret = pico_transport_crc_check(f);
fail_if(ret == 1, "incorrect TCP checksum got accepted\n");
}
END_TEST
#endif

View File

@ -0,0 +1,40 @@
#define EXISTING_TIMERS 7
START_TEST (test_timers)
{
uint32_t T[128];
int i;
struct pico_timer_ref *tref;
pico_stack_init();
for (i = 0; i < 128; i++) {
pico_time expire = (pico_time)(999999 + i);
void (*timer)(pico_time, void *) =(void (*)(pico_time, void *))0xff00 + i;
void *arg = ((void*)0xaa00 + i);
T[i] = pico_timer_add(expire, timer, arg);
printf("New timer %u\n", T[i]);
}
for (i = 0; i < 128; i++) {
void (*timer)(pico_time, void *) =(void (*)(pico_time, void *))0xff00 + i;
void *arg = ((void*)0xaa00 + i);
fail_if((uint32_t)(i + 1) > Timers->n);
tref = heap_get_element(Timers, (uint32_t)i + EXISTING_TIMERS);
fail_unless(tref->id == T[i]);
fail_unless(tref->tmr->timer == timer);
fail_unless(tref->tmr->arg == arg);
}
for (i = 127; i >= 0; i--) {
printf("Deleting timer %d \n", i );
pico_timer_cancel(T[i]);
printf("Deleted timer %d \n", i );
tref = heap_get_element(Timers, (uint32_t)i + EXISTING_TIMERS);
fail_unless(tref->tmr == NULL);
}
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
pico_stack_tick();
}
END_TEST