mirror of https://github.com/ARMmbed/mbed-os.git
commit
1eab0723ba
|
@ -88,3 +88,9 @@ tags
|
|||
.vscode/
|
||||
|
||||
features/FEATURE_BLE/targets/TARGET_CORDIO/stack_backup/
|
||||
|
||||
.pytest_cache
|
||||
log
|
||||
|
||||
# Icetea related file
|
||||
test_suite.json
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "mbed.h"
|
||||
#include "mbed-client-cli/ns_cmdline.h"
|
||||
|
||||
#ifndef ICETEA_EXAMPLE_ENABLED
|
||||
#error [NOT_SUPPORTED] Skipping example application.
|
||||
#endif
|
||||
/**
|
||||
* Macros for setting console flow control.
|
||||
*/
|
||||
#define CONSOLE_FLOWCONTROL_RTS 1
|
||||
#define CONSOLE_FLOWCONTROL_CTS 2
|
||||
#define CONSOLE_FLOWCONTROL_RTSCTS 3
|
||||
#define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x
|
||||
#define mbed_console_concat(x) mbed_console_concat_(x)
|
||||
#define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL)
|
||||
|
||||
#define SERIAL_CONSOLE_BAUD_RATE 115200
|
||||
|
||||
void cmd_ready_cb(int retcode)
|
||||
{
|
||||
cmd_next(retcode);
|
||||
}
|
||||
|
||||
void wrap_printf(const char *f, va_list a)
|
||||
{
|
||||
vprintf(f, a);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
cmd_init(&wrap_printf);
|
||||
|
||||
int c;
|
||||
while ((c = getchar()) != EOF) {
|
||||
cmd_char_input(c);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
FileHandle *mbed::mbed_override_console(int)
|
||||
{
|
||||
static UARTSerial console(STDIO_UART_TX, STDIO_UART_RX, SERIAL_CONSOLE_BAUD_RATE);
|
||||
#if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
|
||||
console.set_flow_control(SerialBase::RTS, STDIO_UART_RTS, NC);
|
||||
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
|
||||
console.set_flow_control(SerialBase::CTS, NC, STDIO_UART_CTS);
|
||||
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
|
||||
console.set_flow_control(SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS);
|
||||
#endif
|
||||
return &console;
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "NetworkStack.h"
|
||||
#include "NetworkInterface.h"
|
||||
|
||||
#include "mbed-client-cli/ns_cmdline.h"
|
||||
#include "mbed-trace/mbed_trace.h"
|
||||
|
||||
#include "ip4string.h"
|
||||
|
||||
#define WIFI 2
|
||||
#if !defined(MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE) || \
|
||||
(MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE == WIFI && !defined(MBED_CONF_NSAPI_DEFAULT_WIFI_SSID))
|
||||
#error [NOT_SUPPORTED] No network configuration found for this target.
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define TRACE_GROUP "Aifc"
|
||||
|
||||
NetworkInterface *net;
|
||||
|
||||
NetworkInterface *get_interface(void)
|
||||
{
|
||||
return net;
|
||||
}
|
||||
|
||||
int cmd_ifup(int argc, char *argv[]);
|
||||
int cmd_ifdown(int argc, char *argv[]);
|
||||
int cmd_ifconfig(int argc, char *argv[]);
|
||||
|
||||
const char *MAN_IFCONFIG = " ifup interface up\r\n"\
|
||||
" ifdown interface down\r\n";
|
||||
|
||||
static void ifconfig_print()
|
||||
{
|
||||
if (!net) {
|
||||
cmd_printf("No interface configured\r\n");
|
||||
return;
|
||||
}
|
||||
const char *str = net->get_ip_address();
|
||||
if (str) {
|
||||
uint8_t buf[4];
|
||||
if (stoip4(str, strlen(str), buf)) {
|
||||
cmd_printf("IPv4 if addr: %s\r\n", str);
|
||||
} else {
|
||||
cmd_printf("IPv6 if addr:\r\n [0]: %s\r\n", str);
|
||||
}
|
||||
} else {
|
||||
cmd_printf("No IP address\r\n");
|
||||
}
|
||||
str = net->get_mac_address();
|
||||
if (str) {
|
||||
cmd_printf("MAC-48: %s\r\n", str);
|
||||
} else {
|
||||
cmd_printf("MAC-48: unknown\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmd_ifconfig_init(void)
|
||||
{
|
||||
cmd_add("ifup", cmd_ifup, "ifconfig up", MAN_IFCONFIG);
|
||||
cmd_add("ifdown", cmd_ifdown, "ifconfig down", MAN_IFCONFIG);
|
||||
cmd_add("ifconfig", cmd_ifconfig, "ifconfig", MAN_IFCONFIG);
|
||||
}
|
||||
|
||||
int cmd_ifconfig(int argc, char *argv[])
|
||||
{
|
||||
ifconfig_print();
|
||||
return CMDLINE_RETCODE_SUCCESS;
|
||||
}
|
||||
|
||||
int cmd_ifup(int argc, char *argv[])
|
||||
{
|
||||
if (!net) {
|
||||
net = NetworkInterface::get_default_instance();
|
||||
}
|
||||
int err = net->connect();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
return CMDLINE_RETCODE_FAIL;
|
||||
}
|
||||
|
||||
ifconfig_print();
|
||||
return CMDLINE_RETCODE_SUCCESS;
|
||||
}
|
||||
|
||||
int cmd_ifdown(int argc, char *argv[])
|
||||
{
|
||||
if (!net) {
|
||||
return CMDLINE_RETCODE_FAIL;
|
||||
}
|
||||
int err = net->disconnect();
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
return CMDLINE_RETCODE_FAIL;
|
||||
}
|
||||
|
||||
return CMDLINE_RETCODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *networkstack_error_to_str(int errorcode)
|
||||
{
|
||||
switch (errorcode) {
|
||||
case NSAPI_ERROR_OK:
|
||||
return "NSAPI_ERROR_OK";
|
||||
case NSAPI_ERROR_WOULD_BLOCK:
|
||||
return "NSAPI_ERROR_WOULD_BLOCK";
|
||||
case NSAPI_ERROR_UNSUPPORTED:
|
||||
return "NSAPI_ERROR_UNSUPPORTED";
|
||||
case NSAPI_ERROR_PARAMETER:
|
||||
return "NSAPI_ERROR_PARAMETER";
|
||||
case NSAPI_ERROR_NO_CONNECTION:
|
||||
return "NSAPI_ERROR_NO_CONNECTION";
|
||||
case NSAPI_ERROR_NO_SOCKET:
|
||||
return "NSAPI_ERROR_NO_SOCKET";
|
||||
case NSAPI_ERROR_NO_ADDRESS:
|
||||
return "NSAPI_ERROR_NO_ADDRESS";
|
||||
case NSAPI_ERROR_NO_MEMORY:
|
||||
return "NSAPI_ERROR_NO_MEMORY";
|
||||
case NSAPI_ERROR_NO_SSID:
|
||||
return "NSAPI_ERROR_NO_SSID";
|
||||
case NSAPI_ERROR_DNS_FAILURE:
|
||||
return "NSAPI_ERROR_DNS_FAILURE";
|
||||
case NSAPI_ERROR_DHCP_FAILURE:
|
||||
return "NSAPI_ERROR_DHCP_FAILURE";
|
||||
case NSAPI_ERROR_AUTH_FAILURE:
|
||||
return "NSAPI_ERROR_AUTH_FAILURE";
|
||||
case NSAPI_ERROR_DEVICE_ERROR:
|
||||
return "NSAPI_ERROR_DEVICE_ERROR";
|
||||
case NSAPI_ERROR_IN_PROGRESS:
|
||||
return "NSAPI_ERROR_IN_PROGRESS";
|
||||
case NSAPI_ERROR_ALREADY:
|
||||
return "NSAPI_ERROR_ALREADY";
|
||||
case NSAPI_ERROR_IS_CONNECTED:
|
||||
return "NSAPI_ERROR_IS_CONNECTED";
|
||||
case NSAPI_ERROR_CONNECTION_LOST:
|
||||
return "NSAPI_ERROR_CONNECTION_LOST";
|
||||
case NSAPI_ERROR_CONNECTION_TIMEOUT:
|
||||
return "NSAPI_ERROR_CONNECTION_TIMEOUT";
|
||||
default:
|
||||
return "unknown error code";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef CMD_IFCONFIG_H
|
||||
#define CMD_IFCONFIG_H
|
||||
|
||||
#include "NetworkInterface.h"
|
||||
#include "NetworkStack.h"
|
||||
|
||||
/** Get a pointer to a network interface instance
|
||||
*
|
||||
* Allowed interface types (depend on application configurations):
|
||||
* cell0, wlan0, eth0, mesh0
|
||||
*
|
||||
* @return pointer to the network interface, or NULL if unrecognized or ambiguous
|
||||
*/
|
||||
NetworkInterface *get_interface(void);
|
||||
|
||||
void cmd_ifconfig_init(void);
|
||||
const char *networkstack_error_to_str(int errorcode);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef CMD_SOCKET_H_
|
||||
#define CMD_SOCKET_H_
|
||||
|
||||
#include "nsapi_types.h"
|
||||
|
||||
int handle_nsapi_error(const char *function, nsapi_error_t ret);
|
||||
int handle_nsapi_size_or_error(const char *function, nsapi_size_or_error_t ret);
|
||||
void cmd_socket_init(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "mbed.h"
|
||||
#include "mbed-client-cli/ns_cmdline.h"
|
||||
#include "cmd_ifconfig.h"
|
||||
#include "cmd_socket.h"
|
||||
|
||||
/**
|
||||
* Macros for setting console flow control.
|
||||
*/
|
||||
#define CONSOLE_FLOWCONTROL_RTS 1
|
||||
#define CONSOLE_FLOWCONTROL_CTS 2
|
||||
#define CONSOLE_FLOWCONTROL_RTSCTS 3
|
||||
#define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x
|
||||
#define mbed_console_concat(x) mbed_console_concat_(x)
|
||||
#define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL)
|
||||
|
||||
#define SERIAL_CONSOLE_BAUD_RATE 115200
|
||||
|
||||
void cmd_ready_cb(int retcode)
|
||||
{
|
||||
cmd_next(retcode);
|
||||
}
|
||||
|
||||
void wrap_printf(const char *f, va_list a)
|
||||
{
|
||||
vprintf(f, a);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
cmd_init(&wrap_printf);
|
||||
cmd_ifconfig_init();
|
||||
cmd_socket_init();
|
||||
|
||||
int c;
|
||||
while ((c = getchar()) != EOF) {
|
||||
cmd_char_input(c);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
FileHandle *mbed::mbed_override_console(int)
|
||||
{
|
||||
static UARTSerial console(STDIO_UART_TX, STDIO_UART_RX, SERIAL_CONSOLE_BAUD_RATE);
|
||||
#if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
|
||||
console.set_flow_control(SerialBase::RTS, STDIO_UART_RTS, NC);
|
||||
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
|
||||
console.set_flow_control(SerialBase::CTS, NC, STDIO_UART_CTS);
|
||||
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
|
||||
console.set_flow_control(SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS);
|
||||
#endif
|
||||
return &console;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"macros": [
|
||||
"MEM_ALLOC=malloc",
|
||||
"MEM_FREE=free",
|
||||
"MBED_HEAP_STATS_ENABLED=1",
|
||||
"MBED_MEM_TRACING_ENABLED"
|
||||
],
|
||||
"target_overrides": {
|
||||
"*": {
|
||||
"target.features_add": ["LWIP", "COMMON_PAL"],
|
||||
"mbed-trace.enable": 1,
|
||||
"platform.stdio-baud-rate": 115200,
|
||||
"platform.stdio-convert-newlines": true,
|
||||
"platform.stdio-buffered-serial": true,
|
||||
"platform.stdio-flush-at-exit": true,
|
||||
"drivers.uart-serial-rxbuf-size": 768
|
||||
},
|
||||
"UBLOX_EVK_ODIN_W2" : {
|
||||
"target.device_has_remove": ["EMAC"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "ip6string.h"
|
||||
#include "strconv.h"
|
||||
|
||||
|
||||
int8_t strtohex(uint8_t *out, const char *str, int8_t max_length)
|
||||
{
|
||||
int8_t i = 0;
|
||||
char *rd = (char *)str;
|
||||
uint8_t *wr = out;
|
||||
while (*rd != 0) {
|
||||
if (i > max_length) {
|
||||
break;
|
||||
}
|
||||
*wr++ = strtoul(rd, &rd, 16);
|
||||
while (!isxdigit((int)*rd) && *rd != 0) {
|
||||
rd++; //skip some invalid characters
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int hexstr_to_bytes_inplace(char *str)
|
||||
{
|
||||
int16_t len, i, j;
|
||||
if (str == NULL) {
|
||||
return -1;
|
||||
}
|
||||
len = strlen(str);
|
||||
if (len < 2 || (len + 1) % 3 != 0) {
|
||||
return -1;
|
||||
}
|
||||
for (i = 0, j = 0; i < len; i += 3, ++j) {
|
||||
str[j] = (char)strtol(str + i, 0, 16);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
// convert hex string (eg. "76 ab ff") to binary array
|
||||
int string_to_bytes(const char *str, uint8_t *buf, int bytes)
|
||||
{
|
||||
int len = strlen(str);
|
||||
if (len <= (3 * bytes - 1)) {
|
||||
int i;
|
||||
for (i = 0; i < bytes; i++) {
|
||||
if (i * 3 < len) {
|
||||
buf[i] = (uint8_t)strtoul(str + i * 3, 0, 16);
|
||||
} else {
|
||||
buf[i] = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int16_t hextostr(const uint8_t *buf, uint16_t buf_length, char *out, int16_t out_length, char delimiter)
|
||||
{
|
||||
int16_t outLeft = out_length;
|
||||
int16_t arrLeft = buf_length;
|
||||
const uint8_t *rd = buf;
|
||||
int retcode = 0;
|
||||
char *wr = out;
|
||||
while (arrLeft > 0 && outLeft > 0) {
|
||||
retcode = snprintf(wr, outLeft, "%02x", *rd);
|
||||
|
||||
if (retcode <= 0 || retcode >= outLeft) {
|
||||
break;
|
||||
}
|
||||
outLeft -= retcode;
|
||||
wr += retcode;
|
||||
arrLeft --;
|
||||
rd++;
|
||||
if (delimiter && arrLeft > 0 && outLeft > 0) {
|
||||
*wr++ = delimiter;
|
||||
outLeft--;
|
||||
*wr = 0;
|
||||
}
|
||||
}
|
||||
return (int16_t)(wr - out);
|
||||
}
|
||||
int replace_hexdata(char *str)
|
||||
{
|
||||
char *ptr = str;
|
||||
if (str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
while (*ptr) {
|
||||
if (ptr[0] == '\\') {
|
||||
if (ptr[1] == 'n') {
|
||||
ptr[0] = 0x0a;
|
||||
memmove(ptr + 1, ptr + 2, strlen(ptr + 2) + 1);
|
||||
} else if (ptr[1] == 'r') {
|
||||
ptr[0] = 0x0d;
|
||||
memmove(ptr + 1, ptr + 2, strlen(ptr + 2) + 1);
|
||||
} else if (ptr[1] == 'x') {
|
||||
char *end;
|
||||
ptr[0] = (char)strtoul(ptr + 2, &end, 16);
|
||||
memmove(ptr + 1, end, strlen(end) + 1);
|
||||
} else if (isdigit((int)ptr[1])) {
|
||||
char *end;
|
||||
ptr[0] = strtoul(ptr + 1, &end, 10);
|
||||
memmove(ptr + 1, end, strlen(end) + 1);
|
||||
}
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
return ptr - str;
|
||||
}
|
||||
bool is_visible(uint8_t *buf, int len)
|
||||
{
|
||||
while (len--) {
|
||||
if (!isalnum(*buf) && *buf != ' ') {
|
||||
return false;
|
||||
}
|
||||
buf++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char *strdupl(const char *str)
|
||||
{
|
||||
if (!str) {
|
||||
return NULL;
|
||||
}
|
||||
char *p = malloc(strlen(str) + 1);
|
||||
if (!p) {
|
||||
return p;
|
||||
}
|
||||
strcpy(p, str);
|
||||
return p;
|
||||
}
|
||||
int strnlen_(const char *s, int n)
|
||||
{
|
||||
char *end = memchr(s, 0, n);
|
||||
return end ? end - s : n;
|
||||
}
|
||||
char *strndupl(const char *s, int n)
|
||||
{
|
||||
char *p = NULL;
|
||||
int len = strnlen_(s, n);
|
||||
p = malloc(len + 1);
|
||||
if (!p) {
|
||||
return p;
|
||||
}
|
||||
p[len] = 0;
|
||||
return memcpy(p, s, len);
|
||||
}
|
||||
int strnicmp_(char const *a, char const *b, int n)
|
||||
{
|
||||
for (; (n > 0 && *a != 0 && *b != 0) ; a++, b++, n--) {
|
||||
int d = tolower((int) * a) - tolower((int) * b);
|
||||
if (d != 0 || !*a) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* HELPING PRINT FUNCTIONS for cmd_printf */
|
||||
|
||||
static inline uint8_t context_split_mask(uint_fast8_t split_value)
|
||||
{
|
||||
return (uint8_t) - (0x100u >> split_value);
|
||||
}
|
||||
|
||||
static uint8_t *bitcopy(uint8_t *restrict dst, const uint8_t *restrict src, uint_fast8_t bits)
|
||||
{
|
||||
uint_fast8_t bytes = bits / 8;
|
||||
bits %= 8;
|
||||
|
||||
if (bytes) {
|
||||
dst = (uint8_t *) memcpy(dst, src, bytes) + bytes;
|
||||
src += bytes;
|
||||
}
|
||||
|
||||
if (bits) {
|
||||
uint_fast8_t split_bit = context_split_mask(bits);
|
||||
*dst = (*src & split_bit) | (*dst & ~ split_bit);
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
char tmp_print_buffer[128] = {0};
|
||||
|
||||
char *print_ipv6(const void *addr_ptr)
|
||||
{
|
||||
ip6tos(addr_ptr, tmp_print_buffer);
|
||||
return tmp_print_buffer;
|
||||
}
|
||||
char *print_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len)
|
||||
{
|
||||
char *str = tmp_print_buffer;
|
||||
int retval;
|
||||
char tmp[40];
|
||||
uint8_t addr[16] = {0};
|
||||
|
||||
if (prefix_len != 0) {
|
||||
if (prefix == NULL || prefix_len > 128) {
|
||||
return "<err>";
|
||||
}
|
||||
bitcopy(addr, prefix, prefix_len);
|
||||
}
|
||||
|
||||
ip6tos(addr, tmp);
|
||||
retval = snprintf(str, 128, "%s/%u", tmp, prefix_len);
|
||||
if (retval <= 0) {
|
||||
return "";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
char *print_array(const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
int16_t retcode = hextostr(buf, len, tmp_print_buffer, 128, ':');
|
||||
if (retcode > 0) {
|
||||
//yeah, something is converted
|
||||
}
|
||||
return tmp_print_buffer;
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2018 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef STRCONVERSION_H
|
||||
#define STRCONVERSION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ns_types.h"
|
||||
|
||||
/** Convert hex string to binary array
|
||||
* e.g.
|
||||
* char str[] = {30, 31, 32, 33};
|
||||
* uint8_t buffer[4];
|
||||
* strtohex( buffer, str, 4 );
|
||||
*/
|
||||
int8_t strtohex(uint8_t *out, const char *str, int8_t max_length);
|
||||
|
||||
/** Convert space separated hex string (eg. "76 ab ff") to binary array.
|
||||
*/
|
||||
int string_to_bytes(const char *str, uint8_t *buf, int bytes);
|
||||
|
||||
/** Convert a colon/space separated hex string (eg. "76:ab:ff") to binary
|
||||
* array (inplace) returning the number of the bytes in the array.
|
||||
*/
|
||||
int hexstr_to_bytes_inplace(char *str);
|
||||
|
||||
/** Convert hex array to string
|
||||
*/
|
||||
int16_t hextostr(const uint8_t *buf, uint16_t buf_length, char *out, int16_t out_length, char delimiter);
|
||||
/** Replace hex characters from string
|
||||
* e.g.
|
||||
* "hello\\n" -> "hello\n"
|
||||
* "hello\\r" -> "hello\r"
|
||||
* "val: \\10" -> "val: \x0a" //integer
|
||||
* "val: \\x10" -> "val: \x10" //hex value
|
||||
* @param str string that will be replaced
|
||||
* @return length
|
||||
*/
|
||||
int replace_hexdata(char *str);
|
||||
/**
|
||||
* check if array contains only visible characters
|
||||
* = isalpha | isdigit
|
||||
*/
|
||||
bool is_visible(uint8_t *buf, int len);
|
||||
|
||||
/** Convert ipv6 address to string format
|
||||
*/
|
||||
char *print_ipv6(const void *addr_ptr);
|
||||
/** Convert ipv6 prefix to string format
|
||||
*/
|
||||
char *print_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len);
|
||||
/** Convert binary array to string format and return static results
|
||||
*/
|
||||
char *print_array(const uint8_t *buf, uint16_t len);
|
||||
/** The strdupl() function shall return a pointer to a new string,
|
||||
* which is a duplicate of the string pointed to by s1. The returned pointer can be passed to free().
|
||||
* A null pointer is returned if the new string cannot be created.
|
||||
* strdupl are same than linux strdup, but this way we avoid to duplicate reference in linux
|
||||
*/
|
||||
char *strdupl(const char *str);
|
||||
/** The strdup() function returns a pointer to a new string which is a duplicate of the string.
|
||||
* Memory for the new string is obtained with malloc(3), and can be freed with free(3).
|
||||
* The strndup() function is similar, but only copies at most n bytes. If s is longer than n,
|
||||
* only n bytes are copied, and a terminating null byte ('\0') is added.
|
||||
*/
|
||||
char *strndupl(const char *s, int n);
|
||||
/** strnlen - determine the length of a fixed-size string
|
||||
* The strnlen() function returns the number of bytes in the string pointed to by s, excluding the terminating null bye ('\0'), but at most maxlen.
|
||||
* In doing this, strnlen() looks only at the first maxlen bytes at s and never beyond s+maxlen.
|
||||
* The strnlen() function returns strlen(s), if that is less than maxlen, or maxlen if there is no null byte ('\0')
|
||||
* among the first maxlen bytes pointed to by s.
|
||||
*/
|
||||
int strnlen_(const char *s, int n);
|
||||
/** strnicmp compares a and b without sensitivity to case.
|
||||
* All alphabetic characters in the two arguments a and b are converted to lowercase before the comparison.
|
||||
*/
|
||||
int strnicmp_(char const *a, char const *b, int n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
import re
|
||||
import time
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
|
||||
from icetea_lib.Plugin.PluginBase import PluginBase
|
||||
|
||||
|
||||
class IpTestParsers(PluginBase):
|
||||
# constructor
|
||||
def __init__(self):
|
||||
super(IpTestParsers, self).__init__()
|
||||
|
||||
def get_parsers(self):
|
||||
return {
|
||||
'ifconfig': self.__ifconfigParser,
|
||||
'ifup': self.__ifconfigParser,
|
||||
'ethup': self.__ifconfigParser,
|
||||
'dut1': self.__ifconfigParser,
|
||||
'dut2': self.__ifconfigParser,
|
||||
'dut3': self.__ifconfigParser,
|
||||
'dut4': self.__ifconfigParser,
|
||||
'dut5': self.__ifconfigParser,
|
||||
'dut6': self.__ifconfigParser,
|
||||
'socket': self.__mbedossocketParser,
|
||||
'ticker': self.__ticker_parser
|
||||
}
|
||||
|
||||
# socket command for mbedos
|
||||
def __mbedossocketParser(self, response):
|
||||
results = {'socket_id': None,
|
||||
'data_type': None,
|
||||
'data': "",
|
||||
'printed_bytes': None,
|
||||
'sent_bytes': None,
|
||||
'received_bytes': None,
|
||||
'address': None,
|
||||
'port': None,
|
||||
'loop_id': None
|
||||
}
|
||||
respLines = response.lines
|
||||
part = None
|
||||
for line in respLines:
|
||||
ret = PluginBase.find_one(line, ".*sid: ([0-9]+)")
|
||||
if ret is not False:
|
||||
results['socket_id'] = ret
|
||||
|
||||
ret = PluginBase.find_one(line, ".*(hex|string) data, printing .* bytes:")
|
||||
if ret is not False:
|
||||
results['data_type'] = ret
|
||||
|
||||
ret = PluginBase.find_one(line, ".*data, printing (.*) bytes:")
|
||||
if ret is not False:
|
||||
part = "data"
|
||||
|
||||
ret = PluginBase.find_one(line, "^Printed (.*) bytes$")
|
||||
if ret is not False:
|
||||
results['printed_bytes'] = int(ret)
|
||||
part = None
|
||||
|
||||
if part == "data":
|
||||
ret = PluginBase.find_one(line, "^\d{4}: (.*)$")
|
||||
if ret is not False:
|
||||
results['data'] = results['data'] + ret
|
||||
|
||||
ret = PluginBase.find_one(line, ".*sent: ([0-9]+) bytes")
|
||||
if ret is not False:
|
||||
results['sent_bytes'] = int(ret)
|
||||
|
||||
ret = PluginBase.find_one(line, ".*received: ([0-9]+) bytes")
|
||||
if ret is not False:
|
||||
results['received_bytes'] = int(ret)
|
||||
|
||||
ret = PluginBase.find_one(line, ".*address: ([0-9a-fxA-F:.]+)")
|
||||
if ret is not False:
|
||||
results['address'] = ret
|
||||
|
||||
ret = PluginBase.find_one(line, ".*port: ([0-9]+)")
|
||||
if ret is not False:
|
||||
results['port'] = ret
|
||||
|
||||
ret = PluginBase.find_one(line, ".*lid: ([0-9]+)")
|
||||
if ret is not False:
|
||||
results['loop_id'] = ret
|
||||
|
||||
return results
|
||||
|
||||
# response parser for ifup
|
||||
def __ifconfigParser(self, response):
|
||||
results = {}
|
||||
lines = response.traces
|
||||
part = None
|
||||
|
||||
results['address'] = {
|
||||
'll': '',
|
||||
'globals': [],
|
||||
'ipv4': None,
|
||||
'ipv6': []
|
||||
}
|
||||
|
||||
for line in lines:
|
||||
# print "ifcfgparser: %s" % line
|
||||
match = re.search('IPv6 if addr', line)
|
||||
if match:
|
||||
part = "address"
|
||||
match = re.search('IPv4 if addr', line)
|
||||
if match:
|
||||
part = "address"
|
||||
match = re.search('MAC-48\:[\W]{1,}(.*)', line)
|
||||
if match:
|
||||
mac48 = match.group(1)
|
||||
# Validate the MAC-48 syntax as well
|
||||
match = re.search("([0-9a-fA-F]{2}:??){5}([0-9a-fA-F]{2})", mac48)
|
||||
if match:
|
||||
results['MAC'] = mac48
|
||||
|
||||
if part == "address":
|
||||
match = re.search('.*\[(\d)\]:\W([abcdefg\d\:]{5,})', line)
|
||||
if match:
|
||||
addr = match.group(2)
|
||||
if re.search('^fe80\:\:', addr):
|
||||
results['address']['ll'] = addr
|
||||
else:
|
||||
results['address']["globals"].append(addr)
|
||||
|
||||
match = re.search('\[(\d)\]:\W([a-fA-F\d\:]{5,})', line)
|
||||
if match:
|
||||
results['address']['ipv6'].append(match.group(2))
|
||||
|
||||
match = re.search('(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$', line)
|
||||
if match:
|
||||
results['address']['ipv4'] = match.group(1)
|
||||
|
||||
return results
|
||||
|
||||
def __ticker_parser(self, response):
|
||||
results = {}
|
||||
respLines = response.lines
|
||||
for line in respLines:
|
||||
ret = PluginBase.find_one(line, 'Ticker id: ([0-9]+)')
|
||||
if ret is not False:
|
||||
results['ticker_id'] = ret
|
||||
return results
|
|
@ -0,0 +1,19 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
from ip_test_parsers import IpTestParsers
|
||||
|
||||
plugins_to_load = {
|
||||
"ip_test_parsers": IpTestParsers
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
## Running Icetea tests located under mbed-os
|
||||
|
||||
### Structure
|
||||
|
||||
mbed-os has a folder called TEST_APPS that contains everything related to Icetea testing.
|
||||
There are currently 3 folders:
|
||||
|
||||
- device - contains all the different test applications you can flash to your board
|
||||
- icetea-plugins - contains plugins that are being used by some of the testcases, needed for the test execution
|
||||
- testcases - contains Icetea testcases written in Python
|
||||
|
||||
The testcases depends on test applications
|
||||
|
||||
### Preparing your work environment
|
||||
|
||||
#### Prerequisities
|
||||
|
||||
You need Icetea and mbed-cli that supports Icetea, installed.
|
||||
|
||||
#### Selecting the network interface to use
|
||||
|
||||
Depending on a device, there might be a default network interface type defined in the mbed-os/targets/targets.json, which is used to locate a test-config file by default.
|
||||
If there is not, or you want to use a different interface than the default, you need to provide a relevant test-config -file to the mbed test with --test-config option.
|
||||
The test-config file contains the necessary information for the test application, there are some test-config files located under mbed-os/tools/test-configs.
|
||||
Devices which have their network drivers residing inside mbed-os can use generic test-configs like HeapBlockDeviceAndEthernetInterface.json and HeapBlockDeviceAndWifiInterface.json. Otherwise you need to use a device specific test-config.
|
||||
|
||||
### Running the tests
|
||||
|
||||
Now that the interface has been selected you can run the icetea tests from the mbed-os root on your command line by
|
||||
|
||||
`>mbed test -m <target> -t <toolchain> --icetea`
|
||||
|
||||
This command will compile the mbed-os, then compiles the test applications, creates a test suite and then starts running the tests.
|
||||
|
||||
If you want only to run some specific tests, you can use the -n -option. You can list multiple tests by separating them by comma (,).
|
||||
|
||||
`>mbed test -m <target> -t <toolchain> --icetea -n test1,test2`
|
||||
|
||||
#### Running the tests with specifig test-config
|
||||
|
||||
Some devices may offer multiple network interfaces to operate with. For example, UBLOX_EVK_ODIN_W2 offers ethernet and Wi-Fi capabilities.
|
||||
The tests can be run for either one of those using already existing test-config -files.
|
||||
|
||||
To run the tests with Wi-Fi interface:
|
||||
`>mbed test -m UBLOX_EVK_ODIN_W2 -t <toolchain> --icetea --test-config tools/test-configs/HeapBlockDeviceAndWifiInterface.json`
|
||||
|
||||
To run the tests with ethernet interface:
|
||||
`>mbed test -m UBLOX_EVK_ODIN_W2 -t <toolchain> --icetea --test-config tools/test-configs/HeapBlockDeviceAndEthernetInterface.json`
|
||||
|
||||
#### Providing Wi-Fi access point information
|
||||
|
||||
If you are using Wi-Fi interface for running the tests, you need to provide also information about the used access point.
|
||||
The information can be provided in the used test-config file.
|
||||
|
||||
Example of access point information:
|
||||
```
|
||||
"target_overrides": {
|
||||
"*": {
|
||||
"target.network-default-interface-type": "WIFI",
|
||||
"nsapi.default-wifi-ssid": "\"ssid\"",
|
||||
"nsapi.default-wifi-password": "\"password\"",
|
||||
"nsapi.default-wifi-security": "WPA_WPA2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test results
|
||||
|
||||
Icetea prints the results from the test run to the command line, and the final result looks similar to this.
|
||||
|
||||
```
|
||||
+--------------------------------+---------+-------------+-------------+-----------+----------+
|
||||
| Testcase | Verdict | Fail Reason | Skip Reason | platforms | duration |
|
||||
+--------------------------------+---------+-------------+-------------+-----------+----------+
|
||||
| test_cmdline | pass | | | K64F | 8.555 |
|
||||
| UDPSOCKET_BIND_PORT | pass | | | K64F | 19.614 |
|
||||
| TCPSOCKET_BIND_PORT | pass | | | K64F | 15.852 |
|
||||
| TCPSERVER_ACCEPT | pass | | | K64F | 41.629 |
|
||||
| TCPSOCKET_ECHOTEST_BURST_SHORT | pass | | | K64F | 19.926 |
|
||||
+--------------------------------+---------+-------------+-------------+-----------+----------+
|
||||
+---------------+----------------+
|
||||
| Summary | |
|
||||
+---------------+----------------+
|
||||
| Final Verdict | PASS |
|
||||
| count | 5 |
|
||||
| passrate | 100.00 % |
|
||||
| pass | 5 |
|
||||
| Duration | 0:01:45.576000 |
|
||||
+---------------+----------------+
|
||||
```
|
||||
|
||||
The results from the tests can also be found in the mbed-os/log folder.
|
||||
You probably want to add the log folder to your .mbedignore file to prevent issues with build commands becoming too long over the time.
|
|
@ -0,0 +1,50 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from icetea_lib.bench import Bench
|
||||
|
||||
|
||||
class Testcase(Bench):
|
||||
def __init__(self):
|
||||
Bench.__init__(self,
|
||||
name="test_cmdline",
|
||||
title="Smoke test for command line interface",
|
||||
status="released",
|
||||
purpose="Verify Command Line Interface",
|
||||
component=["cmdline"],
|
||||
type="smoke",
|
||||
requirements={
|
||||
"duts": {
|
||||
'*': {
|
||||
"count": 1,
|
||||
"type": "hardware",
|
||||
"application": {
|
||||
"name": "TEST_APPS-device-exampleapp"
|
||||
}
|
||||
},
|
||||
"1": {"nick": "dut1"},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
def setup(self):
|
||||
pass
|
||||
|
||||
def case(self):
|
||||
self.command("dut1", "echo hello world")
|
||||
self.command("dut1", "help")
|
||||
|
||||
def teardown(self):
|
||||
pass
|
|
@ -0,0 +1,71 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
from icetea_lib.bench import Bench
|
||||
from icetea_lib.tools import test_case
|
||||
|
||||
|
||||
class MultipleTestcase(Bench):
|
||||
def __init__(self, **kwargs):
|
||||
testcase_args = {
|
||||
'status': "released",
|
||||
'component': ["mbed-os", "netsocket"],
|
||||
'type': "smoke",
|
||||
'subtype': "socket",
|
||||
'requirements': {
|
||||
"duts": {
|
||||
"*": {
|
||||
"count": 1,
|
||||
"type": "hardware",
|
||||
"application": {"name": "TEST_APPS-device-socket_app"}
|
||||
},
|
||||
"1": {"nick": "dut1"},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testcase_args.update(kwargs)
|
||||
Bench.__init__(self, **testcase_args)
|
||||
|
||||
def setup(self):
|
||||
self.command("dut1", "ifup")
|
||||
|
||||
def socket_bind_port(self, socket_type):
|
||||
response = self.command("dut1", "socket new " + socket_type)
|
||||
socket_id = int(response.parsed['socket_id'])
|
||||
|
||||
self.command("dut1", "socket " + str(socket_id) + " open")
|
||||
|
||||
self.command("dut1", "socket " + str(socket_id) + " bind port 1024")
|
||||
|
||||
self.command("dut1", "socket " + str(socket_id) + " delete")
|
||||
|
||||
def teardown(self):
|
||||
self.command("dut1", "ifdown")
|
||||
|
||||
|
||||
@test_case(MultipleTestcase,
|
||||
name="TCPSOCKET_BIND_PORT",
|
||||
title="tcpsocket open and bind port",
|
||||
purpose="Verify TCPSocket can be created, opened and port binded")
|
||||
def test1(self):
|
||||
self.socket_bind_port("TCPSocket")
|
||||
|
||||
|
||||
@test_case(MultipleTestcase,
|
||||
name="UDPSOCKET_BIND_PORT",
|
||||
title="udpsocket open and bind port",
|
||||
purpose="Verify UDPSocket can be created, opened and port binded")
|
||||
def test2(self):
|
||||
self.socket_bind_port("UDPSocket")
|
|
@ -0,0 +1,103 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import threading
|
||||
import time
|
||||
|
||||
from icetea_lib.TestStepError import TestStepFail
|
||||
from icetea_lib.bench import Bench
|
||||
from interface import interfaceUp, interfaceDown
|
||||
|
||||
|
||||
class Testcase(Bench):
|
||||
def __init__(self):
|
||||
Bench.__init__(self,
|
||||
name="TCPSERVER_ACCEPT",
|
||||
title="TCPSERVER_ACCEPT",
|
||||
purpose="Test that TCPServer::bind(), TCPServer::listen() and TCPServer::accept() works",
|
||||
status="released",
|
||||
component=["mbed-os", "netsocket"],
|
||||
author="Juha Ylinen <juha.ylinen@arm.com>",
|
||||
type="smoke",
|
||||
subtype="socket",
|
||||
requirements={
|
||||
"duts": {
|
||||
'*': { # requirements for all nodes
|
||||
"count": 2,
|
||||
"type": "hardware",
|
||||
"application": {"name": "TEST_APPS-device-socket_app"}
|
||||
},
|
||||
"1": {"nick": "dut1"},
|
||||
"2": {"nick": "dut2"}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
def setup(self):
|
||||
interface = interfaceUp(self, ["dut1"])
|
||||
self.server_ip = interface["dut1"]["ip"]
|
||||
interface = interfaceUp(self, ["dut2"])
|
||||
self.client_ip = interface["dut2"]["ip"]
|
||||
|
||||
def clientThread(self):
|
||||
self.logger.info("Starting")
|
||||
time.sleep(5) # wait accept from server
|
||||
self.command("dut2", "socket " + str(self.client_socket_id) + " open")
|
||||
self.command("dut2", "socket " + str(self.client_socket_id) + " connect " + str(self.server_ip) + " " + str(
|
||||
self.used_port))
|
||||
|
||||
def case(self):
|
||||
self.used_port = 2000
|
||||
|
||||
response = self.command("dut1", "socket new TCPServer")
|
||||
server_base_socket_id = int(response.parsed['socket_id'])
|
||||
|
||||
self.command("dut1", "socket " + str(server_base_socket_id) + " open")
|
||||
self.command("dut1", "socket " + str(server_base_socket_id) + " bind port " + str(self.used_port))
|
||||
self.command("dut1", "socket " + str(server_base_socket_id) + " listen")
|
||||
|
||||
response = self.command("dut1", "socket new TCPSocket")
|
||||
server_socket_id = int(response.parsed['socket_id'])
|
||||
self.command("dut1", "socket " + str(server_socket_id) + " open")
|
||||
|
||||
response = self.command("dut2", "socket new TCPSocket")
|
||||
zero = response.timedelta
|
||||
self.client_socket_id = int(response.parsed['socket_id'])
|
||||
|
||||
# Create a thread which calls client connect()
|
||||
t = threading.Thread(name='clientThread', target=self.clientThread)
|
||||
t.start()
|
||||
|
||||
wait = 5
|
||||
response = self.command("dut1", "socket " + str(server_base_socket_id) + " accept " + str(server_socket_id))
|
||||
response.verify_response_duration(expected=wait, zero=zero, threshold_percent=10, break_in_fail=True)
|
||||
socket_id = int(response.parsed['socket_id'])
|
||||
|
||||
t.join()
|
||||
self.command("dut1", "socket " + str(socket_id) + " send hello")
|
||||
|
||||
response = self.command("dut2", "socket " + str(self.client_socket_id) + " recv 5")
|
||||
data = response.parsed['data'].replace(":", "")
|
||||
|
||||
if data != "hello":
|
||||
raise TestStepFail("Received data doesn't match the sent data")
|
||||
|
||||
self.command("dut1", "socket " + str(server_socket_id) + " delete")
|
||||
self.command("dut1", "socket " + str(server_base_socket_id) + " delete")
|
||||
self.command("dut2", "socket " + str(self.client_socket_id) + " delete")
|
||||
|
||||
def teardown(self):
|
||||
interfaceDown(self, ["dut1"])
|
||||
interfaceDown(self, ["dut2"])
|
|
@ -0,0 +1,78 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
import string
|
||||
|
||||
from icetea_lib.Randomize.randomize import Randomize
|
||||
from icetea_lib.bench import Bench, TestStepFail
|
||||
|
||||
|
||||
class Testcase(Bench):
|
||||
def __init__(self):
|
||||
Bench.__init__(self,
|
||||
name="TCPSOCKET_ECHOTEST_BURST_SHORT",
|
||||
title="TCPSOCKET_ECHOTEST_BURST_SHORT",
|
||||
purpose="Verify that TCPSocket can send burst of packets to echo server and read incoming packets",
|
||||
status="released",
|
||||
component=["mbed-os", "netsocket"],
|
||||
author="Juha Ylinen <juha.ylinen@arm.com>",
|
||||
type="smoke",
|
||||
subtype="socket",
|
||||
requirements={
|
||||
"duts": {
|
||||
'*': { # requirements for all nodes
|
||||
"count": 1,
|
||||
"type": "hardware",
|
||||
"application": {
|
||||
"name": "TEST_APPS-device-socket_app"
|
||||
}
|
||||
},
|
||||
"1": {"nick": "dut1"},
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
def setup(self):
|
||||
self.command("dut1", "ifup")
|
||||
|
||||
def case(self):
|
||||
response = self.command("dut1", "socket new TCPSocket")
|
||||
socket_id = int(response.parsed['socket_id'])
|
||||
|
||||
self.command("dut1", "socket " + str(socket_id) + " open")
|
||||
self.command("dut1", "socket " + str(socket_id) + " connect echo.mbedcloudtesting.com 7")
|
||||
|
||||
for i in range(2):
|
||||
sentData = ""
|
||||
for size in (100, 200, 300, 120, 500):
|
||||
packet = Randomize.random_string(max_len=size, min_len=size, chars=string.ascii_uppercase)
|
||||
sentData += packet
|
||||
response = self.command("dut1", "socket " + str(socket_id) + " send " + str(packet))
|
||||
response.verify_trace("TCPSocket::send() returned: " + str(size))
|
||||
|
||||
received = 0
|
||||
data = ""
|
||||
totalSize = 1220
|
||||
while received < totalSize:
|
||||
response = self.command("dut1", "socket " + str(socket_id) + " recv " + str(totalSize))
|
||||
data += response.parsed['data'].replace(":", "")
|
||||
received += int(response.parsed['received_bytes'])
|
||||
|
||||
if data != sentData:
|
||||
raise TestStepFail("Received data doesn't match the sent data")
|
||||
|
||||
self.command("dut1", "socket " + str(socket_id) + " delete")
|
||||
|
||||
def teardown(self):
|
||||
self.command("dut1", "ifdown")
|
|
@ -0,0 +1,43 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
from icetea_lib.TestStepError import TestStepFail
|
||||
|
||||
'''
|
||||
This interface script is intended to be a common library to be used in testcase scripts by testers.
|
||||
It delegates setUp and tearDown functions with different provided network interface types using setUp() and tearDown() methods.
|
||||
'''
|
||||
|
||||
|
||||
def interfaceUp(tc, duts):
|
||||
interfaces = {}
|
||||
for dut in duts:
|
||||
interface = {dut: {"ipv4": None, "ipv6": None}}
|
||||
|
||||
resp = tc.command("%s" % dut, "ifup")
|
||||
|
||||
ip = interface[dut]["ip"] = interface[dut]["ipv4"] = resp.parsed["address"]["ipv4"]
|
||||
if not ip:
|
||||
if resp.parsed["address"]["ipv6"]:
|
||||
ip = interface[dut]["ip"] = interface[dut]["ipv6"] = resp.parsed["address"]["ipv6"][0]
|
||||
if not ip:
|
||||
raise TestStepFail("Failed to parse IP address")
|
||||
|
||||
interfaces.update(interface)
|
||||
return interfaces
|
||||
|
||||
|
||||
def interfaceDown(tc, duts):
|
||||
for dut in duts:
|
||||
tc.command(dut, "ifdown")
|
|
@ -0,0 +1,406 @@
|
|||
/*
|
||||
* Copyright (c) 2016 ARM Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file ns_cmdline.h
|
||||
*
|
||||
* Command line library - mbedOS shell
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* \code
|
||||
* //simple print function
|
||||
* void myprint(const char* fmt, va_list ap){ vprintf(fmt, ap); }
|
||||
* // simple ready cb, which call next command to be execute
|
||||
* void cmd_ready_cb(int retcode) { cmd_next( retcode ); }
|
||||
*
|
||||
* // dummy command with some option
|
||||
* int cmd_dummy(int argc, char *argv[]){
|
||||
* if( cmd_has_option(argc, argv, "o") ) {
|
||||
* cmd_printf("This is o option");
|
||||
* } else {
|
||||
* return CMDLINE_RETCODE_INVALID_PARAMETERS;
|
||||
* }
|
||||
* return CMDLINE_RETCODE_SUCCESS;
|
||||
*}
|
||||
* // timer cb ( pseudo-timer-code )
|
||||
* void timer_ready_cb(void) {
|
||||
* cmd_ready(CMDLINE_RETCODE_SUCCESS);
|
||||
* }
|
||||
* // long command, which need e.g. some events to finalize command execution
|
||||
* int cmd_long(int argc, char *argv[] ) {
|
||||
timer_start( 5000, timer_ready_cb );
|
||||
* return CMDLINE_RETCODE_EXCUTING_CONTINUE;
|
||||
* }
|
||||
* void main(void) {
|
||||
* cmd_init( &myprint ); // initialize cmdline with print function
|
||||
* cmd_set_ready_cb( cmd_ready_cb ); // configure ready cb
|
||||
* cmd_add("dummy", cmd_dummy, 0, 0); // add one dummy command
|
||||
* cmd_add("long", cmd_long, 0, 0); // add one dummy command
|
||||
* //execute dummy and long commands
|
||||
* cmd_exe( "dymmy;long" );
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
#ifndef _CMDLINE_H_
|
||||
#define _CMDLINE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CMDLINE_RETCODE_COMMAND_BUSY 2 //!< Command Busy
|
||||
#define CMDLINE_RETCODE_EXCUTING_CONTINUE 1 //!< Execution continue in background
|
||||
#define CMDLINE_RETCODE_SUCCESS 0 //!< Execution Success
|
||||
#define CMDLINE_RETCODE_FAIL -1 //!< Execution Fail
|
||||
#define CMDLINE_RETCODE_INVALID_PARAMETERS -2 //!< Command parameters was incorrect
|
||||
#define CMDLINE_RETCODE_COMMAND_NOT_IMPLEMENTED -3 //!< Command not implemented
|
||||
#define CMDLINE_RETCODE_COMMAND_CB_MISSING -4 //!< Command callback function missing
|
||||
#define CMDLINE_RETCODE_COMMAND_NOT_FOUND -5 //!< Command not found
|
||||
|
||||
/**
|
||||
* typedef for print functions
|
||||
*/
|
||||
typedef void (cmd_print_t)(const char *, va_list);
|
||||
/**
|
||||
* Initialize cmdline class.
|
||||
* This is command line editor without any commands. Application
|
||||
* needs to add commands that should be enabled.
|
||||
* usage e.g.
|
||||
* \code
|
||||
cmd_init( &default_cmd_response_out );
|
||||
* \endcode
|
||||
* \param outf console printing function (like vprintf)
|
||||
*/
|
||||
void cmd_init(cmd_print_t *outf);
|
||||
/** Command ready function for __special__ cases.
|
||||
* This need to be call if command implementation return CMDLINE_RETCODE_EXECUTING_CONTINUE
|
||||
* because there is some background stuff ongoing before command is finally completed.
|
||||
* Normally there is some event, which call cmd_ready().
|
||||
* \param retcode return code for command
|
||||
*/
|
||||
void cmd_ready(int retcode);
|
||||
/** typedef for ready cb function */
|
||||
typedef void (cmd_ready_cb_f)(int);
|
||||
/**
|
||||
* Configure cb which will be called after commands are executed
|
||||
* or cmd_ready is called
|
||||
* \param cb callback function for command ready
|
||||
*/
|
||||
void cmd_set_ready_cb(cmd_ready_cb_f *cb);
|
||||
/**
|
||||
* execute next command if any
|
||||
* \param retcode last command return value
|
||||
*/
|
||||
void cmd_next(int retcode);
|
||||
/** Free cmd class */
|
||||
void cmd_free(void);
|
||||
/** Reset cmdline to default values
|
||||
* detach external commands, delete all variables and aliases
|
||||
*/
|
||||
void cmd_reset(void);
|
||||
/** Configure command history size (default 32)
|
||||
* \param max maximum history size
|
||||
* max > 0 -> configure new value
|
||||
* max = 0 -> just return current value
|
||||
* \return current history max-size
|
||||
*/
|
||||
uint8_t cmd_history_size(uint8_t max);
|
||||
/** command line print function
|
||||
* This function should be used when user want to print something to the console
|
||||
* \param fmt console print function (like printf)
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__CC_ARM)
|
||||
void cmd_printf(const char *fmt, ...) __attribute__ ((__format__(__printf__, 1, 2)));
|
||||
#else
|
||||
void cmd_printf(const char *fmt, ...);
|
||||
#endif
|
||||
/** command line print function
|
||||
* This function should be used when user want to print something to the console with vprintf functionality
|
||||
* \param fmt The format string is a character string, beginning and ending in its initial shift state, if any. The format string is composed of zero or more directives.
|
||||
* \param ap list of parameters needed by format string. This must correspond properly with the conversion specifier.
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__CC_ARM)
|
||||
void cmd_vprintf(const char *fmt, va_list ap) __attribute__ ((__format__(__printf__, 1, 0)));
|
||||
#else
|
||||
void cmd_vprintf(const char *fmt, va_list ap);
|
||||
#endif
|
||||
/** Reconfigure default cmdline out function (cmd_printf)
|
||||
* \param outf select console print function
|
||||
*/
|
||||
void cmd_out_func(cmd_print_t *outf);
|
||||
/** Configure function, which will be called when Ctrl+A is pressed
|
||||
* \param sohf control function which called every time when user input control keys
|
||||
*/
|
||||
void cmd_ctrl_func(void (*sohf)(uint8_t c));
|
||||
/**
|
||||
* Configure mutex wait function
|
||||
* By default, cmd_printf calls may not be thread safe, depending on the implementation of the used output.
|
||||
* This can be used to set a callback function that will be called before each cmd_printf call.
|
||||
* The specific implementation is up to the application developer, but simple mutex locking is assumed.
|
||||
*/
|
||||
void cmd_mutex_wait_func(void (*mutex_wait_f)(void));
|
||||
/**
|
||||
* Configure mutex wait function
|
||||
* By default, cmd_printf calls may not be thread safe, depending on the implementation of the used output.
|
||||
* This can be used to set a callback function that will be called after each cmd_printf call.
|
||||
* The specific implementation is up to the application developer, but simple mutex locking is assumed.
|
||||
*/
|
||||
void cmd_mutex_release_func(void (*mutex_release_f)(void));
|
||||
/**
|
||||
* Retrieve output mutex lock
|
||||
* This can be used to retrieve the output mutex when multiple cmd_printf/cmd_vprintf calls must be
|
||||
* guaranteed to be grouped together in a thread safe manner. Must be released by a following call to
|
||||
* cmd_mutex_unlock()
|
||||
* For example:
|
||||
* * \code
|
||||
* cmd_mutex_lock();
|
||||
for (i = 0; i < 10; i++) {
|
||||
cmd_printf("%02x ", i);
|
||||
}
|
||||
// without locking a print from another thread could happen here
|
||||
cmd_printf("\r\n);
|
||||
cmd_mutex_unlock();
|
||||
* \endcode
|
||||
* Exact behaviour depends on the implementation of the configured mutex,
|
||||
* but counting mutexes are required.
|
||||
*/
|
||||
void cmd_mutex_lock(void);
|
||||
/**
|
||||
* Release output mutex lock
|
||||
* This can be used to release the output mutex once it has been retrieved with cmd_mutex_lock()
|
||||
* Exact behaviour depends on the implementation of the configured mutex,
|
||||
* but counting mutexes are required.
|
||||
*/
|
||||
void cmd_mutex_unlock(void);
|
||||
/** Refresh output */
|
||||
void cmd_output(void);
|
||||
/** default cmd response function, use stdout
|
||||
* \param fmt The format string is a character string, beginning and ending in its initial shift state, if any. The format string is composed of zero or more directives.
|
||||
* \param ap list of parameters needed by format string. This must correspond properly with the conversion specifier.
|
||||
*/
|
||||
void default_cmd_response_out(const char *fmt, va_list ap);
|
||||
/** Initialize screen */
|
||||
void cmd_init_screen(void);
|
||||
/** Get echo state
|
||||
* \return true if echo is on otherwise false
|
||||
*/
|
||||
bool cmd_echo_state(void);
|
||||
/** Echo off */
|
||||
void cmd_echo_off(void);
|
||||
/** Echo on */
|
||||
void cmd_echo_on(void);
|
||||
/** Enter character to console.
|
||||
* insert key pressess to cmdline called from main loop of application
|
||||
* \param u_data char to be added to console
|
||||
*/
|
||||
void cmd_char_input(int16_t u_data);
|
||||
/*
|
||||
* Set the passthrough mode callback function. In passthrough mode normal command input handling is skipped and any
|
||||
* received characters are passed to the passthrough callback function. Setting this to null will disable passthrough mode.
|
||||
* \param passthrough_fnc The passthrough callback function
|
||||
*/
|
||||
typedef void (*input_passthrough_func_t)(uint8_t c);
|
||||
void cmd_input_passthrough_func(input_passthrough_func_t passthrough_fnc);
|
||||
|
||||
/* Methods used for adding and handling of commands and aliases
|
||||
*/
|
||||
|
||||
/** Callback called when your command is run.
|
||||
* \param argc argc is the count of arguments given in argv pointer list. value begins from 1 and this means that the 0 item in list argv is a string to name of command.
|
||||
* \param argv argv is list of arguments. List size is given in argc parameter. Value in argv[0] is string to name of command.
|
||||
*/
|
||||
typedef int (cmd_run_cb)(int argc, char *argv[]);
|
||||
/** Add command to intepreter
|
||||
* \param name command string
|
||||
* \param callback This function is called when command line start executing
|
||||
* \param info Command short description which is visible in help command, or null if not in use
|
||||
* \param man Help page for this command. This is shown when executing command with invalid parameters or command with --help parameter. Can be null if not in use.
|
||||
*/
|
||||
void cmd_add(const char *name, cmd_run_cb *callback, const char *info, const char *man);
|
||||
|
||||
/** delete command from intepreter
|
||||
* \param name command to be delete
|
||||
*/
|
||||
void cmd_delete(const char *name);
|
||||
/** Command executer.
|
||||
* Command executer, which split&push command(s) to the buffer and
|
||||
* start executing commands in cmd tasklet.
|
||||
* if not, execute command directly.
|
||||
* If command implementation returns CMDLINE_RETCODE_EXCUTING_CONTINUE,
|
||||
* executor will wait for cmd_ready() before continue to next command.
|
||||
* \param str command string, e.g. "help"
|
||||
*/
|
||||
void cmd_exe(char *str);
|
||||
/** Add alias to interpreter.
|
||||
* Aliases are replaced with values before executing a command. All aliases must be started from beginning of line.
|
||||
* null or empty value deletes alias.
|
||||
* \code
|
||||
cmd_alias_add("print", "echo");
|
||||
cmd_exe("print \"hello world!\""); // this is now same as "echo \"hello world!\"" .
|
||||
* \endcode
|
||||
* \param alias alias name
|
||||
* \param value value for alias. Values can be any visible ASCII -characters.
|
||||
*/
|
||||
void cmd_alias_add(const char *alias, const char *value);
|
||||
/** Add Variable to interpreter.
|
||||
* Variables are replaced with values before executing a command.
|
||||
* To use variables from cli, use dollar ($) -character so that interpreter knows user want to use variable in that place.
|
||||
* null or empty value deletes variable.
|
||||
* \code
|
||||
cmd_variable_add("world", "hello world!");
|
||||
cmd_exe("echo $world"); // this is now same as echo "hello world!" .
|
||||
* \endcode
|
||||
* \param variable Variable name, which will be replaced in interpreter.
|
||||
* \param value Value for variable. Values can contains white spaces and '"' or '"' characters.
|
||||
*/
|
||||
void cmd_variable_add(char *variable, char *value);
|
||||
|
||||
/** find command parameter index by key.
|
||||
* e.g.
|
||||
* \code
|
||||
int main(void){
|
||||
//..init cmd..
|
||||
//..
|
||||
cmd_exe("mycmd enable")
|
||||
}
|
||||
int mycmd_command(int argc, char *argv[]) {
|
||||
bool found = cmd_parameter_index( argc, argv, "enable" ) > 0;
|
||||
}
|
||||
* \endcode
|
||||
* \param argc argc is the count of arguments given in argv pointer list. value begins from 1 and this means that the 0 item in list argv is a string to name of command.
|
||||
* \param argv is list of arguments. List size is given in argc parameter. Value in argv[0] is string to name of command.
|
||||
* \param key option key, which index you want to find out.
|
||||
* \return index where parameter was or -1 when not found
|
||||
*/
|
||||
int cmd_parameter_index(int argc, char *argv[], const char *key);
|
||||
/** check if command option is present.
|
||||
* e.g. cmd: "mycmd -c"
|
||||
* \code
|
||||
* bool on = cmd_has_option( argc, argv, "p" );
|
||||
* \endcode
|
||||
* \param argc argc is the count of arguments given in argv pointer list. value begins from 1 and this means that the 0 item in list argv is a string to name of command.
|
||||
* \param argv is list of arguments. List size is given in argc parameter. Value in argv[0] is string to name of command.
|
||||
* \param key option key to be find
|
||||
* \return true if option found otherwise false
|
||||
*/
|
||||
bool cmd_has_option(int argc, char *argv[], const char *key);
|
||||
/** find command parameter by key.
|
||||
* if exists, return true, otherwise false.
|
||||
* e.g. cmd: "mycmd enable 1"
|
||||
* \code
|
||||
int mycmd_command(int argc, char *argv[]) {
|
||||
bool value;
|
||||
bool found = cmd_parameter_bool( argc, argv, "mykey", &value );
|
||||
if( found ) return CMDLINE_RETCODE_SUCCESS;
|
||||
else return CMDLINE_RETCODE_FAIL;
|
||||
}
|
||||
* \endcode
|
||||
* \param argc argc is the count of arguments given in argv pointer list. value begins from 1 and this means that the 0 item in list argv is a string to name of command.
|
||||
* \param argv is list of arguments. List size is given in argc parameter. Value in argv[0] is string to name of command.
|
||||
* \param key parameter key to be find
|
||||
* \param value parameter value to be fetch, if key not found value are untouched. "1" and "on" and "true" and "enable" and "allow" are True -value, all others false.
|
||||
* \return true if parameter key and value found otherwise false
|
||||
*/
|
||||
bool cmd_parameter_bool(int argc, char *argv[], const char *key, bool *value);
|
||||
/** find command parameter by key and return value (next parameter).
|
||||
* if exists, return parameter pointer, otherwise null.
|
||||
* e.g. cmd: "mycmd mykey myvalue"
|
||||
* \code
|
||||
int mycmd_command(int argc, char *argv[]) {
|
||||
char *value;
|
||||
bool found = cmd_parameter_val( argc, argv, "mykey", &value );
|
||||
if( found ) return CMDLINE_RETCODE_SUCCESS;
|
||||
else return CMDLINE_RETCODE_FAIL;
|
||||
}
|
||||
* \endcode
|
||||
* \param argc argc is the count of arguments given in argv pointer list. value begins from 1 and this means that the 0 item in list argv is a string to name of command.
|
||||
* \param argv is list of arguments. List size is given in argc parameter. Value in argv[0] is string to name of command.
|
||||
* \param key parameter key to be find
|
||||
* \param value pointer to pointer, which will point to cli input data when key and value found. if key or value not found this parameter are untouched.
|
||||
* \return true if parameter key and value found otherwise false
|
||||
*/
|
||||
bool cmd_parameter_val(int argc, char *argv[], const char *key, char **value);
|
||||
/** find command parameter by key and return value (next parameter) in integer. Only whitespaces are allowed in addition to the float to be read.
|
||||
* e.g. cmd: "mycmd mykey myvalue"
|
||||
* \code
|
||||
int32_t value;
|
||||
cmd_parameter_int( argc, argv, "key", &value );
|
||||
* \endcode
|
||||
* \param argc argc is the count of arguments given in argv pointer list. value begins from 1 and this means that the item 0 in the list argv is a string to name of command.
|
||||
* \param argv is list of arguments. List size is given in argc parameter. Value in argv[0] is string to name of command.
|
||||
* \param key parameter key to be found
|
||||
* \param value A pointer to a variable where to write the converted number. If value cannot be converted, it is not touched.
|
||||
* \return true if parameter key and an integer is found, otherwise return false
|
||||
*/
|
||||
bool cmd_parameter_int(int argc, char *argv[], const char *key, int32_t *value);
|
||||
/** find command parameter by key and return value (next parameter) in float. Only whitespaces are allowed in addition to the float to be read.
|
||||
* e.g. cmd: "mycmd mykey myvalue"
|
||||
* \code
|
||||
float value;
|
||||
cmd_parameter_float( argc, argv, "key", &value );
|
||||
* \endcode
|
||||
* \param argc argc is the count of arguments given in argv pointer list. values begin from 1 and this means that the item 0 in the list argv is a string to name of command.
|
||||
* \param argv is list of arguments. List size is given in argc parameter. Value in argv[0] is string to name of command.
|
||||
* \param key parameter key to be found
|
||||
* \param value A pointer to a variable where to write the converted number. If value cannot be converted, it is not touched.
|
||||
* \return true if parameter key and a float found, otherwise return false
|
||||
*/
|
||||
bool cmd_parameter_float(int argc, char *argv[], const char *key, float *value);
|
||||
/** Get last command line parameter as string.
|
||||
* e.g.
|
||||
* cmd: "mycmd hello world"
|
||||
* cmd_parameter_last -> "world"
|
||||
* cmd: "mycmd"
|
||||
* cmd_parameter_last() -> NULL
|
||||
* \code
|
||||
cmd_parameter_last(argc, argv)
|
||||
* \endcode
|
||||
* \param argc argc is the count of arguments given in argv pointer list. value begins from 1 and this means that the 0 item in list argv is a string to name of command.
|
||||
* \param argv is list of arguments. List size is given in argc parameter. Value in argv[0] is string to name of command.
|
||||
* \return pointer to last parameter or NULL when there is no any parameters.
|
||||
*/
|
||||
char *cmd_parameter_last(int argc, char *argv[]);
|
||||
|
||||
/** find command parameter by key and return value (next parameter) in int64.
|
||||
* e.g. cmd: "mycmd mykey myvalue"
|
||||
* \code
|
||||
uint32_t i;
|
||||
cmd_parameter_timestamp( argc, argv, "mykey", &i );
|
||||
* \endcode
|
||||
*
|
||||
* Supports following formats:
|
||||
* number -> direct conversion
|
||||
* 11:22:33:44:55:66:77:88 -> converts to number
|
||||
* seconds,tics -> converts thread type timestamp to int64
|
||||
*
|
||||
* \param argc argc is the count of arguments given in argv pointer list. value begins from 1 and this means that the 0 item in list argv is a string to name of command.
|
||||
* \param argv is list of arguments. List size is given in argc parameter. Value in argv[0] is string to name of command.
|
||||
* \param key parameter key to be find
|
||||
* \param value parameter value to be fetch, if key not found value are untouched.
|
||||
* \return true if parameter key and value found otherwise false
|
||||
*/
|
||||
bool cmd_parameter_timestamp(int argc, char *argv[], const char *key, int64_t *value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /*_CMDLINE_H_*/
|
File diff suppressed because it is too large
Load Diff
|
@ -8,7 +8,15 @@
|
|||
"fea-ipv6": {
|
||||
"help": "Used to globally disable ipv6 tracing features.",
|
||||
"value": null
|
||||
},
|
||||
"allocator": {
|
||||
"value": "malloc",
|
||||
"macro_name": "MEM_ALLOC"
|
||||
},
|
||||
"deallocator": {
|
||||
"value": "free",
|
||||
"macro_name": "MEM_FREE"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ IntelHex>=1.3
|
|||
junit-xml
|
||||
pyYAML
|
||||
requests
|
||||
mbed-ls>=0.2.13
|
||||
mbed-ls>=1.4.2,==1.*
|
||||
mbed-host-tests>=1.1.2
|
||||
mbed-greentea>=0.2.24
|
||||
beautifulsoup4>=4
|
||||
|
@ -17,3 +17,4 @@ future>=0.16.0
|
|||
six>=1.11.0
|
||||
git+https://github.com/armmbed/manifest-tool.git@v1.4.5
|
||||
mbed-cloud-sdk==2.0.0
|
||||
icetea>=1.0.1,<2
|
||||
|
|
|
@ -1348,11 +1348,13 @@ def merge_build_data(filename, toolchain_report, app_type):
|
|||
for project in tc.values():
|
||||
for build in project:
|
||||
try:
|
||||
build[0]['bin_fullpath'] = build[0]['bin']
|
||||
build[0]['elf_fullpath'] = build[0]['elf']
|
||||
build[0]['elf'] = relpath(build[0]['elf'], path_to_file)
|
||||
build[0]['bin'] = relpath(build[0]['bin'], path_to_file)
|
||||
except KeyError:
|
||||
pass
|
||||
if 'type' not in build[0]:
|
||||
build[0]['type'] = app_type
|
||||
build_data['builds'].append(build[0])
|
||||
dump(build_data, open(filename, "w"), indent=4, separators=(',', ': '))
|
||||
build_data['builds'].insert(0, build[0])
|
||||
dump(build_data, open(filename, "wb"), indent=4, separators=(',', ': '))
|
||||
|
|
|
@ -69,6 +69,7 @@ LEGACY_IGNORE_DIRS = set([
|
|||
|
||||
# Tests, here for simplicity
|
||||
'TESTS',
|
||||
'TEST_APPS',
|
||||
])
|
||||
LEGACY_TOOLCHAIN_NAMES = {
|
||||
'ARM_STD':'ARM',
|
||||
|
|
|
@ -0,0 +1,332 @@
|
|||
#! /usr/bin/env python2
|
||||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from __future__ import print_function, division, absolute_import
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
from os.path import abspath, join, dirname, relpath, sep
|
||||
import json
|
||||
import traceback
|
||||
from fnmatch import translate
|
||||
from argparse import ArgumentParser
|
||||
|
||||
ROOT = abspath(join(dirname(__file__), '..'))
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
from tools.config import ConfigException
|
||||
from tools.utils import cmd, run_cmd
|
||||
|
||||
plugins_path = abspath(join(ROOT, 'TEST_APPS', 'icetea_plugins', 'plugins_to_load.py'))
|
||||
|
||||
|
||||
def find_build_from_build_data(build_data, id, target, toolchain):
|
||||
|
||||
if 'builds' not in build_data:
|
||||
raise Exception("build data is in wrong format, does not include builds object")
|
||||
|
||||
for build in build_data['builds']:
|
||||
if 'id' in build.keys() \
|
||||
and id.upper() in build['id'].upper() \
|
||||
and 'target_name' in build.keys() \
|
||||
and target.upper() == build['target_name'].upper() \
|
||||
and 'toolchain_name' in build.keys() \
|
||||
and toolchain.upper() == build['toolchain_name'].upper() \
|
||||
and 'result' in build.keys() \
|
||||
and "OK" == build['result']:
|
||||
return build
|
||||
return None
|
||||
|
||||
|
||||
def create_test_suite(target, tool, icetea_json_output, build_data, tests_by_name):
|
||||
"""
|
||||
Create test suite content
|
||||
:param target:
|
||||
:param tool:
|
||||
:param icetea_json_output:
|
||||
:param build_data:
|
||||
:return:
|
||||
"""
|
||||
test_suite = dict()
|
||||
test_suite['testcases'] = list()
|
||||
|
||||
for test in icetea_json_output:
|
||||
skip = False
|
||||
|
||||
for dut in test['requirements']['duts'].values():
|
||||
# Set binary path based on application name
|
||||
if 'application' in dut.keys() and 'name' in dut['application'].keys():
|
||||
build = find_build_from_build_data(
|
||||
build_data=build_data,
|
||||
id=dut['application']['name'],
|
||||
target=target,
|
||||
toolchain=tool)
|
||||
if build:
|
||||
try:
|
||||
dut['application']['bin'] = build['bin_fullpath']
|
||||
except KeyError:
|
||||
raise Exception('Full path is missing from build: {}'.format(build))
|
||||
else:
|
||||
skip = True
|
||||
|
||||
if not tests_by_name or is_test_in_test_by_name(test['name'], tests_by_name):
|
||||
test_case = {
|
||||
'name': test['name'],
|
||||
'config': {
|
||||
'requirements': test['requirements']
|
||||
}
|
||||
}
|
||||
|
||||
# Skip test if not binary path
|
||||
if skip:
|
||||
test_case['config']['execution'] = {
|
||||
'skip': {
|
||||
'value': True,
|
||||
'reason': "Test requiring application binary not build"
|
||||
}
|
||||
}
|
||||
|
||||
test_suite['testcases'].append(test_case)
|
||||
|
||||
return test_suite
|
||||
|
||||
|
||||
def get_applications(test):
|
||||
ret = list()
|
||||
for dut in test['requirements']['duts'].values():
|
||||
if 'application' in dut.keys() and 'name' in dut['application'].keys():
|
||||
ret.append(dut['application']['name'])
|
||||
return ret
|
||||
|
||||
|
||||
def filter_test_by_build_data(icetea_json_output, build_data, target, toolchain):
|
||||
if not build_data:
|
||||
return icetea_json_output
|
||||
|
||||
ret = list()
|
||||
for test in icetea_json_output:
|
||||
for dut in test['requirements']['duts'].values():
|
||||
if 'application' in dut.keys() and 'name' in dut['application'].keys():
|
||||
id = dut['application']['name']
|
||||
if find_build_from_build_data(build_data, id, target, toolchain):
|
||||
# Test requiring build found
|
||||
ret.append(test)
|
||||
return ret
|
||||
|
||||
|
||||
def filter_test_by_name(icetea_json_output, test_by_name):
|
||||
if not test_by_name:
|
||||
return icetea_json_output
|
||||
ret = list()
|
||||
for test_temp in icetea_json_output:
|
||||
if is_test_in_test_by_name(test_temp['name'], test_by_name) and test_temp not in ret:
|
||||
ret.append(test_temp)
|
||||
return ret
|
||||
|
||||
|
||||
def get_applications_from_test(test):
|
||||
ret = list()
|
||||
if u'requirements' in test.keys() and u'duts' in test[u'requirements']:
|
||||
for name, dut in test[u'requirements'][u'duts'].items():
|
||||
if u'application' in dut.keys() and u'name' in dut[u'application']:
|
||||
ret.append(dut[u'application'][u'name'])
|
||||
return ret
|
||||
|
||||
|
||||
def get_application_list(icetea_json_output, tests_by_name):
|
||||
""" Return comma separated list of application which are used in tests """
|
||||
ret = list()
|
||||
for test in filter_test_by_name(icetea_json_output, tests_by_name):
|
||||
ret.extend(get_applications_from_test(test))
|
||||
# Remove duplicates
|
||||
return list(set(ret))
|
||||
|
||||
|
||||
def icetea_tests(target, tcdir, verbose):
|
||||
command = ['icetea', '--tcdir', tcdir, '--list', '--json', '--platform_filter', target] \
|
||||
+ (['-v'] if verbose else [])
|
||||
|
||||
stdout, stderr, returncode = run_cmd(command)
|
||||
|
||||
if returncode != 0:
|
||||
raise Exception(
|
||||
"Error when running icetea. \ncwd:{} \nCommand:'{}' \noutput:{}".format(os.getcwd(), ' '.join(command),
|
||||
stderr.decode()))
|
||||
|
||||
return json.loads(stdout)
|
||||
|
||||
|
||||
def is_test_in_test_by_name(test_name, test_by_name):
|
||||
for tbn_temp in test_by_name:
|
||||
if re.search(translate(tbn_temp), test_name):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def check_tests(icetea_json_output):
|
||||
"""
|
||||
Check that all tests have all necessary information
|
||||
:return:
|
||||
"""
|
||||
for test in icetea_json_output:
|
||||
if not get_applications_from_test(test):
|
||||
raise Exception('Test {} does not have application with correct name'.format(test['name']))
|
||||
|
||||
|
||||
def load_build_data(build_data_path):
|
||||
"""
|
||||
:return: build_data.json content as dict and None if build data is not available
|
||||
"""
|
||||
if not os.path.isfile(build_data_path):
|
||||
return None
|
||||
return json.load(open(build_data_path))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
# Parse Options
|
||||
parser = ArgumentParser()
|
||||
|
||||
parser.add_argument('-m', '--mcu',
|
||||
dest='target',
|
||||
default=None,
|
||||
help='Test target MCU',
|
||||
required=True)
|
||||
|
||||
parser.add_argument('-t', '--toolchain',
|
||||
dest='toolchain',
|
||||
default=None,
|
||||
help='Toolchain',
|
||||
required=True)
|
||||
|
||||
parser.add_argument('--build-data',
|
||||
dest='build_data',
|
||||
default=None,
|
||||
help='Detail data from build')
|
||||
|
||||
parser.add_argument('--test-suite',
|
||||
dest='test_suite',
|
||||
default=None,
|
||||
help='Path used for test suite file')
|
||||
|
||||
parser.add_argument('-n', '--tests-by-name',
|
||||
dest='tests_by_name',
|
||||
default=None,
|
||||
help='Limit the tests to a list (ex. test1,test2,test3)')
|
||||
|
||||
parser.add_argument('--tcdir',
|
||||
dest='tcdir',
|
||||
default='TEST_APPS',
|
||||
help='Test case directory',
|
||||
required=False)
|
||||
|
||||
parser.add_argument('--compile-list',
|
||||
action='store_true',
|
||||
dest='compile_list',
|
||||
default=False,
|
||||
help='List tests, which applications can be compiled')
|
||||
|
||||
parser.add_argument('--run-list',
|
||||
action='store_true',
|
||||
dest='run_list',
|
||||
default=False,
|
||||
help='List tests, which applications are compiled and ready for run')
|
||||
|
||||
parser.add_argument('--application-list',
|
||||
action='store_true',
|
||||
dest='application_list',
|
||||
default=False,
|
||||
help='List applications that need to be build')
|
||||
|
||||
parser.add_argument('--ignore-checks',
|
||||
action='store_true',
|
||||
dest='ignore_checks',
|
||||
default=False,
|
||||
help='Ignore data validation checks')
|
||||
|
||||
parser.add_argument('-v', '--verbose',
|
||||
action='store_true',
|
||||
dest='verbose',
|
||||
default=False,
|
||||
help='Verbose diagnostic output')
|
||||
|
||||
options = parser.parse_args()
|
||||
|
||||
icetea_json_output = icetea_tests(options.target, options.tcdir, options.verbose)
|
||||
tests_by_name = options.tests_by_name.split(',') if options.tests_by_name else None
|
||||
build_data = load_build_data(options.build_data) if options.build_data else None
|
||||
|
||||
if not options.ignore_checks:
|
||||
check_tests(icetea_json_output)
|
||||
|
||||
if options.compile_list:
|
||||
print('Available icetea tests for build \'{}-{}\', location \'{}\''.format(
|
||||
options.target, options.toolchain, options.tcdir))
|
||||
for test in icetea_json_output:
|
||||
print(
|
||||
'Test Case:\n Name: {name}\n Path: .{sep}{filepath}\n Test applications: .{sep}{apps}'.format(
|
||||
name=test['name'],
|
||||
sep=sep,
|
||||
filepath=relpath(test['filepath'], ROOT),
|
||||
apps=''.join(get_applications(test)).replace('-', os.path.sep)))
|
||||
|
||||
elif options.run_list:
|
||||
print('Available icetea tests for build \'{}-{}\', location \'{}\''.format(
|
||||
options.target, options.toolchain, options.tcdir))
|
||||
|
||||
# Filters
|
||||
tests = filter_test_by_name(icetea_json_output, tests_by_name)
|
||||
if build_data:
|
||||
tests = filter_test_by_build_data(tests, build_data, options.target, options.toolchain)
|
||||
|
||||
for test in tests:
|
||||
print(' test \'{name}\''.format(name=test['name']))
|
||||
|
||||
elif options.application_list:
|
||||
print(','.join(get_application_list(icetea_json_output, tests_by_name)))
|
||||
|
||||
else:
|
||||
if not build_data:
|
||||
raise Exception("Build data file does not exist: {}".format(options.build_data))
|
||||
|
||||
test_suite = create_test_suite(options.target, options.toolchain, icetea_json_output, build_data,
|
||||
tests_by_name)
|
||||
|
||||
if not test_suite['testcases']:
|
||||
raise Exception("Test suite is empty. Check that --tcdir and --tests-by-name have correct values")
|
||||
|
||||
if not options.test_suite:
|
||||
raise Exception('--test-suite is required when running tests')
|
||||
|
||||
with open(options.test_suite, 'w') as f:
|
||||
json.dump(test_suite, f, indent=2)
|
||||
|
||||
# List just for debug
|
||||
if options.verbose:
|
||||
cmd(['icetea', '--tcdir', options.tcdir, '--list'] + (['-v'] if options.verbose else []))
|
||||
|
||||
cmd(['icetea', '--tcdir', options.tcdir, '--suite', options.test_suite, '--clean', '--plugin_path',
|
||||
plugins_path] + (['-v'] if options.verbose else []))
|
||||
|
||||
except KeyboardInterrupt as e:
|
||||
print('\n[CTRL+c] exit')
|
||||
except ConfigException as e:
|
||||
# Catching ConfigException here to prevent a traceback
|
||||
print('[ERROR] {}'.format(e))
|
||||
except Exception as e:
|
||||
traceback.print_exc(file=sys.stdout)
|
||||
print('[ERROR] {}'.format(e))
|
||||
sys.exit(1)
|
|
@ -16,27 +16,28 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
|
||||
|
||||
TEST BUILD & RUN
|
||||
TEST BUILD
|
||||
"""
|
||||
from __future__ import print_function, division, absolute_import
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import fnmatch
|
||||
|
||||
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
from tools.config import ConfigException, Config
|
||||
from tools.test_api import test_path_to_name, find_tests, get_test_config, print_tests, build_tests, test_spec_from_test_builds
|
||||
from tools.test_configs import get_default_config
|
||||
from tools.config import ConfigException
|
||||
from tools.test_api import find_tests, get_test_config, print_tests, build_tests, test_spec_from_test_builds
|
||||
import tools.test_configs as TestConfig
|
||||
from tools.options import get_default_options_parser, extract_profile, extract_mcus
|
||||
from tools.build_api import build_project, build_library
|
||||
from tools.build_api import print_build_memory_usage
|
||||
from tools.build_api import merge_build_data
|
||||
from tools.targets import TARGET_MAP
|
||||
from tools.notifier.term import TerminalNotifier
|
||||
from tools.utils import mkdir, ToolException, NotSupportedException, args_error
|
||||
from tools.utils import mkdir, ToolException, NotSupportedException, args_error, write_json_to_file
|
||||
from tools.test_exporters import ReportExporter, ResultExporterType
|
||||
from tools.utils import argparse_filestring_type, argparse_lowercase_type, argparse_many
|
||||
from tools.utils import argparse_dir_not_parent
|
||||
|
@ -111,9 +112,19 @@ if __name__ == '__main__':
|
|||
dest="stats_depth",
|
||||
default=2,
|
||||
help="Depth level for static memory report")
|
||||
|
||||
parser.add_argument("--ignore", dest="ignore", type=argparse_many(str),
|
||||
default=None, help="Comma separated list of patterns to add to mbedignore (eg. ./main.cpp)")
|
||||
parser.add_argument("--icetea",
|
||||
action="store_true",
|
||||
dest="icetea",
|
||||
default=False,
|
||||
help="Only icetea tests")
|
||||
|
||||
parser.add_argument("--greentea",
|
||||
action="store_true",
|
||||
dest="greentea",
|
||||
default=False,
|
||||
help="Only greentea tests")
|
||||
|
||||
options = parser.parse_args()
|
||||
|
||||
|
@ -126,8 +137,13 @@ if __name__ == '__main__':
|
|||
all_tests = {}
|
||||
tests = {}
|
||||
|
||||
# As default both test tools are enabled
|
||||
if not (options.greentea or options.icetea):
|
||||
options.greentea = True
|
||||
options.icetea = True
|
||||
|
||||
# Target
|
||||
if options.mcu is None :
|
||||
if options.mcu is None:
|
||||
args_error(parser, "argument -m/--mcu is required")
|
||||
mcu = extract_mcus(parser, options)[0]
|
||||
|
||||
|
@ -159,8 +175,13 @@ if __name__ == '__main__':
|
|||
|
||||
# Find all tests in the relevant paths
|
||||
for path in all_paths:
|
||||
all_tests.update(find_tests(path, mcu, toolchain,
|
||||
app_config=config))
|
||||
all_tests.update(find_tests(
|
||||
base_dir=path,
|
||||
target_name=mcu,
|
||||
toolchain_name=toolchain,
|
||||
icetea=options.icetea,
|
||||
greentea=options.greentea,
|
||||
app_config=config))
|
||||
|
||||
# Filter tests by name if specified
|
||||
if options.names:
|
||||
|
@ -251,20 +272,7 @@ if __name__ == '__main__':
|
|||
|
||||
# If a path to a test spec is provided, write it to a file
|
||||
if options.test_spec:
|
||||
test_spec_data = test_spec_from_test_builds(test_build)
|
||||
|
||||
# Create the target dir for the test spec if necessary
|
||||
# mkdir will not create the dir if it already exists
|
||||
test_spec_dir = os.path.dirname(options.test_spec)
|
||||
if test_spec_dir:
|
||||
mkdir(test_spec_dir)
|
||||
|
||||
try:
|
||||
with open(options.test_spec, 'w') as f:
|
||||
f.write(json.dumps(test_spec_data, indent=2))
|
||||
except IOError as e:
|
||||
print("[ERROR] Error writing test spec to file")
|
||||
print(e)
|
||||
write_json_to_file(test_spec_from_test_builds(test_build), options.test_spec)
|
||||
|
||||
# If a path to a JUnit build report spec is provided, write it to a file
|
||||
if options.build_report_junit:
|
||||
|
@ -296,3 +304,4 @@ if __name__ == '__main__':
|
|||
traceback.print_exc(file=sys.stdout)
|
||||
print("[ERROR] %s" % str(e))
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
"""
|
||||
Copyright 2017 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from icetea_lib.bench import Bench
|
||||
|
||||
|
||||
class Testcase(Bench):
|
||||
def __init__(self):
|
||||
Bench.__init__(self,
|
||||
name="test_pass",
|
||||
title="Test icetea integration",
|
||||
status="released",
|
||||
purpose="Just for testing scripts",
|
||||
component=[],
|
||||
type="smoke"
|
||||
)
|
||||
|
||||
def setup(self):
|
||||
pass
|
||||
|
||||
def case(self):
|
||||
print("Test2 running")
|
||||
|
||||
def teardown(self):
|
||||
pass
|
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from icetea_lib.bench import Bench
|
||||
|
||||
|
||||
class Testcase(Bench):
|
||||
def __init__(self):
|
||||
Bench.__init__(self,
|
||||
name="test_print",
|
||||
title="Test icetea integration",
|
||||
status="released",
|
||||
purpose="Just for testing scripts",
|
||||
component=[],
|
||||
type="smoke"
|
||||
)
|
||||
|
||||
def setup(self):
|
||||
pass
|
||||
|
||||
def case(self):
|
||||
print("Test running")
|
||||
|
||||
def teardown(self):
|
||||
pass
|
|
@ -0,0 +1 @@
|
|||
This folder contains hardware test data for icetea integration
|
|
@ -0,0 +1,49 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from icetea_lib.bench import Bench
|
||||
|
||||
|
||||
class Testcase(Bench):
|
||||
def __init__(self):
|
||||
Bench.__init__(self,
|
||||
name="test_K64F_only",
|
||||
title="Test a test case which have only K64F support",
|
||||
status="released",
|
||||
purpose="Just for testing scripts",
|
||||
component=[],
|
||||
type="smoke",
|
||||
requirements={
|
||||
"duts": {
|
||||
'*': {
|
||||
"count": 1,
|
||||
"type": "hardware",
|
||||
"allowed_platforms": ['K64F'],
|
||||
"application": {
|
||||
"name": "TEST_APPS-device-exampleapp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
def setup(self):
|
||||
pass
|
||||
|
||||
def case(self):
|
||||
pass
|
||||
|
||||
def teardown(self):
|
||||
pass
|
|
@ -0,0 +1,58 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from icetea_lib.bench import Bench
|
||||
|
||||
|
||||
class Testcase(Bench):
|
||||
def __init__(self):
|
||||
Bench.__init__(self,
|
||||
name="test_predefined_platforms",
|
||||
title="Test a test case which have support for multiple platforms",
|
||||
status="released",
|
||||
purpose="Just for testing scripts",
|
||||
component=[],
|
||||
type="regression",
|
||||
requirements={
|
||||
"duts": {
|
||||
'*': {
|
||||
"count": 1,
|
||||
"type": "hardware",
|
||||
"allowed_platforms": [
|
||||
"LPC1768", "KL25Z", "K64F", "K66F", "K22F", "LPC4088", "LPC1549",
|
||||
"NUCLEO_F072RB", "NUCLEO_F091RC", "NUCLEO_F302R8", "NUCLEO_F303K8",
|
||||
"NUCLEO_F303RE", "NUCLEO_F207ZG", "NUCLEO_F334R8", "NUCLEO_F303ZE",
|
||||
"NUCLEO_L053R8", "DISCO_L072CZ_LRWAN1", "NUCLEO_L073RZ", "NUCLEO_L152RE",
|
||||
"NUCLEO_F410RB", "NUCLEO_F446RE", "NUCLEO_F446ZE", "NUCLEO_F429ZI",
|
||||
"DISCO_F407VG", "NUCLEO_F746ZG", "NUCLEO_L476RG", "DISCO_L053C8", "DISCO_F334C8",
|
||||
"DISCO_L475VG_IOT01A", "DISCO_L476VG", "DISCO_F469NI", "DISCO_F429ZI",
|
||||
"DISCO_F769NI", "ARCH_MAX", "MAX32600MBED", "MOTE_L152RC", "B96B_F446VE"
|
||||
],
|
||||
"application": {
|
||||
"name": "TEST_APPS-device-exampleapp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
def setup(self):
|
||||
pass
|
||||
|
||||
def case(self):
|
||||
pass
|
||||
|
||||
def teardown(self):
|
||||
pass
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"builds": []
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from os.path import realpath, join, dirname, isfile
|
||||
import subprocess
|
||||
|
||||
"""
|
||||
Tests for run_icetea.py
|
||||
"""
|
||||
this_file_dir = dirname(realpath(__file__))
|
||||
hw_test_dir = join(this_file_dir, 'TEST_DIR_HW')
|
||||
test_dir = join(this_file_dir, 'TEST_DIR')
|
||||
empty_build_data = join(this_file_dir, 'empty_build_data.json')
|
||||
test_suite = join(this_file_dir, 'test_suite.json')
|
||||
run_icetea_py = join(dirname(dirname(this_file_dir)), 'run_icetea.py')
|
||||
assert isfile(run_icetea_py)
|
||||
|
||||
|
||||
def _execute_icetea(*params):
|
||||
command = ["python", run_icetea_py] + list(params)
|
||||
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stout, sterr = process.communicate()
|
||||
status = process.poll()
|
||||
if status != 0:
|
||||
raise Exception("Error with {}, \nreturn code: {}, \nerror message: {}, \noutput:{}".format(
|
||||
" ".join(command), status, sterr, stout
|
||||
))
|
||||
return stout.decode()
|
||||
|
||||
|
||||
def test_help():
|
||||
"""
|
||||
Just test that something works
|
||||
:return:
|
||||
"""
|
||||
_execute_icetea('--help')
|
||||
|
||||
|
||||
def test_list_tests_k64f():
|
||||
out = _execute_icetea('--compile-list', '--mcu', 'K64F', '--toolchain', 'GCC_ARM', '--tcdir', hw_test_dir)
|
||||
assert 'test_K64F_only' in out
|
||||
assert 'test_predefined_platforms' in out
|
||||
|
||||
|
||||
def test_list_tests_nucleo_l073rz():
|
||||
out = _execute_icetea('--compile-list', '--mcu', 'NUCLEO_L073RZ', '--toolchain', 'GCC_ARM', '--tcdir', hw_test_dir)
|
||||
assert 'test_predefined_platforms' in out
|
||||
assert 'test_K64F_only' not in out
|
||||
|
||||
|
||||
def test_run():
|
||||
out = _execute_icetea('--mcu', 'K64F', '--toolchain', 'GCC_ARM', '--tcdir', test_dir, '--build-data',
|
||||
empty_build_data, '--test-suite', test_suite, '--ignore-checks')
|
||||
assert 'test_print' in out
|
||||
assert 'test_pass' in out
|
||||
|
||||
|
||||
def test_run_by_name():
|
||||
out = _execute_icetea('--mcu', 'K64F', '--toolchain', 'GCC_ARM', '--tcdir', test_dir, '--build-data',
|
||||
empty_build_data, '--test-suite', test_suite, '--tests-by-name', 'test_pass',
|
||||
'--ignore-checks')
|
||||
assert 'test_pass' in out
|
||||
assert 'test_print' not in out
|
||||
|
||||
|
||||
def test_run_hw_with_not_build_tests():
|
||||
"""
|
||||
When test binaries are not found tests will be skipped
|
||||
:return:
|
||||
"""
|
||||
out = _execute_icetea('--mcu', 'K64F', '--toolchain', 'GCC_ARM', '--tcdir', hw_test_dir, '--build-data',
|
||||
empty_build_data, '--test-suite', test_suite)
|
||||
output_lines = out.split('\n')
|
||||
|
||||
# Assert that
|
||||
temp = list(filter(lambda x: 'test_K64F_only' in x, output_lines))[0]
|
||||
assert 'skip' in temp
|
||||
|
||||
temp = list(filter(lambda x: 'test_predefined_platforms' in x, output_lines))[0]
|
||||
assert 'skip' in temp
|
||||
|
||||
|
||||
def test_data_validation():
|
||||
exception_happened = False
|
||||
try:
|
||||
_execute_icetea('--mcu', 'K64F', '--toolchain', 'GCC_ARM', '--tcdir', test_dir, '--build-data',
|
||||
empty_build_data, '--test-suite', test_suite)
|
||||
except BaseException:
|
||||
exception_happened = True
|
||||
assert exception_happened
|
|
@ -0,0 +1,144 @@
|
|||
"""
|
||||
Copyright 2018 ARM Limited
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..",
|
||||
".."))
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
from tools.run_icetea import find_build_from_build_data, filter_test_by_build_data, filter_test_by_name, \
|
||||
get_application_list
|
||||
|
||||
"""
|
||||
Unit tests for run_icetea.py
|
||||
"""
|
||||
|
||||
test_build_data = {
|
||||
'builds': [
|
||||
{
|
||||
"id": "TEST_APPS-DEVICE-SOCKET_APP",
|
||||
"target_name": "K64F",
|
||||
"toolchain_name": "GCC_ARM"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_find_build_from_build_data_empty():
|
||||
assert find_build_from_build_data(build_data={'builds': []}, id="something", target="K64F",
|
||||
toolchain="GCC_ARM") is None
|
||||
|
||||
|
||||
def test_find_build_from_build_data_wrong_target():
|
||||
assert find_build_from_build_data(build_data=test_build_data, id="TEST_APPS-DEVICE-SOCKET_APP", target="AAAA",
|
||||
toolchain="GCC_ARM") is None
|
||||
|
||||
|
||||
def test_find_build_from_build_data():
|
||||
assert find_build_from_build_data(build_data=test_build_data, id="TEST_APPS-DEVICE-SOCKET_APP", target="K64F",
|
||||
toolchain="GCC_ARM") is not None
|
||||
|
||||
|
||||
icetea_json_output = [
|
||||
{
|
||||
"status": "released",
|
||||
"requirements": {
|
||||
"duts": {
|
||||
"1": {
|
||||
"nick": "dut1"
|
||||
},
|
||||
"*": {
|
||||
"count": 1,
|
||||
"application": {
|
||||
"bin": None,
|
||||
"name": "TEST_APPS-device-socket_app"
|
||||
},
|
||||
"type": "hardware"
|
||||
}
|
||||
},
|
||||
"external": {
|
||||
"apps": []
|
||||
}
|
||||
},
|
||||
"name": "UDPSOCKET_BIND_PORT",
|
||||
"filepath": "/Users/test/mbed-os/TEST_APPS/testcases/SOCKET_BIND_PORT.py",
|
||||
"title": "udpsocket open and bind port",
|
||||
"component": [
|
||||
"mbed-os",
|
||||
"netsocket"
|
||||
],
|
||||
"compatible": {
|
||||
"framework": {
|
||||
"version": ">=1.0.0",
|
||||
"name": "Icetea"
|
||||
},
|
||||
"hw": {
|
||||
"value": True
|
||||
},
|
||||
"automation": {
|
||||
"value": True
|
||||
}
|
||||
},
|
||||
"subtype": "socket",
|
||||
"purpose": "Verify UDPSocket can be created, opened and port binded",
|
||||
"type": "smoke",
|
||||
"sub_type": None
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def test_filter_test_by_build_data_when_data_is_empty():
|
||||
assert filter_test_by_build_data(
|
||||
icetea_json_output=icetea_json_output,
|
||||
build_data=None,
|
||||
target="K64F",
|
||||
toolchain="GCC_ARM"
|
||||
) == icetea_json_output
|
||||
|
||||
|
||||
def test_filter_test_by_build_data():
|
||||
temp = filter_test_by_build_data(
|
||||
icetea_json_output=icetea_json_output,
|
||||
build_data=test_build_data,
|
||||
target="K64F",
|
||||
toolchain="GCC_ARM"
|
||||
)
|
||||
assert len(temp) > 0
|
||||
|
||||
|
||||
def test_filter_test_by_name():
|
||||
assert len(filter_test_by_name(icetea_json_output, ['UDPSOCKET_BIND_PORT'])) > 0
|
||||
|
||||
|
||||
def test_filter_test_by_name_when_not_found():
|
||||
assert filter_test_by_name(icetea_json_output, ['AAA']) == list()
|
||||
|
||||
|
||||
def test_filter_test_by_name_when_name_is_empty():
|
||||
assert filter_test_by_name(icetea_json_output, None) == icetea_json_output
|
||||
|
||||
|
||||
def test_get_application_list():
|
||||
assert 'TEST_APPS-device-socket_app' in get_application_list(icetea_json_output, ['UDPSOCKET_BIND_PORT'])
|
||||
|
||||
|
||||
def test_get_application_list_not_found():
|
||||
assert 'TEST_APPS-device-socket_app' not in get_application_list(icetea_json_output, ['SOMETHING_ELSE'])
|
||||
|
||||
|
||||
def test_get_application_list_none():
|
||||
assert 'TEST_APPS-device-socket_app' in get_application_list(icetea_json_output, None)
|
|
@ -2066,13 +2066,15 @@ def get_test_config(config_name, target_name):
|
|||
# Otherwise find the path to configuration file based on mbed OS interface
|
||||
return TestConfig.get_config_path(config_name, target_name)
|
||||
|
||||
def find_tests(base_dir, target_name, toolchain_name, app_config=None):
|
||||
|
||||
def find_tests(base_dir, target_name, toolchain_name, icetea, greentea, app_config=None):
|
||||
""" Finds all tests in a directory recursively
|
||||
base_dir: path to the directory to scan for tests (ex. 'path/to/project')
|
||||
target_name: name of the target to use for scanning (ex. 'K64F')
|
||||
toolchain_name: name of the toolchain to use for scanning (ex. 'GCC_ARM')
|
||||
options: Compile options to pass to the toolchain (ex. ['debug-info'])
|
||||
app_config - location of a chosen mbed_app.json file
|
||||
:param base_dir: path to the directory to scan for tests (ex. 'path/to/project')
|
||||
:param target_name: name of the target to use for scanning (ex. 'K64F')
|
||||
:param toolchain_name: name of the toolchain to use for scanning (ex. 'GCC_ARM')
|
||||
:param icetea: icetea enabled
|
||||
:param greentea: greentea enabled
|
||||
:param app_config - location of a chosen mbed_app.json file
|
||||
|
||||
returns a dictionary where keys are the test name, and the values are
|
||||
lists of paths needed to biuld the test.
|
||||
|
@ -2089,38 +2091,56 @@ def find_tests(base_dir, target_name, toolchain_name, app_config=None):
|
|||
base_resources = Resources(MockNotifier(), collect_ignores=True)
|
||||
base_resources.scan_with_config(base_dir, config)
|
||||
|
||||
dirs = [d for d in base_resources.ignored_dirs if basename(d) == 'TESTS']
|
||||
ignoreset = MbedIgnoreSet()
|
||||
if greentea:
|
||||
dirs = [d for d in base_resources.ignored_dirs if basename(d) == 'TESTS']
|
||||
ignoreset = MbedIgnoreSet()
|
||||
|
||||
for directory in dirs:
|
||||
ignorefile = join(directory, IGNORE_FILENAME)
|
||||
if isfile(ignorefile):
|
||||
ignoreset.add_mbedignore(directory, ignorefile)
|
||||
for test_group_directory in os.listdir(directory):
|
||||
grp_dir = join(directory, test_group_directory)
|
||||
if not isdir(grp_dir) or ignoreset.is_ignored(grp_dir):
|
||||
continue
|
||||
grpignorefile = join(grp_dir, IGNORE_FILENAME)
|
||||
if isfile(grpignorefile):
|
||||
ignoreset.add_mbedignore(grp_dir, grpignorefile)
|
||||
for test_case_directory in os.listdir(grp_dir):
|
||||
d = join(directory, test_group_directory, test_case_directory)
|
||||
if not isdir(d) or ignoreset.is_ignored(d):
|
||||
for directory in dirs:
|
||||
ignorefile = join(directory, IGNORE_FILENAME)
|
||||
if isfile(ignorefile):
|
||||
ignoreset.add_mbedignore(directory, ignorefile)
|
||||
for test_group_directory in os.listdir(directory):
|
||||
grp_dir = join(directory, test_group_directory)
|
||||
if not isdir(grp_dir) or ignoreset.is_ignored(grp_dir):
|
||||
continue
|
||||
special_dirs = ['host_tests', 'COMMON']
|
||||
if test_group_directory not in special_dirs and test_case_directory not in special_dirs:
|
||||
test_name = test_path_to_name(d, base_dir)
|
||||
tests[(test_name, directory, test_group_directory, test_case_directory)] = [d]
|
||||
if test_case_directory == 'COMMON':
|
||||
def predicate(base_pred, group_pred, name_base_group_case):
|
||||
grpignorefile = join(grp_dir, IGNORE_FILENAME)
|
||||
if isfile(grpignorefile):
|
||||
ignoreset.add_mbedignore(grp_dir, grpignorefile)
|
||||
for test_case_directory in os.listdir(grp_dir):
|
||||
d = join(directory, test_group_directory, test_case_directory)
|
||||
if not isdir(d) or ignoreset.is_ignored(d):
|
||||
continue
|
||||
special_dirs = ['host_tests', 'COMMON']
|
||||
if test_group_directory not in special_dirs and test_case_directory not in special_dirs:
|
||||
test_name = test_path_to_name(d, base_dir)
|
||||
tests[(test_name, directory, test_group_directory, test_case_directory)] = [d]
|
||||
if test_case_directory == 'COMMON':
|
||||
def predicate(base_pred, group_pred, name_base_group_case):
|
||||
(name, base, group, case) = name_base_group_case
|
||||
return base == base_pred and group == group_pred
|
||||
|
||||
commons.append((functools.partial(predicate, directory, test_group_directory), d))
|
||||
if test_group_directory == 'COMMON':
|
||||
def predicate(base_pred, name_base_group_case):
|
||||
(name, base, group, case) = name_base_group_case
|
||||
return base == base_pred and group == group_pred
|
||||
commons.append((functools.partial(predicate, directory, test_group_directory), d))
|
||||
if test_group_directory == 'COMMON':
|
||||
def predicate(base_pred, name_base_group_case):
|
||||
(name, base, group, case) = name_base_group_case
|
||||
return base == base_pred
|
||||
commons.append((functools.partial(predicate, directory), grp_dir))
|
||||
return base == base_pred
|
||||
|
||||
commons.append((functools.partial(predicate, directory), grp_dir))
|
||||
|
||||
if icetea:
|
||||
dirs = [d for d in base_resources.ignored_dirs if basename(d) == 'TEST_APPS']
|
||||
for directory in dirs:
|
||||
if not isdir(directory):
|
||||
continue
|
||||
for subdir in os.listdir(directory):
|
||||
d = join(directory, subdir)
|
||||
if not isdir(d):
|
||||
continue
|
||||
if 'device' == subdir:
|
||||
for test_dir in os.listdir(d):
|
||||
test_dir_path = join(d, test_dir)
|
||||
test_name = test_path_to_name(test_dir_path, base_dir)
|
||||
tests[(test_name, directory, subdir, test_dir)] = [test_dir_path]
|
||||
|
||||
# Apply common directories
|
||||
for pred, path in commons:
|
||||
|
@ -2131,6 +2151,7 @@ def find_tests(base_dir, target_name, toolchain_name, app_config=None):
|
|||
# Drop identity besides name
|
||||
return {name: paths for (name, _, _, _), paths in six.iteritems(tests)}
|
||||
|
||||
|
||||
def print_tests(tests, format="list", sort=True):
|
||||
"""Given a dictionary of tests (as returned from "find_tests"), print them
|
||||
in the specified format"""
|
||||
|
@ -2235,7 +2256,8 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
|
|||
"base_path": base_path,
|
||||
"baud_rate": baud_rate,
|
||||
"binary_type": "bootable",
|
||||
"tests": {}
|
||||
"tests": {},
|
||||
"test_apps": {}
|
||||
}
|
||||
|
||||
result = True
|
||||
|
@ -2314,7 +2336,8 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
|
|||
'bin_file' in worker_result):
|
||||
bin_file = norm_relative_path(worker_result['bin_file'], execution_directory)
|
||||
|
||||
test_build['tests'][worker_result['kwargs']['project_id']] = {
|
||||
test_key = 'test_apps' if 'test_apps-' in worker_result['kwargs']['project_id'] else 'tests'
|
||||
test_build[test_key][worker_result['kwargs']['project_id']] = {
|
||||
"binaries": [
|
||||
{
|
||||
"path": bin_file
|
||||
|
@ -2357,4 +2380,4 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
|
|||
def test_spec_from_test_builds(test_builds):
|
||||
return {
|
||||
"builds": test_builds
|
||||
}
|
||||
}
|
|
@ -3,6 +3,9 @@
|
|||
"HEAPBLOCKDEVICE": "HeapBlockDevice.json",
|
||||
"HEAPBLOCKDEVICE_AND_ETHERNET": "HeapBlockDeviceAndEthernetInterface.json",
|
||||
"HEAPBLOCKDEVICE_AND_WIFI": "HeapBlockDeviceAndWifiInterface.json",
|
||||
"ODIN_WIFI" : "OdinInterface.json",
|
||||
"ODIN_ETHERNET" : "Odin_EthernetInterface.json",
|
||||
"REALTEK_WIFI" : "RealtekInterface.json",
|
||||
"ESP8266_WIFI" : "ESP8266Interface.json",
|
||||
"ISM43362_WIFI" : "ISM43362Interface.json",
|
||||
"IDW0XX1_WIFI" : "SpwfSAInterface.json",
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
},
|
||||
"K64F": {
|
||||
"default_test_configuration": "HEAPBLOCKDEVICE_AND_ETHERNET",
|
||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_ETHERNET", "ESP8266_WIFI", "ETHERNET"]
|
||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_ETHERNET", "MAC_TESTER", "ESP8266_WIFI", "ETHERNET"]
|
||||
},
|
||||
"NUCLEO_F429ZI": {
|
||||
"default_test_configuration": "HEAPBLOCKDEVICE_AND_ETHERNET",
|
||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_ETHERNET"]
|
||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_ETHERNET", "MAC_TESTER"]
|
||||
},
|
||||
"DISCO_L475VG_IOT01A": {
|
||||
"default_test_configuration": "NONE",
|
||||
|
|
|
@ -179,6 +179,27 @@ def mkdir(path):
|
|||
makedirs(path)
|
||||
|
||||
|
||||
def write_json_to_file(json_data, file_name):
|
||||
"""
|
||||
Write json content in file
|
||||
:param json_data:
|
||||
:param file_name:
|
||||
:return:
|
||||
"""
|
||||
# Create the target dir for file if necessary
|
||||
test_spec_dir = os.path.dirname(file_name)
|
||||
|
||||
if test_spec_dir:
|
||||
mkdir(test_spec_dir)
|
||||
|
||||
try:
|
||||
with open(file_name, 'w') as f:
|
||||
f.write(json.dumps(json_data, indent=2))
|
||||
except IOError as e:
|
||||
print("[ERROR] Error writing test spec to file")
|
||||
print(e)
|
||||
|
||||
|
||||
def copy_file(src, dst):
|
||||
""" Implement the behaviour of "shutil.copy(src, dst)" without copying the
|
||||
permissions (this was causing errors with directories mounted with samba)
|
||||
|
|
Loading…
Reference in New Issue