1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

tests/gcoap_fileserver: add integration test for GCoAP fileserver

This commit is contained in:
Benjamin Valentin 2022-06-12 22:22:54 +02:00
parent 66452d15ae
commit c5282bb2ad
4 changed files with 308 additions and 0 deletions

View File

@ -0,0 +1,46 @@
include ../Makefile.tests_common
USEMODULE += auto_init_gnrc_netif
USEMODULE += auto_init_gnrc_rpl
USEMODULE += gnrc_ipv6_router_default
USEMODULE += gnrc_icmpv6_echo
USEMODULE += gnrc_rpl
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += gcoap_fileserver
USEMODULE += nanocoap_vfs
USEMODULE += constfs
USEMODULE += vfs_default
USEMODULE += vfs_auto_format
USEMODULE += md5sum
# automated test only works on native
TEST_ON_CI_WHITELIST += native
# use small blocksize for test to increase chance for errors
CFLAGS += -DCONFIG_NANOCOAP_BLOCKSIZE_DEFAULT=COAP_BLOCKSIZE_16
CFLAGS += -DCONFIG_COAP_ACK_TIMEOUT_MS=100UL
CFLAGS += -DCONFIG_COAP_MAX_RETRANSMIT=10
ifeq (native, $(BOARD))
USEMODULE += socket_zep
USEMODULE += socket_zep_hello
USEMODULE += netdev
TERMFLAGS += -z 127.0.0.1:17754 # Murdock has no IPv6 support
else
USEMODULE += netdev_default
endif
.PHONY: host-tools
# Build zep_dispatch
host-tools:
$(Q)env -u CC -u CFLAGS $(MAKE) -C $(RIOTTOOLS)
TERMDEPS += host-tools
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,46 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a3bu-xplained \
blackpill \
bluepill \
bluepill-stm32f030c8 \
derfmega128 \
i-nucleo-lrwan1 \
im880b \
m1284p \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \
nucleo-f030r8 \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-f302r8 \
nucleo-f303k8 \
nucleo-f334r8 \
nucleo-l011k4 \
nucleo-l031k6 \
nucleo-l053r8 \
samd10-xmini \
saml10-xpro \
saml11-xpro \
slstk3400a \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
stm32f7508-dk \
stm32g0316-disco \
stm32l0538-disco \
stm32mp157c-dk2 \
telosb \
waspmote-pro \
z1 \
zigduino \
#

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2022 ML!PA Consulting GmbH
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief test application for the GCoAP file server
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
* @}
*/
#include "fs/constfs.h"
#include "net/gcoap.h"
#include "net/gcoap/fileserver.h"
#include "shell.h"
#include "vfs_default.h"
#define MAIN_QUEUE_SIZE (4)
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
/* CoAP resources. Must be sorted by path (ASCII order). */
static const coap_resource_t _resources[] = {
{ "/const", COAP_GET | COAP_MATCH_SUBTREE, gcoap_fileserver_handler, "/const" },
};
static gcoap_listener_t _listener = {
.resources = _resources,
.resources_len = ARRAY_SIZE(_resources),
};
static const char song[] =
"Join us now and share the software;\n"
"You'll be free, hackers, you'll be free.\n"
"Join us now and share the software;\n"
"You'll be free, hackers, you'll be free.\n"
"\n"
"Hoarders can get piles of money,\n"
"That is true, hackers, that is true.\n"
"But they cannot help their neighbors;\n"
"That's not good, hackers, that's not good.\n"
"\n"
"When we have enough free software\n"
"At our call, hackers, at our call,\n"
"We'll kick out those dirty licenses\n"
"Ever more, hackers, ever more.\n"
"\n"
"Join us now and share the software;\n"
"You'll be free, hackers, you'll be free.\n"
"Join us now and share the software;\n"
"You'll be free, hackers, you'll be free.\n";
/* this defines two const files in the constfs */
static constfs_file_t constfs_files[] = {
{
.path = "/song.txt",
.size = sizeof(song),
.data = song,
},
};
/* this is the constfs specific descriptor */
static constfs_t constfs_desc = {
.nfiles = ARRAY_SIZE(constfs_files),
.files = constfs_files,
};
/* constfs mount point, as for previous example, it needs a file system driver,
* a mount point and private_data as a pointer to the constfs descriptor */
static vfs_mount_t const_mount = {
.fs = &constfs_file_system,
.mount_point = "/const",
.private_data = &constfs_desc,
};
int main(void)
{
vfs_mount(&const_mount);
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
gcoap_register_listener(&_listener);
char line_buf[SHELL_DEFAULT_BUFSIZE];
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
return 0;
}

