Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement double threaded auxiliary interface #74

Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ae31f40
Merge pull request #1 from eclipse/master
BKaDamien Mar 23, 2022
460cbee
Merge branch 'eclipse:master' into master
BKaDamien Mar 28, 2022
8e8704a
Merge branch 'eclipse:master' into master
BKaDamien Mar 29, 2022
f5c7706
Merge branch 'eclipse:master' into master
BKaDamien Apr 4, 2022
0b4ee0e
Merge branch 'eclipse:master' into master
BKaDamien Apr 13, 2022
3126843
Merge branch 'eclipse:master' into master
BKaDamien Apr 25, 2022
63928f7
Merge branch 'eclipse:master' into master
BKaDamien May 4, 2022
71c3cb4
Merge branch 'eclipse:master' into master
BKaDamien May 23, 2022
6598054
Merge branch 'eclipse:master' into master
BKaDamien May 25, 2022
2b9f286
Merge branch 'eclipse:master' into master
BKaDamien May 31, 2022
65dcc99
Refactor/generic return for all connectors (#47)
BKaDamien Jun 1, 2022
dd93ab2
Merge branch 'eclipse:master' into master
BKaDamien Jun 1, 2022
ff0004e
Merge branch 'eclipse:master' into master
BKaDamien Jun 4, 2022
e25c343
Merge branch 'eclipse:master' into master
BKaDamien Jun 7, 2022
26a80fe
Merge branch 'eclipse:master' into master
BKaDamien Jun 8, 2022
9f24535
- add first double threaded auxiliary interface implementation
BKaDamien Jun 15, 2022
163e826
- rework com aux template example
BKaDamien Jun 15, 2022
cace026
- add dt-aux interface to sphinx doc
BKaDamien Jun 15, 2022
dedb82f
- rewrite com_aux pytest entirely
BKaDamien Jun 18, 2022
572ff47
- exclude pass and __repr__ from test coverage
BKaDamien Jun 18, 2022
a51d393
- rework test com in tempates
BKaDamien Jun 18, 2022
a9d4533
- add bool for starting task in dt aux interface
BKaDamien Jun 18, 2022
666299b
- adapt template tests to new aux interface dt
BKaDamien Jun 20, 2022
9cd03c6
- rework cc_mp_proxy add _cc_send and _cc_receive implementation
BKaDamien Jun 21, 2022
255d2a2
- delete dt_proxy_auxiliary module
BKaDamien Jun 21, 2022
c4c2d03
- rework proxy aux test
BKaDamien Jun 22, 2022
6361957
feat: add double threaded auxiliary interface
BKaDamien Jun 22, 2022
5611da0
- fix typo
BKaDamien Jun 23, 2022
4e77121
- rename attached_tx_callback in attach_tx_callback
BKaDamien Jun 23, 2022
6b00eb6
- add chec of CCproxy channel in proxy aux
BKaDamien Jun 23, 2022
795427d
- update what's new in the sphinx documentation
BKaDamien Jun 23, 2022
43b94aa
-remove channel name from TypeError message
BKaDamien Jun 23, 2022
5552e93
Merge branch 'eclipse:master' into master
BKaDamien Jun 28, 2022
2f9023a
Merge branch 'master' into implement_double_threaded_auxiliary_interface
BKaDamien Jun 28, 2022
adc0b47
- add warning regarding pykiso to pytest conftest generation
BKaDamien Jun 28, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 0 additions & 46 deletions docs/advanced_features/aux_copies.rst

This file was deleted.

24 changes: 24 additions & 0 deletions docs/advanced_features/dynamic_conf.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Dynamic Configuration
=====================

In some situation, it can be useful to change the behaviour of the auxiliary in-use dynamically.
For example, switching for a brand new channel or simply change an attribute value.

Thanks to the common auxiliary interface, users can easily change their auxiliary
configuration by simply stop it (call of delete_instance public method) ,access
BKaDamien marked this conversation as resolved.
Show resolved Hide resolved
it different public attributes, and then just restarts the auxiliary (call of
the public method ``delete_instance``)

.. warning:: if you are using the original auxiliary instance don't forget to
switch back to its initial configuration for the next test cases.

Find below a complete example where during the test, the current pcan
connector is replaced by a simple CCLoopback:

.. literalinclude:: ../../examples/templates/suite_proxy/test_proxy.py
:language: python
:lines: 22-152

.. warning:: this feature allows to change the complete auxiliary configuration,
so depending on which parameters are changed the auxiliary execution could lead
to unexpected behaviors.
2 changes: 1 addition & 1 deletion docs/advanced_features/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ Advanced features
:maxdepth: 2

access_config
aux_copies
dynamic_conf
multiprocessing
5 changes: 5 additions & 0 deletions docs/auxiliary_interfaces/dt_aux.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
double threaded auxiliary
========================

.. automodule:: pykiso.interfaces.dt_auxiliary
:members:
1 change: 1 addition & 0 deletions docs/auxiliary_interfaces/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ Auxiliary interfaces
mp_auxiliary
simple_auxiliary
thread_auxiliary
dt_aux
32 changes: 31 additions & 1 deletion docs/examples/how_to_auxiliary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ possible usage of an auxiliary:
- The :py:class:`~pykiso.interfaces.simple_auxiliary.SimpleAuxiliaryInterface`
does not implement any kind of concurrent execution. It is suited for host-based applications where the auxiliary
initiates every possible action, i.e. the reception of data can always be expected.
- The :py:class:`~pykiso.interfaces.dt_auxiliary.DTAuxiliaryInterface`
is a double threaded base auxiliary, where a thread is used for the transmission
and a second one for the reception. It is suited for IO-bound tasks where
the reception of data cannot be expected.

Execution of an Auxiliary
~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -46,7 +50,11 @@ Concurrent auxiliary execution

The execution of concurrent auxiliaries (i.e. inheriting from :py:class:`~pykiso.interfaces.thread_auxiliary.AuxiliaryInterface`
or :py:class:`~pykiso.interfaces.mp_auxiliary.MpAuxiliaryInterface`) is
handled by the interfaces' :py:meth:`~pykiso.interfaces.thread_auxiliary.AuxiliaryInterface.run>` method.
handled by the interfaces' :py:meth:`run()<pykiso.interfaces.thread_auxiliary.AuxiliaryInterface.run>` method.

In the DTAuxiliaryInterface case, everything related to the tansmission is handled by
:py:meth:`~pykiso.interfaces.dt_auxiliary.DTAuxiliaryInterface._transmit_task` and for the reception
by :py:meth:`~pykiso.interfaces.dt_auxiliary.DTAuxiliaryInterface._reception_task`

Each command execution is handled in a thread-safe way by getting values from an input queue and
returning the command result in an output queue.
Expand Down Expand Up @@ -79,6 +87,20 @@ Each time the execution is entered, the following actions are performed:
#. Call the auxiliarie's :py:meth:`~pykiso.interfaces.thread_auxiliary.AuxiliaryInterface._receive_message` method
#. If something is returned, put it in the output queue, otherwise repeat this execution cycle.

For an auxiliary based on DTAuxiliaryInterface, the execution is slightly different due to the usage of two threads:

1. Verify if a request is available in the input queue

#. If the command message is "DELETE_AUXILIARY" the transmit task while loop ends

#. If the command message is a tuple of 2 elements starting with your custom command type, and then the data to send. This custom command has to be implemented in the :py:meth:`~pykiso.interfaces.dt_auxiliary.DTAuxiliaryInterface._run_command` method.

2. Verify if a Message is available for reception

#. Call the auxiliarie's :py:meth:`~pykiso.interfaces.dt_auxiliary.DTAuxiliaryInterface._receive_message` and simpy wait for a message coming from the connector.

#. If something is returned, put it in the output queue, otherwise repeat this execution cycle.

Implement an Auxiliary
~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -115,6 +137,10 @@ the following methods to be implemented:
:py:meth:`~pykiso.connector.CChannel.cc_receive` method. The received data can then be decoded according to a particular protocol, matched
against a previously sent request, or trigger any kind of further processing.

For the concurrent Auxiliary interface :py:class:`~pykiso.interfaces.dt_auxiliary.DTAuxiliaryInterface`,
only one significant difference :

- :py:meth:`~pykiso.interfaces.thread_auxiliary.AuxiliaryInterface._abort_command`: is not mandatory

.. _aux-tutorial-example:

Expand Down Expand Up @@ -242,6 +268,10 @@ See below an example implementing the basic functionalities of a Thread Auxiliar
except Exception:
logging.exception(f"Channel {self.channel} failed to receive data")

Regarding a concrete implementation using :py:class:`~pykiso.interfaces.dt_auxiliary.DTAuxiliaryInterface`
take a look to :py:class:`~pykiso.lib.auxiliaries.communication_auxiliary.CommunicationAuxiliary` source code.


More examples are available under :py:mod:`pykiso.lib.auxiliaries`.

.. note::
Expand Down
4 changes: 2 additions & 2 deletions docs/introduction/integration_test.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ following:
- provide the auxiliaries with the matching connectors
- generate the list of tests to perform
- provide the testcases with the auxiliaries they need
- verify if the tests can be performed
- verify if the tests can be performed
- for remote tests (see :ref:`../remote_test/remote_test`) flash and run and synchronize the tests on the auxiliaries
- gather the reports and publish the results

Expand All @@ -80,7 +80,7 @@ The **auxiliary** provides to the **test-coordinator** an interface to
interact with the physical or digital auxiliary target. It is composed
by 2 blocks:

- instance creation / deletion
- instance creation / deletion
- connectors to facilitate interaction and communication with the
device (e.g. messaging with *UART*)

Expand Down
12 changes: 6 additions & 6 deletions docs/remote_test/remote_test.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
Remote Test
===========

With the remote test approach, the idea is to execute tests on the targeted hardware to enable
With the remote test approach, the idea is to execute tests on the targeted hardware to enable
the developer to practice test-driven-development directly on the target.


Test Coordinator
~~~~~~~~~~~~~~~~

In the case of remote tests usage, the **test-coordinator** will still perform the same task
In the case of remote tests usage, the **test-coordinator** will still perform the same task
but will also:

- verify if the tests can be performed
Expand All @@ -24,10 +24,10 @@ For the remote test approach, auxiliaries should be composed by 2 blocks:
container)
- connectors to facilitate interaction and communication with the
device (e.g. flashing via *JTAG*, messaging with *UART*)

