mirror of https://github.com/ARMmbed/mbed-os.git
commit
1eab0723ba
|
@ -88,3 +88,9 @@ tags
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
features/FEATURE_BLE/targets/TARGET_CORDIO/stack_backup/
|
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": {
|
"fea-ipv6": {
|
||||||
"help": "Used to globally disable ipv6 tracing features.",
|
"help": "Used to globally disable ipv6 tracing features.",
|
||||||
"value": null
|
"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
|
junit-xml
|
||||||
pyYAML
|
pyYAML
|
||||||
requests
|
requests
|
||||||
mbed-ls>=0.2.13
|
mbed-ls>=1.4.2,==1.*
|
||||||
mbed-host-tests>=1.1.2
|
mbed-host-tests>=1.1.2
|
||||||
mbed-greentea>=0.2.24
|
mbed-greentea>=0.2.24
|
||||||
beautifulsoup4>=4
|
beautifulsoup4>=4
|
||||||
|
@ -17,3 +17,4 @@ future>=0.16.0
|
||||||
six>=1.11.0
|
six>=1.11.0
|
||||||
git+https://github.com/armmbed/manifest-tool.git@v1.4.5
|
git+https://github.com/armmbed/manifest-tool.git@v1.4.5
|
||||||
mbed-cloud-sdk==2.0.0
|
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 project in tc.values():
|
||||||
for build in project:
|
for build in project:
|
||||||
try:
|
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]['elf'] = relpath(build[0]['elf'], path_to_file)
|
||||||
build[0]['bin'] = relpath(build[0]['bin'], path_to_file)
|
build[0]['bin'] = relpath(build[0]['bin'], path_to_file)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
if 'type' not in build[0]:
|
if 'type' not in build[0]:
|
||||||
build[0]['type'] = app_type
|
build[0]['type'] = app_type
|
||||||
build_data['builds'].append(build[0])
|
build_data['builds'].insert(0, build[0])
|
||||||
dump(build_data, open(filename, "w"), indent=4, separators=(',', ': '))
|
dump(build_data, open(filename, "wb"), indent=4, separators=(',', ': '))
|
||||||
|
|
|
@ -69,6 +69,7 @@ LEGACY_IGNORE_DIRS = set([
|
||||||
|
|
||||||
# Tests, here for simplicity
|
# Tests, here for simplicity
|
||||||
'TESTS',
|
'TESTS',
|
||||||
|
'TEST_APPS',
|
||||||
])
|
])
|
||||||
LEGACY_TOOLCHAIN_NAMES = {
|
LEGACY_TOOLCHAIN_NAMES = {
|
||||||
'ARM_STD':'ARM',
|
'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.
|
limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
TEST BUILD & RUN
|
TEST BUILD
|
||||||
"""
|
"""
|
||||||
from __future__ import print_function, division, absolute_import
|
from __future__ import print_function, division, absolute_import
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import json
|
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
|
||||||
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||||
sys.path.insert(0, ROOT)
|
sys.path.insert(0, ROOT)
|
||||||
|
|
||||||
from tools.config import ConfigException, Config
|
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.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.options import get_default_options_parser, extract_profile, extract_mcus
|
||||||
from tools.build_api import build_project, build_library
|
from tools.build_api import build_project, build_library
|
||||||
from tools.build_api import print_build_memory_usage
|
from tools.build_api import print_build_memory_usage
|
||||||
from tools.build_api import merge_build_data
|
from tools.build_api import merge_build_data
|
||||||
from tools.targets import TARGET_MAP
|
from tools.targets import TARGET_MAP
|
||||||
from tools.notifier.term import TerminalNotifier
|
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.test_exporters import ReportExporter, ResultExporterType
|
||||||
from tools.utils import argparse_filestring_type, argparse_lowercase_type, argparse_many
|
from tools.utils import argparse_filestring_type, argparse_lowercase_type, argparse_many
|
||||||
from tools.utils import argparse_dir_not_parent
|
from tools.utils import argparse_dir_not_parent
|
||||||
|
@ -111,9 +112,19 @@ if __name__ == '__main__':
|
||||||
dest="stats_depth",
|
dest="stats_depth",
|
||||||
default=2,
|
default=2,
|
||||||
help="Depth level for static memory report")
|
help="Depth level for static memory report")
|
||||||
|
|
||||||
parser.add_argument("--ignore", dest="ignore", type=argparse_many(str),
|
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)")
|
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()
|
options = parser.parse_args()
|
||||||
|
|
||||||
|
@ -126,8 +137,13 @@ if __name__ == '__main__':
|
||||||
all_tests = {}
|
all_tests = {}
|
||||||
tests = {}
|
tests = {}
|
||||||
|
|
||||||
|
# As default both test tools are enabled
|
||||||
|
if not (options.greentea or options.icetea):
|
||||||
|
options.greentea = True
|
||||||
|
options.icetea = True
|
||||||
|
|
||||||
# Target
|
# Target
|
||||||
if options.mcu is None :
|
if options.mcu is None:
|
||||||
args_error(parser, "argument -m/--mcu is required")
|
args_error(parser, "argument -m/--mcu is required")
|
||||||
mcu = extract_mcus(parser, options)[0]
|
mcu = extract_mcus(parser, options)[0]
|
||||||
|
|
||||||
|
@ -159,8 +175,13 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
# Find all tests in the relevant paths
|
# Find all tests in the relevant paths
|
||||||
for path in all_paths:
|
for path in all_paths:
|
||||||
all_tests.update(find_tests(path, mcu, toolchain,
|
all_tests.update(find_tests(
|
||||||
app_config=config))
|
base_dir=path,
|
||||||
|
target_name=mcu,
|
||||||
|
toolchain_name=toolchain,
|
||||||
|
icetea=options.icetea,
|
||||||
|
greentea=options.greentea,
|
||||||
|
app_config=config))
|
||||||
|
|
||||||
# Filter tests by name if specified
|
# Filter tests by name if specified
|
||||||
if options.names:
|
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 a path to a test spec is provided, write it to a file
|
||||||
if options.test_spec:
|
if options.test_spec:
|
||||||
test_spec_data = test_spec_from_test_builds(test_build)
|
write_json_to_file(test_spec_from_test_builds(test_build), options.test_spec)
|
||||||
|
|
||||||
# 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)
|
|
||||||
|
|
||||||
# If a path to a JUnit build report spec is provided, write it to a file
|
# If a path to a JUnit build report spec is provided, write it to a file
|
||||||
if options.build_report_junit:
|
if options.build_report_junit:
|
||||||
|
@ -296,3 +304,4 @@ if __name__ == '__main__':
|
||||||
traceback.print_exc(file=sys.stdout)
|
traceback.print_exc(file=sys.stdout)
|
||||||
print("[ERROR] %s" % str(e))
|
print("[ERROR] %s" % str(e))
|
||||||
sys.exit(1)
|
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
|
# Otherwise find the path to configuration file based on mbed OS interface
|
||||||
return TestConfig.get_config_path(config_name, target_name)
|
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
|
""" Finds all tests in a directory recursively
|
||||||
base_dir: path to the directory to scan for tests (ex. 'path/to/project')
|
:param 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')
|
:param 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')
|
:param toolchain_name: name of the toolchain to use for scanning (ex. 'GCC_ARM')
|
||||||
options: Compile options to pass to the toolchain (ex. ['debug-info'])
|
:param icetea: icetea enabled
|
||||||
app_config - location of a chosen mbed_app.json file
|
: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
|
returns a dictionary where keys are the test name, and the values are
|
||||||
lists of paths needed to biuld the test.
|
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 = Resources(MockNotifier(), collect_ignores=True)
|
||||||
base_resources.scan_with_config(base_dir, config)
|
base_resources.scan_with_config(base_dir, config)
|
||||||
|
|
||||||
dirs = [d for d in base_resources.ignored_dirs if basename(d) == 'TESTS']
|
if greentea:
|
||||||
ignoreset = MbedIgnoreSet()
|
dirs = [d for d in base_resources.ignored_dirs if basename(d) == 'TESTS']
|
||||||
|
ignoreset = MbedIgnoreSet()
|
||||||
|
|
||||||
for directory in dirs:
|
for directory in dirs:
|
||||||
ignorefile = join(directory, IGNORE_FILENAME)
|
ignorefile = join(directory, IGNORE_FILENAME)
|
||||||
if isfile(ignorefile):
|
if isfile(ignorefile):
|
||||||
ignoreset.add_mbedignore(directory, ignorefile)
|
ignoreset.add_mbedignore(directory, ignorefile)
|
||||||
for test_group_directory in os.listdir(directory):
|
for test_group_directory in os.listdir(directory):
|
||||||
grp_dir = join(directory, test_group_directory)
|
grp_dir = join(directory, test_group_directory)
|
||||||
if not isdir(grp_dir) or ignoreset.is_ignored(grp_dir):
|
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):
|
|
||||||
continue
|
continue
|
||||||
special_dirs = ['host_tests', 'COMMON']
|
grpignorefile = join(grp_dir, IGNORE_FILENAME)
|
||||||
if test_group_directory not in special_dirs and test_case_directory not in special_dirs:
|
if isfile(grpignorefile):
|
||||||
test_name = test_path_to_name(d, base_dir)
|
ignoreset.add_mbedignore(grp_dir, grpignorefile)
|
||||||
tests[(test_name, directory, test_group_directory, test_case_directory)] = [d]
|
for test_case_directory in os.listdir(grp_dir):
|
||||||
if test_case_directory == 'COMMON':
|
d = join(directory, test_group_directory, test_case_directory)
|
||||||
def predicate(base_pred, group_pred, name_base_group_case):
|
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
|
(name, base, group, case) = name_base_group_case
|
||||||
return base == base_pred and group == group_pred
|
return base == base_pred
|
||||||
commons.append((functools.partial(predicate, directory, test_group_directory), d))
|
|
||||||
if test_group_directory == 'COMMON':
|
commons.append((functools.partial(predicate, directory), grp_dir))
|
||||||
def predicate(base_pred, name_base_group_case):
|
|
||||||
(name, base, group, case) = name_base_group_case
|
if icetea:
|
||||||
return base == base_pred
|
dirs = [d for d in base_resources.ignored_dirs if basename(d) == 'TEST_APPS']
|
||||||
commons.append((functools.partial(predicate, directory), grp_dir))
|
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
|
# Apply common directories
|
||||||
for pred, path in commons:
|
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
|
# Drop identity besides name
|
||||||
return {name: paths for (name, _, _, _), paths in six.iteritems(tests)}
|
return {name: paths for (name, _, _, _), paths in six.iteritems(tests)}
|
||||||
|
|
||||||
|
|
||||||
def print_tests(tests, format="list", sort=True):
|
def print_tests(tests, format="list", sort=True):
|
||||||
"""Given a dictionary of tests (as returned from "find_tests"), print them
|
"""Given a dictionary of tests (as returned from "find_tests"), print them
|
||||||
in the specified format"""
|
in the specified format"""
|
||||||
|
@ -2235,7 +2256,8 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
|
||||||
"base_path": base_path,
|
"base_path": base_path,
|
||||||
"baud_rate": baud_rate,
|
"baud_rate": baud_rate,
|
||||||
"binary_type": "bootable",
|
"binary_type": "bootable",
|
||||||
"tests": {}
|
"tests": {},
|
||||||
|
"test_apps": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = True
|
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' in worker_result):
|
||||||
bin_file = norm_relative_path(worker_result['bin_file'], execution_directory)
|
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": [
|
"binaries": [
|
||||||
{
|
{
|
||||||
"path": bin_file
|
"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):
|
def test_spec_from_test_builds(test_builds):
|
||||||
return {
|
return {
|
||||||
"builds": test_builds
|
"builds": test_builds
|
||||||
}
|
}
|
|
@ -3,6 +3,9 @@
|
||||||
"HEAPBLOCKDEVICE": "HeapBlockDevice.json",
|
"HEAPBLOCKDEVICE": "HeapBlockDevice.json",
|
||||||
"HEAPBLOCKDEVICE_AND_ETHERNET": "HeapBlockDeviceAndEthernetInterface.json",
|
"HEAPBLOCKDEVICE_AND_ETHERNET": "HeapBlockDeviceAndEthernetInterface.json",
|
||||||
"HEAPBLOCKDEVICE_AND_WIFI": "HeapBlockDeviceAndWifiInterface.json",
|
"HEAPBLOCKDEVICE_AND_WIFI": "HeapBlockDeviceAndWifiInterface.json",
|
||||||
|
"ODIN_WIFI" : "OdinInterface.json",
|
||||||
|
"ODIN_ETHERNET" : "Odin_EthernetInterface.json",
|
||||||
|
"REALTEK_WIFI" : "RealtekInterface.json",
|
||||||
"ESP8266_WIFI" : "ESP8266Interface.json",
|
"ESP8266_WIFI" : "ESP8266Interface.json",
|
||||||
"ISM43362_WIFI" : "ISM43362Interface.json",
|
"ISM43362_WIFI" : "ISM43362Interface.json",
|
||||||
"IDW0XX1_WIFI" : "SpwfSAInterface.json",
|
"IDW0XX1_WIFI" : "SpwfSAInterface.json",
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
},
|
},
|
||||||
"K64F": {
|
"K64F": {
|
||||||
"default_test_configuration": "HEAPBLOCKDEVICE_AND_ETHERNET",
|
"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": {
|
"NUCLEO_F429ZI": {
|
||||||
"default_test_configuration": "HEAPBLOCKDEVICE_AND_ETHERNET",
|
"default_test_configuration": "HEAPBLOCKDEVICE_AND_ETHERNET",
|
||||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_ETHERNET"]
|
"test_configurations": ["HEAPBLOCKDEVICE_AND_ETHERNET", "MAC_TESTER"]
|
||||||
},
|
},
|
||||||
"DISCO_L475VG_IOT01A": {
|
"DISCO_L475VG_IOT01A": {
|
||||||
"default_test_configuration": "NONE",
|
"default_test_configuration": "NONE",
|
||||||
|
|
|
@ -179,6 +179,27 @@ def mkdir(path):
|
||||||
makedirs(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):
|
def copy_file(src, dst):
|
||||||
""" Implement the behaviour of "shutil.copy(src, dst)" without copying the
|
""" Implement the behaviour of "shutil.copy(src, dst)" without copying the
|
||||||
permissions (this was causing errors with directories mounted with samba)
|
permissions (this was causing errors with directories mounted with samba)
|
||||||
|
|
Loading…
Reference in New Issue