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