One example of implementation of such an auxiliary is the *device under test* auxiliary used with the TestApp.
In this specific case we have:

- As communication channel (**cchannel**) usually *UART*
- As flashing channel (**flashing**) usually *JTAG*

Expand All @@ -49,7 +49,7 @@ The Flasher Connectors usually provide only one method, :py:meth:`Flasher.flash`
.. _flashing-1:


Message Protocol
Message Protocol
~~~~~~~~~~~~~~~~

The message protocol is used (but not only) between the *device under
Expand Down Expand Up @@ -250,7 +250,7 @@ The flashing connector is in turn called from an appropriate auxiliary (usually
Implementation of Remote Tests
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For remote tests, RemoteTestCase / RemoteTestSuite should be used instead of BasicTestCase / BasicTestSuite, based on Message Protocol,
For remote tests, RemoteTestCase / RemoteTestSuite should be used instead of BasicTestCase / BasicTestSuite, based on Message Protocol,
users can configure the maximum time (in seconds) used to wait for a report.
This "timeout" is configurable for each available fixtures :

Expand Down
53 changes: 21 additions & 32 deletions examples/templates/suite_com/test_com.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"""

import logging
import time

import pykiso

Expand All @@ -42,17 +43,14 @@ def setUp(self):
logging.info(
f"--------------- SETUP: {self.test_suite_id}, {self.test_case_id} ---------------"
)
# just create a communication auxiliary with a bran new channel
# in order to send odd bytes. Always use named arguments!
# due to the fact that auto_start flag is set to False, this let
# the user to start the auxiliary on demand using start method
com_aux.start()
self.com_aux_odd = com_aux.create_copy(com=CCLoopback())
# just create a communication auxiliary based on the given
# parameters present in the yaml config (com_aux.yaml) to send
# even bytes
self.com_aux_even = self.com_aux_odd.create_copy()
# start com_aux_even because original configuration has
# auto_start flag set to False
self.com_aux_even.start()

# just suspend the current auxiliary execution
com_aux.suspend()
# just resume the current auxiliary execution
com_aux.resume()

def test_run(self):
"""Thanks to the usage of dev cc_raw_loopback, let's try to send
Expand All @@ -61,29 +59,20 @@ def test_run(self):
logging.info(
f"--------------- RUN: {self.test_suite_id}, {self.test_case_id} ---------------"
)
# first send the even bytes and stop the copy in order to
# automatically resume the original one (self.com_aux_odd)
self.com_aux_even.send_message(b"\x02\x04\x06")
response = self.com_aux_even.receive_message()
self.assertEqual(response, b"\x02\x04\x06")
# destroy com_aux_even and start working with com_aux_odd aux
# copy
self.com_aux_odd.destroy_copy()

# Then send the odd bytes and stop the copy in order to
# automatically resume the original one (com_aux)
self.com_aux_odd.send_message(b"\x01\x03\x05")
response = self.com_aux_odd.receive_message()
self.assertEqual(response, b"\x01\x03\x05")
# destroy com_aux_odd and start working with com_aux
com_aux.destroy_copy()
# send 20 requests over the connected channel and check if the
# command was successfully sent
for _ in range(20):
req = b"\x02\x04\x06"
logging.info(f"send request {req} over {com_aux.name}")
state = com_aux.send_message(req)
logging.info(f"request excecution state: {state}")
self.assertEqual(state, True)

# Just use the original communication auxiliary to send and
# receive some bytes
com_aux.send_message(b"\x01\x02\x03\x04\x05\x06")
response = com_aux.receive_message()
logging.info(f"received message: {response}")
self.assertEqual(response, b"\x01\x02\x03\x04\x05\x06")
# get the 20 first received messages
for _ in range(20):
response = com_aux.receive_message()
logging.info(f"received data {response}")
self.assertEqual(response, b"\x02\x04\x06")

def tearDown(self):
"""If a fixture is not use just override it like below."""
Expand Down
Loading