[PATCH v7 19/21] dts: base traffic generators docstring update

Yoan Picchi yoan.picchi at foss.arm.com
Tue Nov 21 17:20:15 CET 2023


On 11/15/23 13:09, Juraj Linkeš wrote:
> Format according to the Google format and PEP257, with slight
> deviations.
> 
> Signed-off-by: Juraj Linkeš <juraj.linkes at pantheon.tech>
> ---
>   .../traffic_generator/__init__.py             | 22 ++++++++-
>   .../capturing_traffic_generator.py            | 46 +++++++++++--------
>   .../traffic_generator/traffic_generator.py    | 33 +++++++------
>   3 files changed, 68 insertions(+), 33 deletions(-)
> 
> diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/framework/testbed_model/traffic_generator/__init__.py
> index 11bfa1ee0f..51cca77da4 100644
> --- a/dts/framework/testbed_model/traffic_generator/__init__.py
> +++ b/dts/framework/testbed_model/traffic_generator/__init__.py
> @@ -1,6 +1,19 @@
>   # SPDX-License-Identifier: BSD-3-Clause
>   # Copyright(c) 2023 PANTHEON.tech s.r.o.
>   
> +"""DTS traffic generators.
> +
> +A traffic generator is capable of generating traffic and then monitor returning traffic.
> +A traffic generator may just count the number of received packets
> +and it may additionally capture individual packets.

The sentence feels odd. Isn't it supposed to be "or" here? and no need 
for that early of a line break

> +
> +A traffic generator may be software running on generic hardware or it could be specialized hardware.
> +
> +The traffic generators that only count the number of received packets are suitable only for
> +performance testing. In functional testing, we need to be able to dissect each arrived packet
> +and a capturing traffic generator is required.
> +"""
> +
>   from framework.config import ScapyTrafficGeneratorConfig, TrafficGeneratorType
>   from framework.exception import ConfigurationError
>   from framework.testbed_model.node import Node
> @@ -12,8 +25,15 @@
>   def create_traffic_generator(
>       tg_node: Node, traffic_generator_config: ScapyTrafficGeneratorConfig
>   ) -> CapturingTrafficGenerator:
> -    """A factory function for creating traffic generator object from user config."""
> +    """The factory function for creating traffic generator objects from the test run configuration.
> +
> +    Args:
> +        tg_node: The traffic generator node where the created traffic generator will be running.
> +        traffic_generator_config: The traffic generator config.
>   
> +    Returns:
> +        A traffic generator capable of capturing received packets.
> +    """
>       match traffic_generator_config.traffic_generator_type:
>           case TrafficGeneratorType.SCAPY:
>               return ScapyTrafficGenerator(tg_node, traffic_generator_config)
> diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
> index e521211ef0..b0a43ad003 100644
> --- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
> +++ b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
> @@ -23,19 +23,22 @@
>   
>   
>   def _get_default_capture_name() -> str:
> -    """
> -    This is the function used for the default implementation of capture names.
> -    """
>       return str(uuid.uuid4())
>   
>   
>   class CapturingTrafficGenerator(TrafficGenerator):
>       """Capture packets after sending traffic.
>   
> -    A mixin interface which enables a packet generator to declare that it can capture
> +    The intermediary interface which enables a packet generator to declare that it can capture
>       packets and return them to the user.
>   
> +    Similarly to
> +    :class:`~framework.testbed_model.traffic_generator.traffic_generator.TrafficGenerator`,
> +    this class exposes the public methods specific to capturing traffic generators and defines
> +    a private method that must implement the traffic generation and capturing logic in subclasses.
> +
>       The methods of capturing traffic generators obey the following workflow:
> +
>           1. send packets
>           2. capture packets
>           3. write the capture to a .pcap file
> @@ -44,6 +47,7 @@ class CapturingTrafficGenerator(TrafficGenerator):
>   
>       @property
>       def is_capturing(self) -> bool:
> +        """This traffic generator can capture traffic."""
>           return True
>   
>       def send_packet_and_capture(
> @@ -54,11 +58,12 @@ def send_packet_and_capture(
>           duration: float,
>           capture_name: str = _get_default_capture_name(),
>       ) -> list[Packet]:
> -        """Send a packet, return received traffic.
> +        """Send `packet` and capture received traffic.
> +
> +        Send `packet` on `send_port` and then return all traffic captured
> +        on `receive_port` for the given `duration`.
>   
> -        Send a packet on the send_port and then return all traffic captured
> -        on the receive_port for the given duration. Also record the captured traffic
> -        in a pcap file.
> +        The captured traffic is recorded in the `capture_name`.pcap file.
>   
>           Args:
>               packet: The packet to send.
> @@ -68,7 +73,7 @@ def send_packet_and_capture(
>               capture_name: The name of the .pcap file where to store the capture.
>   
>           Returns:
> -             A list of received packets. May be empty if no packets are captured.
> +             The received packets. May be empty if no packets are captured.
>           """
>           return self.send_packets_and_capture(
>               [packet], send_port, receive_port, duration, capture_name
> @@ -82,11 +87,14 @@ def send_packets_and_capture(
>           duration: float,
>           capture_name: str = _get_default_capture_name(),
>       ) -> list[Packet]:
> -        """Send packets, return received traffic.
> +        """Send `packets` and capture received traffic.
>   
> -        Send packets on the send_port and then return all traffic captured
> -        on the receive_port for the given duration. Also record the captured traffic
> -        in a pcap file.
> +        Send `packets` on `send_port` and then return all traffic captured
> +        on `receive_port` for the given `duration`.
> +
> +        The captured traffic is recorded in the `capture_name`.pcap file. The target directory
> +        can be configured with the :option:`--output-dir` command line argument or
> +        the :envvar:`DTS_OUTPUT_DIR` environment variable.
>   
>           Args:
>               packets: The packets to send.
> @@ -96,7 +104,7 @@ def send_packets_and_capture(
>               capture_name: The name of the .pcap file where to store the capture.
>   
>           Returns:
> -             A list of received packets. May be empty if no packets are captured.
> +             The received packets. May be empty if no packets are captured.
>           """
>           self._logger.debug(get_packet_summaries(packets))
>           self._logger.debug(
> @@ -124,10 +132,12 @@ def _send_packets_and_capture(
>           receive_port: Port,
>           duration: float,
>       ) -> list[Packet]:
> -        """
> -        The extended classes must implement this method which
> -        sends packets on send_port and receives packets on the receive_port
> -        for the specified duration. It must be able to handle no received packets.
> +        """The implementation of :method:`send_packets_and_capture`.
> +
> +        The subclasses must implement this method which sends `packets` on `send_port`
> +        and receives packets on `receive_port` for the specified `duration`.
> +
> +        It must be able to handle no received packets.

This sentence feels odd too. Maybe "It must be able to handle receiving 
no packets."

>           """
>   
>       def _write_capture_from_packets(
> diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
> index ea7c3963da..ed396c6a2f 100644
> --- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
> +++ b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
> @@ -22,7 +22,8 @@
>   class TrafficGenerator(ABC):
>       """The base traffic generator.
>   
> -    Defines the few basic methods that each traffic generator must implement.
> +    Exposes the common public methods of all traffic generators and defines private methods
> +    that must implement the traffic generation logic in subclasses.
>       """
>   
>       _config: TrafficGeneratorConfig
> @@ -30,6 +31,12 @@ class TrafficGenerator(ABC):
>       _logger: DTSLOG
>   
>       def __init__(self, tg_node: Node, config: TrafficGeneratorConfig):
> +        """Initialize the traffic generator.
> +
> +        Args:
> +            tg_node: The traffic generator node where the created traffic generator will be running.
> +            config: The traffic generator's test run configuration.
> +        """
>           self._config = config
>           self._tg_node = tg_node
>           self._logger = getLogger(
> @@ -37,9 +44,9 @@ def __init__(self, tg_node: Node, config: TrafficGeneratorConfig):
>           )
>   
>       def send_packet(self, packet: Packet, port: Port) -> None:
> -        """Send a packet and block until it is fully sent.
> +        """Send `packet` and block until it is fully sent.
>   
> -        What fully sent means is defined by the traffic generator.
> +        Send `packet` on `port`, then wait until `packet` is fully sent.
>   
>           Args:
>               packet: The packet to send.
> @@ -48,9 +55,9 @@ def send_packet(self, packet: Packet, port: Port) -> None:
>           self.send_packets([packet], port)
>   
>       def send_packets(self, packets: list[Packet], port: Port) -> None:
> -        """Send packets and block until they are fully sent.
> +        """Send `packets` and block until they are fully sent.
>   
> -        What fully sent means is defined by the traffic generator.
> +        Send `packets` on `port`, then wait until `packets` are fully sent.
>   
>           Args:
>               packets: The packets to send.
> @@ -62,19 +69,17 @@ def send_packets(self, packets: list[Packet], port: Port) -> None:
>   
>       @abstractmethod
>       def _send_packets(self, packets: list[Packet], port: Port) -> None:
> -        """
> -        The extended classes must implement this method which
> -        sends packets on send_port. The method should block until all packets
> -        are fully sent.
> +        """The implementation of :method:`send_packets`.
> +
> +        The subclasses must implement this method which sends `packets` on `port`.
> +        The method should block until all `packets` are fully sent.
> +
> +        What full sent means is defined by the traffic generator.

full -> fully

>           """
>   
>       @property
>       def is_capturing(self) -> bool:
> -        """Whether this traffic generator can capture traffic.
> -
> -        Returns:
> -            True if the traffic generator can capture traffic, False otherwise.
> -        """
> +        """This traffic generator can't capture traffic."""
>           return False
>   
>       @abstractmethod



More information about the dev mailing list