Skip to content

Commit

Permalink
[OIS] Add OTA requestor integration test and CI
Browse files Browse the repository at this point in the history
Add OTA requestor integration test implementation.
Add OTA requestor test options in run script.
Extending OIS workflow with build the OTA requestor example, build
the OTA provider (Linux), test OTA requestor example.

Signed-off-by: ATmobica <artur.tynecki@arm.com>
  • Loading branch information
ATmobica committed Jul 12, 2023
1 parent b9150ff commit f745bc1
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 1 deletion.
32 changes: 31 additions & 1 deletion .github/workflows/examples-openiotsdk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
- name: Checkout submodules & Bootstrap
uses: ./.github/actions/checkout-submodules-and-bootstrap
with:
platform: openiotsdk
platform: openiotsdk linux
extra-submodule-parameters: " --recursive"

- name: Set up environment for size reports
Expand Down Expand Up @@ -91,11 +91,28 @@ jobs:
examples/tv-app/openiotsdk/build/chip-openiotsdk-tv-app-example.elf \
/tmp/bloat_reports/
- name: Build ota-requestor-app example
id: build_ota_requestor_app
timeout-minutes: 10
run: |
scripts/examples/openiotsdk_example.sh -v 1 -V 0.0.1 ota-requestor-app
.environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
openiotsdk release ota-requestor-app \
examples/ota-requestor-app/openiotsdk/build/chip-openiotsdk-ota-requestor-app-example.elf \
/tmp/bloat_reports/
- name: Build unit tests (mbedtls)
id: build_unit_tests_mbedtls
run: |
scripts/examples/openiotsdk_example.sh -b mbedtls unit-tests
- name: Build the OTA provider (Linux)
id: build_ota_provider_app
if: steps.build_ota_requestor_app.outcome == 'success'
timeout-minutes: 10
run: |
scripts/examples/gn_build_example.sh examples/ota-provider-app/linux/ out/ota-provider chip_config_network_layer_ble=false
- name: "Test: shell example"
if: steps.build_shell.outcome == 'success'
run: |
Expand All @@ -119,6 +136,19 @@ jobs:
'scripts/run_in_ns.sh ${TEST_NETWORK_NAME}ns scripts/examples/openiotsdk_example.sh --no-activate -C test -n ${TEST_NETWORK_NAME}tap tv-app'
scripts/setup/openiotsdk/network_setup.sh -n $TEST_NETWORK_NAME down
- name: "Test: ota-requestor-app example"
if: steps.build_ota_requestor_app.outcome == 'success' && steps.build_ota_provider_app.outcome == 'success'
timeout-minutes: 30
run: |
mkdir out/binaries
cp examples/ota-requestor-app/openiotsdk/build/chip-openiotsdk-ota-requestor-app-example.elf out/binaries/
scripts/examples/openiotsdk_example.sh -c -v 2 -V 0.0.2 ota-requestor-app
cp examples/ota-requestor-app/openiotsdk/build/chip-openiotsdk-ota-requestor-app-example.ota out/binaries/
scripts/setup/openiotsdk/network_setup.sh -n $TEST_NETWORK_NAME up
scripts/run_in_python_env.sh out/venv \
'scripts/run_in_ns.sh ${TEST_NETWORK_NAME}ns scripts/examples/openiotsdk_example.sh --no-activate -p out/binaries -v 2 -V 0.0.2 -C test -n ${TEST_NETWORK_NAME}tap ota-requestor-app'
scripts/setup/openiotsdk/network_setup.sh -n $TEST_NETWORK_NAME down
- name: "Test: unit-tests (mbedtls)"
if: steps.build_unit_tests_mbedtls.outcome == 'success'
run: |
Expand Down
12 changes: 12 additions & 0 deletions scripts/examples/openiotsdk_example.sh
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,18 @@ function run_test() {
TEST_OPTIONS+=(--networkInterface="$FVP_NETWORK")
fi

if [[ "$EXAMPLE" == "ota-requestor-app" ]]; then
TEST_OPTIONS+=(--updateBinaryPath="${EXAMPLE_EXE_PATH/elf/"ota"}")
# Check if OTA provider exists, if so get the path to it
OTA_PROVIDER_APP=$(find . -type f -name "chip-ota-provider-app")
if [ -z "$OTA_PROVIDER_APP" ]; then
echo "Error: OTA provider application does not exist." >&2
exit 1
fi
TEST_OPTIONS+=(--otaProvider="$OTA_PROVIDER_APP")
TEST_OPTIONS+=(--softwareVersion="$APP_VERSION:$APP_VERSION_STR")
fi

if [[ -f $EXAMPLE_TEST_PATH/test_report_$EXAMPLE.json ]]; then
rm -rf "$EXAMPLE_TEST_PATH/test_report_$EXAMPLE".json
fi
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#
# Copyright (c) 2023 Project CHIP Authors
# All rights reserved.
#
# 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 logging
import os
import re

import chip.interaction_model
import pytest
from chip.clusters.Objects import OtaSoftwareUpdateRequestor
from chip.clusters.Types import NullValue
from common.utils import (connect_device, disconnect_device, discover_device, get_setup_payload, send_zcl_command,
write_zcl_attribute)

log = logging.getLogger(__name__)


@pytest.fixture(scope="session")
def binaryPath(request, rootDir):
if request.config.getoption('binaryPath'):
return request.config.getoption('binaryPath')
else:
return os.path.join(rootDir, 'examples/ota-requestor-app/openiotsdk/build/chip-openiotsdk-ota-requestor-app-example.elf')


@pytest.fixture(scope="session")
def updateBinaryPath(request, rootDir):
if request.config.getoption('updateBinaryPath'):
return request.config.getoption('updateBinaryPath')
else:
return os.path.join(rootDir, 'examples/ota-requestor-app/openiotsdk/build/chip-openiotsdk-ota-requestor-app-example.ota')


@pytest.fixture(scope="session")
def controllerConfig(request):
config = {
'vendorId': 0xFFF1,
'fabricId': 1,
'persistentStoragePath': '/tmp/openiotsdk-test-storage.json'
}
return config


@pytest.fixture(scope="session")
def otaProviderConfig(request, updateBinaryPath):
config = {
'discriminator': '3841',
'port': '5580',
'filePath': f'{updateBinaryPath}',
'persistentStoragePath': '/tmp/openiotsdk-test-ota-provider.json'
}
return config


@pytest.mark.smoketest
def test_smoke_test(device):
ret = device.wait_for_output("Open IoT SDK ota-requestor-app example application start")
assert ret is not None and len(ret) > 0
ret = device.wait_for_output("Open IoT SDK ota-requestor-app example application run")
assert ret is not None and len(ret) > 0


@pytest.mark.commissioningtest
def test_commissioning(device, controller):
assert controller is not None
devCtrl = controller

ret = device.wait_for_output("Open IoT SDK ota-requestor-app example application start")
assert ret is not None and len(ret) > 0

setupPayload = get_setup_payload(device)
assert setupPayload is not None

commissionable_device = discover_device(devCtrl, setupPayload)
assert commissionable_device is not None

assert commissionable_device.vendorId == int(setupPayload.attributes['VendorID'])
assert commissionable_device.productId == int(setupPayload.attributes['ProductID'])
assert commissionable_device.addresses[0] is not None

nodeId = connect_device(devCtrl, setupPayload, commissionable_device)
assert nodeId is not None
log.info("Device {} connected".format(commissionable_device.addresses[0]))

ret = device.wait_for_output("Commissioning completed successfully")
assert ret is not None and len(ret) > 0

assert disconnect_device(devCtrl, nodeId)


OTA_REQUESTOR_CTRL_TEST_ENDPOINT_ID = 0


@pytest.mark.ctrltest
def test_update_ctrl(device, controller, ota_provider, softwareVersion):
assert controller is not None
devCtrl = controller
version_number, version_str = softwareVersion

log.info("Setup OTA provider...")

# Get OTA provider setup payload
setupPayloadProvider = get_setup_payload(ota_provider)
assert setupPayloadProvider is not None

# Discover and commission the OTA provider
commissionable_provider_device = discover_device(devCtrl, setupPayloadProvider)
assert commissionable_provider_device is not None

providerNodeId = connect_device(devCtrl, setupPayloadProvider, commissionable_provider_device)
assert providerNodeId is not None

ret = ota_provider.wait_for_output("Commissioning completed successfully")
assert ret is not None and len(ret) > 0

log.info("OTA provider ready")
log.info("Setup OTA requestor...")

# Get OTA requestor setup payload
setupPayload = get_setup_payload(device)
assert setupPayload is not None

# Discover and commission the OTA requestor
commissionable_requestor_device = discover_device(devCtrl, setupPayload)
assert commissionable_requestor_device is not None

requestorNodeId = connect_device(devCtrl, setupPayload, commissionable_requestor_device)
assert requestorNodeId is not None

ret = device.wait_for_output("Commissioning completed successfully")
assert ret is not None and len(ret) > 0

log.info("OTA requestor ready")
log.info("Install ACL entries")

# Install necessary ACL entries in OTA provider to enable access by OTA requestor
err, res = write_zcl_attribute(devCtrl, "AccessControl", "Acl", providerNodeId, OTA_REQUESTOR_CTRL_TEST_ENDPOINT_ID,
[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [requestorNodeId], "targets": NullValue},
{"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": NullValue, "targets": [{"cluster": 41, "endpoint": NullValue, "deviceType": NullValue}]}])
assert err == 0
assert res[0].Status == chip.interaction_model.Status.Success