View File

@ -0,0 +1,122 @@
#!/usr/bin/env python3
# Copyright (C) 2022 Benjamin Valentin
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
import subprocess
import time
from subprocess import Popen
from riotctrl_shell.gnrc import GNRCICMPv6Echo, GNRCICMPv6EchoParser
from riotctrl_shell.netif import Ifconfig
from riotctrl.ctrl import RIOTCtrlBoardFactory
from riotctrl_ctrl import native
from riotctrl_shell.netif import IfconfigListParser
PARSERS = {
"ping6": GNRCICMPv6EchoParser(),
"ifconfig": IfconfigListParser(),
}
class RIOTCtrlAppFactory(RIOTCtrlBoardFactory):
def __init__(self):
super().__init__(board_cls={
'native': native.NativeRIOTCtrl,
})
self.ctrl_list = list()
def __enter__(self):
return self
def __exit__(self, *exc):
for ctrl in self.ctrl_list:
ctrl.stop_term()
def get_shell(self, application_directory='.', env={'BOARD': 'native'}):
# retrieve a RIOTCtrl Object
ctrl = super().get_ctrl(
env=env,
application_directory=application_directory
)
# append ctrl to list
self.ctrl_list.append(ctrl)
# start terminal
ctrl.start_term()
# return ctrl with started terminal
return Shell(ctrl)
def get_shells(self, num=1):
terms = []
for i in range(num):
terms.append(self.get_shell())
return terms
class Shell(Ifconfig, GNRCICMPv6Echo):
pass
def first_netif_and_addr_by_scope(ifconfig_out, scope):
netifs = PARSERS["ifconfig"].parse(ifconfig_out)
key = next(iter(netifs))
netif = netifs[key]
return (
key,
[addr["addr"] for addr in netif["ipv6_addrs"] if addr["scope"] == scope][0],
)
def global_addr(ifconfig_out):
return first_netif_and_addr_by_scope(ifconfig_out, "global")
def test_linear_topology(factory, zep_dispatch):
# linear topology with 3 nodes and 25% packet loss
topology = ("A C 0.75\n"
"C B 0.75\n")
zep_dispatch.stdin.write(topology.encode())
zep_dispatch.stdin.close()
# create native instances
nodes = factory.get_shells(3)
A = nodes[0]
B = nodes[2]
# add prefix to root node
A.cmd("nib prefix add 7 2001:db8::/32")
A.cmd("ifconfig 7 add 2001:db8::1/32")
A.cmd("rpl root 0 2001:db8::1")
# wait for the creation of the DODAG
time.sleep(10)
# Download file from CoAP server
B.cmd("vfs rm /nvm0/song.txt")
B.cmd("ncget coap://[2001:db8::1]/const/song.txt", timeout=60)
# make sure the content matches
assert A.cmd("md5sum /const/song.txt").split()[2] == B.cmd("md5sum /nvm0/song.txt").split()[2]
# terminate nodes
for n in nodes:
n.stop_term()
def run_test(func, factory):
with Popen(['../../dist/tools/zep_dispatch/bin/zep_dispatch',
'-t', '-', '127.0.0.1', '17754'], stdin=subprocess.PIPE) as zep_dispatch:
try:
func(factory, zep_dispatch)
finally:
zep_dispatch.terminate()
if __name__ == "__main__":
with RIOTCtrlAppFactory() as factory:
run_test(test_linear_topology, factory)