#!/usr/bin/env python3

# Copyright (C) 2017 Alexandre Abadie <alexandre.abadie@inria.fr>
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.

import sys
import os
from testrunner import run


EXPECTED_HELP = (
    'Command              Description',
    '---------------------------------------',
    'start_test           starts a test',
    'end_test             ends a test',
    'echo                 prints the input command',
    'reboot               Reboot the node',
    'ps                   Prints information about running threads.',
    'app_metadata         Returns application metadata'
)

EXPECTED_PS = (
    '\tpid | state    Q | pri',
    '\t  1 | pending  Q |  15',
    '\t  2 | running  Q |   7'
)

# In native we are directly executing the binary (no terminal program). We must
# therefore use Ctrl-V (DLE or "data link escape") before Ctrl-C to send a
# literal ETX instead of SIGINT.
# When using a board it is also a problem because we are using a "user friendly"
# terminal that interprets Ctrl-C. So until we have rawterm we must also use
# ctrl-v in boards.

DLE = '\x16'

CONTROL_C = DLE+'\x03'
CONTROL_D = DLE+'\x04'

CMDS = (
    (CONTROL_C, ('>')),
    ('start_test', ('[TEST_START]')),
    ('end_test', ('[TEST_END]')),
    ('\n', ('>')),
    ('123456789012345678901234567890123456789012345678901234567890',
        ('shell: command not found: '
         '123456789012345678901234567890123456789012345678901234567890')),
    ('unknown_command', ('shell: command not found: unknown_command')),
    ('help', EXPECTED_HELP),
    ('echo a string', ('\"echo\"\"a\"\"string\"')),
    ('ps', EXPECTED_PS),
    ('help', EXPECTED_HELP),
    ('reboot', ('test_shell.'))
)

PROMPT = '> '

BOARD = os.environ['BOARD']

def check_cmd(child, cmd, expected):
    child.expect(PROMPT)
    child.sendline(cmd)
    for line in expected:
        child.expect_exact(line)


def check_startup(child):
    child.sendline(CONTROL_C)
    child.expect_exact(PROMPT)


def check_and_get_bufsize(child):
    child.sendline('bufsize')
    child.expect('([0-9]+)\r\n')
    bufsize = int(child.match.group(1))

    return bufsize


def check_line_canceling(child):
    child.expect(PROMPT)
    child.sendline('garbage1234' + CONTROL_C)
    garbage_expected = 'garbage1234\r\r\n'
    garbage_received = child.read(len(garbage_expected))

    assert garbage_expected == garbage_received


def testfunc(child):
    # avoid sending an extra empty line on native.
    if BOARD == 'native':
        child.crlf = '\n'

    check_startup(child)

    bufsize = check_and_get_bufsize(child)

    check_line_canceling(child)

    # loop other defined commands and expected output
    for cmd, expected in CMDS:
        check_cmd(child, cmd, expected)


if __name__ == "__main__":
    sys.exit(run(testfunc))

@@ -1851,16 +1851,121 @@
 OARD'%5D%0A%0A
+%0Adef print_error(message):%0A    FAIL = '%5C033%5B91m'%0A    ENDC = '%5C033%5B0m'%0A    print(FAIL + message + ENDC)%0A%0A%0A
 def chec
@@ -2351,16 +2351,613 @@
 fsize%0A%0A%0A
+def check_line_exceeded(child, bufsize):%0A%0A    if BOARD == 'nrf52dk':%0A        # There is an issue with nrf52dk when the Virtual COM port is connected%0A        # and sending more than 64 bytes over UART. If no terminal is connected%0A        # to the Virtual COM and interfacing directly to the nrf52832 UART pins%0A        # the issue is not present. See issue #10639 on GitHub.%0A        print_error('test case %22check_line_exceeded%22 broken for nrf52dk. SKIP')%0A        return%0A%0A    longline = %22_%22*bufsize + %22verylong%22%0A%0A    child.sendline(longline)%0A    child.expect('shell: maximum line length exceeded')%0A%0A%0A
 def chec
@@ -3350,24 +3350,24 @@
 tup(child)%0A%0A
-
     bufsize 
@@ -3394,24 +3394,65 @@
 ize(child)%0A%0A
+    check_line_exceeded(child, bufsize)%0A%0A
     check_li

add test case for exceeding lines