Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Commit

Permalink
Merge branch 'fix/bdd-tests' into release/v5.1
Browse files Browse the repository at this point in the history
  • Loading branch information
mathiasap committed Mar 5, 2019
2 parents cdc612d + 38c865d commit ebea6a3
Show file tree
Hide file tree
Showing 6 changed files with 289 additions and 10 deletions.
8 changes: 8 additions & 0 deletions tests/bdd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# bdd-tests

## dfu.feature

The following environment variables must be exported to run this test:

* SDK_ROOT: path to nRF5_SDK_15.2.0_9412b96 directory
* PCA10056_0 and PCA10056_1: jlink serial numbers
21 changes: 21 additions & 0 deletions tests/bdd/dfu.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Feature: Perform DFU
Scenario: USB serial DFU completes without error
Given the user wants to perform dfu usb-serial
And using package examples\dfu\secure_dfu_test_images\uart\nrf52840\blinky_mbr.zip
And nrfjprog examples\dfu\secure_bootloader\pca10056_usb_debug\hex\secure_bootloader_usb_mbr_pca10056_debug.hex for usb-serial PCA10056_0
Then perform dfu

Scenario: Serial DFU completes without error
Given the user wants to perform dfu serial
And using package examples\dfu\secure_dfu_test_images\uart\nrf52840\blinky_mbr.zip
And nrfjprog examples\dfu\secure_bootloader\pca10056_uart_debug\hex\secure_bootloader_uart_mbr_pca10056_debug.hex for serial PCA10056_0
Then perform dfu

Scenario: BLE DFU completes without error
Given the user wants to perform dfu ble
And using package examples\dfu\secure_dfu_test_images\ble\nrf52840\hrs_application_s140.zip
And option --conn-ic-id NRF52
And option --name DfuTarg
And nrfjprog examples\dfu\secure_bootloader\pca10056_ble_debug\hex\secure_bootloader_ble_s140_pca10056_debug.hex for ble PCA10056_0
And nrfjprog connectivity for serial PCA10056_1
Then perform dfu
10 changes: 0 additions & 10 deletions tests/bdd/genpkg_help_information.feature

This file was deleted.

20 changes: 20 additions & 0 deletions tests/bdd/help_information.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Feature: Help information
Scenario: User types pkg generate --help
Given user types 'nrfutil pkg generate --help'
When user press enter
Then output contains 'Generate a zip package for distribution to apps that support Nordic DFU' and exit code is 0

Scenario: User does not type mandatory arguments
Given user types 'nrfutil pkg generate'
When user press enter
Then output contains 'Error: Missing argument "ZIPFILE".' and exit code is 2

Scenario: User types --help
Given user types 'nrfutil --help'
When user press enter
Then output contains 'Show this message and exit.' and exit code is 0

Scenario: User types version
Given user types 'nrfutil version'
When user press enter
Then output version is correct
229 changes: 229 additions & 0 deletions tests/bdd/steps/dfu_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#
# Copyright (c) 2019 Nordic Semiconductor ASA
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this
# list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
#
# 3. Neither the name of Nordic Semiconductor ASA nor the names of other
# contributors to this software may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# 4. This software must only be used in or with a processor manufactured by Nordic
# Semiconductor ASA, or in or with a processor manufactured by a third party that
# is used in combination with a processor manufactured by Nordic Semiconductor.
#
# 5. Any software provided in binary or object form under this license must not be
# reverse engineered, decompiled, modified and/or disassembled.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

from Queue import Empty
import logging
import os
import time
import sys
import subprocess

from click.testing import CliRunner
from behave import then, given, when

from nordicsemi.__main__ import cli, int_as_text_to_int
from nordicsemi.lister.device_lister import DeviceLister
from pc_ble_driver_py import config
connectivity_root = os.path.join(os.path.dirname(config.__file__), 'hex', 'sd_api_v3')


ENUMERATE_WAIT_TIME = 2.0 # Seconds to wait for enumeration to finish

def resolve_hex_path(filename):
if filename == "connectivity":
hex_version = config.get_connectivity_hex_version()
filename = 'connectivity_{}_115k2_with_s132_3.1.hex'.format(hex_version)
return os.path.join(connectivity_root, filename)
elif filename == "connectivity_usb":
hex_version = config.get_connectivity_hex_version()
filename = 'connectivity_{}_usb_with_s132_3.1.hex'.format(hex_version)
return os.path.join(connectivity_root, filename)
else:
filename = os.path.join(*filename.split("\\"))
assert "SDK_ROOT" in os.environ, \
"Environment variable 'SDK_ROOT' must be exported"

SDK_ROOT = os.environ["SDK_ROOT"]
return os.path.join(SDK_ROOT, filename)


def find_nrfjprog(program):
"""
From pc-ble-driver-py/ble-driver.py
"""
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)

fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file

return None

def program_image_usb_serial(context, nrfjprog, full_image_path, snr):
lister = DeviceLister()

return_code = subprocess.call("\"{nrfjprog}\" --eraseall --snr {snr}" .format(nrfjprog=nrfjprog,snr=snr), shell=True)
assert return_code == 0, "Nrfjprog could not erase board with serial number {}".format(snr)
time.sleep(ENUMERATE_WAIT_TIME) # Waiting for device to enumerate

