code: def sequence_suite_helper(
      rng, input_cases: List[ArgData], ops_test_cases, num_iters=4
  ):
      """
      Generates suite of test cases for a sequence processing operator.
      The operator should meet the SequenceOperator assumptions, i.e.
      1. process frames (and possibly channels) independently,
      2. support per-frame tensor arguments.
      Each test case consists of two pipelines, one fed with the batch of sequences
      and one fed with the batch of frames, the test compares if the processing of
      corresponding frames in both pipelines gives the same result. In other words, if
      given batch = [sequence, ...], the following holds:
      fn.op([frame for sequence in batch for frame in sequence])
          == [frame for sequence in fn.op(batch) for frame in sequence]
      ----------
      `input_cases`: List[ArgData].
          Each ArgData instance describes a single parameter (positional or named) that will be
          passed to the pipeline and serve as a source of truth (regarding the number of expandable
          dimensions and sequence shape). Based on it, all other inputs defined through ArgCb
          in `ops_test_cases` will be computed.
          Note the `.desc.device` argument is ignored in favour of `ops_test_case` devices list.
      `ops_test_cases` : List[Tuple[
              Operator,
              Dict[str, Any],
              ParamProviderBase|List[ArgCb]]
          ]]
          List of operators and their parameters that should be tested.
          Each element is expected to be a tuple of the form: (
              fn.operator,
              {fixed_param_name: fixed_param_value},
              [ArgCb(tensor_arg_name, single_arg_cb, is_per_frame, dest_device)]
          )
          where the first element is ``fn.operator``, the second one is a dictionary of fixed
          arguments that should be passed to the operator and the third one is a list of ArgCb
          instances describing tensor input arguments or custom params provider instance
          (see `ParamsProvider`). The tuple can optionally have fourth element: a list of devices
          where the main input (from `input_cases`) should be placed.
      """
  
      class OpTestCase:
          def __init__(
              self,
              operator_fn,
              fixed_params,
              input_params,
              devices=None,
              input_name=0,
          ):
              self.operator_fn = operator_fn
              self.fixed_params = fixed_params
              self.input_params = input_params
              self.devices = (
                  ["cpu", "gpu"] if devices is None else devices
              )
  
      for test_case_args in ops_test_cases:
          test_case = OpTestCase(*test_case_args)
          for device in test_case.devices:
              for input_case in input_cases:
                  input_desc = input_case.desc
                  arg_desc = ArgDesc(
                      input_desc.name,
                      input_desc.expandable_prefix,
                      device,
                      input_desc.layout,
                  )
                  arg_data = ArgData(arg_desc, input_case.data)
                  yield (
                      _test_seq_input,
                      num_iters,
                      test_case.operator_fn,
                      test_case.fixed_params,
                      test_case.input_params,
                      arg_data,
                      rng,
                  )
  
imports: import os
  import random
  import numpy
  from typing import List, Union, Callable, Optional
  from dataclasses import dataclass, field
  from nvidia.dali import pipeline_def
  import nvidia.dali.fn
  from nvidia.dali import types
  import nvidia.dali.tensors
  from test_utils import get_dali_extra_path, check_batch
label_desc: Use image node_id 13 for calling a global function with example usage: sequence_suite_helper(rng, input_cases, ops_test_cases, num_iters) without return types