Back to Repositories

Testing Tici Amplifier Hardware Integration in OpenPilot

This test suite validates the functionality of the amplifier component in the Tici hardware system for the OpenPilot platform. It includes comprehensive tests for initialization, shutdown operations, and error handling during siren playback scenarios.

Test Coverage Overview

The test suite provides thorough coverage of the Tici amplifier functionality, focusing on core operations and error conditions.

Key areas tested include:
  • Amplifier initialization and configuration
  • Global shutdown operations
  • Siren playback interference scenarios
  • I2C communication error detection
Integration points span the Panda interface and hardware configuration systems.

Implementation Analysis

The testing approach utilizes pytest fixtures and class-based organization for systematic hardware testing. The implementation employs setup and teardown methods to ensure clean test states, with proper hardware resets between test executions.

Notable patterns include:
  • Hardware state management through setup/teardown
  • I2C error detection and validation
  • Randomized timing for edge case testing

Technical Details

Testing infrastructure includes:
  • Pytest framework for test organization
  • Panda interface for hardware communication
  • Subprocess calls for system-level operations
  • DMesg monitoring for I2C error detection
  • Hardware abstraction through TICI and Amplifier classes

Best Practices Demonstrated

The test suite exemplifies robust hardware testing practices with thorough error checking and state management.

Notable practices include:
  • Proper test isolation through setup/teardown
  • Comprehensive error condition validation
  • Platform-specific test skipping
  • Debug mode support for troubleshooting
  • Randomized testing for edge cases

commaai/openpilot

system/hardware/tici/tests/test_amplifier.py

            
import pytest
import time
import random
import subprocess

from panda import Panda
from openpilot.system.hardware import TICI, HARDWARE
from openpilot.system.hardware.tici.hardware import Tici
from openpilot.system.hardware.tici.amplifier import Amplifier


class TestAmplifier:

  @classmethod
  def setup_class(cls):
    if not TICI:
      pytest.skip()

  def setup_method(self):
    # clear dmesg
    subprocess.check_call("sudo dmesg -C", shell=True)

    HARDWARE.reset_internal_panda()
    Panda.wait_for_panda(None, 30)
    self.panda = Panda()

  def teardown_method(self):
    HARDWARE.reset_internal_panda()

  def _check_for_i2c_errors(self, expected):
    dmesg = subprocess.check_output("dmesg", shell=True, encoding='utf8')
    i2c_lines = [l for l in dmesg.strip().splitlines() if 'i2c_geni a88000.i2c' in l]
    i2c_str = '
'.join(i2c_lines)

    if not expected:
      return len(i2c_lines) == 0
    else:
      return "i2c error :-107" in i2c_str or "Bus arbitration lost" in i2c_str

  def test_init(self):
    amp = Amplifier(debug=True)
    r = amp.initialize_configuration(Tici().get_device_type())
    assert r
    assert self._check_for_i2c_errors(False)

  def test_shutdown(self):
    amp = Amplifier(debug=True)
    for _ in range(10):
      r = amp.set_global_shutdown(True)
      r = amp.set_global_shutdown(False)
      # amp config should be successful, with no i2c errors
      assert r
      assert self._check_for_i2c_errors(False)

  def test_init_while_siren_play(self):
    for _ in range(10):
      self.panda.set_siren(False)
      time.sleep(0.1)

      self.panda.set_siren(True)
      time.sleep(random.randint(0, 5))

      amp = Amplifier(debug=True)
      r = amp.initialize_configuration(Tici().get_device_type())
      assert r

      if self._check_for_i2c_errors(True):
        break
    else:
      pytest.fail("didn't hit any i2c errors")