devices_before_programming = lister.get_device(get_all=True, vendor_id="1915", product_id="521F")

return_code = subprocess.call("\"{nrfjprog}\" --program {image} --chiperase -r --snr {snr}"
.format(nrfjprog=nrfjprog, image=full_image_path, snr=snr), shell=True)

assert return_code == 0, \
"Nrfjprog could program image {} to board with serial number {}".format(full_image_path, snr)

time.sleep(ENUMERATE_WAIT_TIME) # Waiting for device to enumerate

devices_after_programming = lister.get_device(get_all=True, vendor_id="1915", product_id="521F")

dfu_device = None

for device in devices_after_programming:
match = False
for device_old in devices_before_programming:
if device.serial_number == device_old.serial_number:
match = True
break
if not match:
dfu_device = device
break

assert dfu_device, "Device was programmed, but did not enumerate in {} seconds.".format(ENUMERATE_WAIT_TIME)

port = dfu_device.get_first_available_com_port()
return port


def program_image_serial(context, nrfjprog, full_image_path, snr):
lister = DeviceLister()

return_code = subprocess.call("\"{nrfjprog}\" --eraseall --snr {snr}"
.format(nrfjprog=nrfjprog,snr=snr), shell=True)

assert return_code == 0, "Nrfjprog could not erase board with serial number {}".format(snr)

return_code = subprocess.call("\"{nrfjprog}\" --program {image} --chiperase -r --snr {snr}"
.format(nrfjprog=nrfjprog, image=full_image_path, snr=snr), shell=True)

assert return_code == 0, \
"Nrfjprog could program image {} to board with serial number {}".format(full_image_path, snr)

time.sleep(ENUMERATE_WAIT_TIME) # Waiting for device to enumerate

snr_left_pad = snr
if (len(snr_left_pad)) < 12:
snr_left_pad = '0'*(12-len(snr_left_pad)) + snr_left_pad

device = lister.get_device(get_all=False, serial_number=snr_left_pad)
devices = lister.enumerate()

assert device, "Device was programmed, but did not enumerate in {} seconds.".format(ENUMERATE_WAIT_TIME)

port = device.get_first_available_com_port()
return port


def program_image_ble(nrfjprog, full_image_path, snr):
return_code = subprocess.call("\"{nrfjprog}\" --eraseall --snr {snr}"
.format(nrfjprog=nrfjprog,snr=snr), shell=True)
assert return_code == 0, "Nrfjprog could not erase board with serial number {}".format(snr)

return_code = subprocess.call("\"{nrfjprog}\" --program {image} --chiperase -r --snr {snr}"
.format(nrfjprog=nrfjprog, image=full_image_path, snr=snr), shell=True)

assert return_code == 0, \
"Nrfjprog could program image {} to board with serial number {}".format(full_image_path, snr)

logger = logging.getLogger(__file__)

STDOUT_TEXT_WAIT_TIME = 50 # Number of seconds to wait for expected output from stdout

@given(u'the user wants to perform dfu {dfu_type}')
def step_impl(context, dfu_type):
runner = CliRunner()
context.runner = runner
args = ['dfu', dfu_type]

context.args = args

@given(u'using package {package}')
def step_impl(context, package):
full_package_path = resolve_hex_path(package)
context.args.extend(['-pkg', full_package_path])
context.pkg = full_package_path

@given(u'option {args}')
def step_impl(context, args):
context.args.extend(args.split(" "))

@given(u'nrfjprog {image} for {image_type} {board}')
def step_impl(context, image, image_type, board):

full_image_path = resolve_hex_path(image)

nrfjprog = find_nrfjprog("nrfjprog")
if nrfjprog == None:
nrfjprog = find_nrfjprog("nrfjprog.exe")

assert nrfjprog, "nrfjprog is not installed"

assert board in os.environ, \
"Environment variable '{}' must be exported with JLink serial number".format(board)

snr = str(int(os.environ[board])) # Remove zeros to the left.

if image_type == "usb-serial":
port = program_image_usb_serial(context, nrfjprog, full_image_path, snr)
context.args.extend(['-p', port])
context.p = port
elif image_type == "serial":
port = program_image_serial(context, nrfjprog, full_image_path, snr)
context.args.extend(['-p', port])
context.p = port
elif image_type == 'ble':
program_image_ble(nrfjprog, full_image_path, snr)
else:
assert False, "Invalid dfu transport."




@then(u'perform dfu')
def step_impl(context):
result = context.runner.invoke(cli, context.args)
logger.debug("exit_code: %s, output: \'%s\'", result.exit_code, result.output)
assert result.exit_code == 0
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,14 @@ def step_impl(context, stdout_text, exit_code):
assert result.exit_code == int_as_text_to_int(exit_code)
assert result.output != None
assert result.output.find(stdout_text) >= 0

@then(u'output version is correct')
def step_impl(context):
assert "nrfutil_version" in os.environ, \
"Environment variable 'nrfutil_version' must be exported"
version = os.environ["nrfutil_version"]

result = context.runner.invoke(cli, context.args)
logger.debug("exit_code: %s, output: \'%s\'", result.exit_code, result.output)
assert result.output != None
assert result.output.find(version) >= 0

0 comments on commit ebea6a3

Please sign in to comment.