View Source Membrane.Testing.Pipeline (Membrane Core v1.0.1)

This Pipeline was created to reduce testing boilerplate and ease communication with its children. It also provides a utility for informing testing process about playback changes and received notifications.

When you want a build Pipeline to test your children you need three things:

  • Pipeline Module
  • List of children
  • Links between those children

To start a testing pipeline you need to build a keyword list representing the options used to determine the pipeline's behaviour and then pass that options list to the Membrane.Testing.Pipeline.start_link_supervised!/1. The testing pipeline can be started in one of two modes - either with its :default behaviour, or by injecting a custom module behaviour. The usage of a :default pipeline implementation is presented below:

links = [
    child(:el1, MembraneElement1) |>
    child(:el2, MembraneElement2)
    ...
]
options =  [
  module: :default # :default is the default value for this parameter, so you do not need to pass it here
  spec: links
]
pipeline = Membrane.Testing.Pipeline.start_link_supervised!(options)

You can also pass your custom pipeline's module as a :module option of the options list. Every callback of the module will be executed before the callbacks of Testing.Pipeline. Passed module has to return a proper spec. There should be no children nor links specified in options passed to test pipeline as that would result in a failure.

options = [
  module: Your.Module
]
pipeline = Membrane.Testing.Pipeline.start_link_supervised!(options)

See Membrane.Testing.Pipeline.options/0 for available options.

Assertions

This pipeline is designed to work with Membrane.Testing.Assertions. Check them out or see example below for more details.

Messaging children

You can send messages to children using their names specified in the children list. Please check message_child/3 for more details.

Example usage

Firstly, we can start the pipeline providing its options as a keyword list: import Membrane.ChildrenSpec children = [

  child(source, %Membrane.Testing.Source{} ) |>
  child(:tested_element, TestedElement) |>
  child(sink, %Membrane.Testing.Sink{})

] {:ok, pipeline} = Membrane.Testing.Pipeline.start_link(spec: links)

We can now wait till the end of the stream reaches the sink element (don't forget to import Membrane.Testing.Assertions):

assert_end_of_stream(pipeline, :sink)

We can also assert that the Membrane.Testing.Sink processed a specific buffer:

assert_sink_buffer(pipeline, :sink, %Membrane.Buffer{payload: 1})

Summary

Functions

Returns child specification for spawning under a supervisor

Executes specified actions in the pipeline.

Returns the pid of the children process.

Returns the pid of the children process.

Sends message to a child by Element name.

Starts the pipeline under the ExUnit test supervisor and links it to the current process.

Starts the pipeline under the ExUnit test supervisor.

Types

@type options() ::
  [
    module: :default,
    spec: [Membrane.ChildrenSpec.builder()],
    test_process: pid(),
    name: Membrane.Pipeline.name(),
    raise_on_child_pad_removed?: boolean()
  ]
  | [
      module: module(),
      custom_args: Membrane.Pipeline.pipeline_options(),
      test_process: pid(),
      name: Membrane.Pipeline.name()
    ]

Functions

@spec child_spec(options()) :: Supervisor.child_spec()

Returns child specification for spawning under a supervisor

Link to this function

execute_actions(pipeline, actions)

View Source
@spec execute_actions(pid(), Keyword.t()) :: :ok

Executes specified actions in the pipeline.

The actions are returned from the handle_info callback.

Link to this function

get_child_pid(pipeline, child_name_path)

View Source
@spec get_child_pid(
  pid(),
  child_name_path :: Membrane.Child.name() | [Membrane.Child.name()]
) ::
  {:ok, pid()} | {:error, reason :: term()}

Returns the pid of the children process.

Accepts pipeline pid as a first argument and a child reference or a list of child references representing a path as a second argument.

If second argument is a child reference, function gets pid of this child from pipeline.

If second argument is a path of child references, function gets pid of last a component pointed by this path.

Returns

  • {:ok, child_pid}, if a child was succesfully found
  • {:error, reason}, if, for example, pipeline is not alive or children path is invalid
Link to this function

get_child_pid!(parent_pid, child_name_path)

View Source
@spec get_child_pid!(
  pid(),
  child_name_path :: Membrane.Child.name() | [Membrane.Child.name()]
) :: pid()

Returns the pid of the children process.

Works as get_child_pid/2, but raises an error instead of returning {:error, reason} tuple.

Link to this function

message_child(pipeline, child, message)

View Source
@spec message_child(pid(), Membrane.Element.name(), any()) :: :ok

Sends message to a child by Element name.

Example

Knowing that pipeline has child named sink, message can be sent as follows:

message_child(pipeline, :sink, {:message, "to handle"})
@spec start(options()) :: Membrane.Pipeline.on_start()
@spec start_link(options()) :: Membrane.Pipeline.on_start()
Link to this function

start_supervised(pipeline_options \\ [])

View Source
@spec start_supervised(options()) :: Membrane.Pipeline.on_start()

Starts the pipeline under the ExUnit test supervisor.

Can be used only in tests.

Link to this function

start_supervised!(pipeline_options \\ [])

View Source
@spec start_supervised!(options()) :: pipeline_pid :: pid()
Link to this function

terminate(pipeline, opts \\ [])

View Source
@spec terminate(pid(), Keyword.t()) :: :ok | {:ok, pid()} | {:error, :timeout}

See Membrane.Pipeline.terminate/2.