ota_provider.set_verbose(False)

log.info("Announce the OTA provider and start the firmware update process")

# Announce the OTA provider and start the firmware update process
err, res = send_zcl_command(devCtrl, "OtaSoftwareUpdateRequestor", "AnnounceOTAProvider", requestorNodeId, OTA_REQUESTOR_CTRL_TEST_ENDPOINT_ID,
dict(providerNodeID=providerNodeId, vendorID=int(setupPayloadProvider.attributes['VendorID']),
announcementReason=OtaSoftwareUpdateRequestor.Enums.OTAAnnouncementReason.kUrgentUpdateAvailable,
metadataForNode=None, endpoint=0))

ret = device.wait_for_output("New version of the software is available")
assert ret is not None and len(ret) > 1

version = ret[-1].split()[-1]
assert version_number == version

device.set_verbose(False)

log.info("New software image downloading and installing...")

ret = device.wait_for_output("Open IoT SDK ota-requestor-app example application start", timeout=1200)
assert ret is not None and len(ret) > 0

device.set_verbose(True)

ret = device.wait_for_output("Current software version")
assert ret is not None and len(ret) > 1

version_app = ret[-1].split()[-2:]
assert version_number == re.sub(r"[\[\]]", "", version_app[0])
assert version_str == version_app[1]

assert disconnect_device(devCtrl, requestorNodeId)
assert disconnect_device(devCtrl, providerNodeId)

0 comments on commit f745bc1

Please sign in to comment.