Back to Repositories

Testing Non-Blocking Parameter Operations in Openpilot

This test suite validates the non-blocking parameter handling functionality in the Openpilot system, focusing specifically on asynchronous parameter writing operations and thread management. The tests ensure proper handling of parameter storage and retrieval in a non-blocking context.

Test Coverage Overview

The test coverage focuses on non-blocking parameter operations in the Openpilot system. Key areas tested include:

  • Asynchronous parameter writing functionality
  • Thread state validation during operations
  • Parameter persistence verification
  • Multiple parameter handling with CarParams and IsMetric

Implementation Analysis

The testing approach utilizes Catch2 framework for C++ unit testing, implementing temporary directory creation for isolated parameter storage. The tests employ future/promise mechanisms to verify asynchronous operations, with specific focus on non-blocking put operations and subsequent parameter retrieval.

Technical Details

Testing components include:

  • Catch2 testing framework
  • Temporary directory management (mkdtemp)
  • std::future for async operation validation
  • Custom Params class implementation
  • Chrono library for timeout handling

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolation of test environment using temporary directories
  • Proper cleanup of resources
  • Verification of both immediate and eventual states
  • Clear separation of setup, execution, and verification phases
  • Comprehensive async operation validation

commaai/openpilot

common/tests/test_params.cc

            
#include "catch2/catch.hpp"
#define private public
#include "common/params.h"
#include "common/util.h"

TEST_CASE("params_nonblocking_put") {
  char tmp_path[] = "/tmp/asyncWriter_XXXXXX";
  const std::string param_path = mkdtemp(tmp_path);
  auto param_names = {"CarParams", "IsMetric"};
  {
    Params params(param_path);
    for (const auto &name : param_names) {
      params.putNonBlocking(name, "1");
      // param is empty
      REQUIRE(params.get(name).empty());
    }

    // check if thread is running
    REQUIRE(params.future.valid());
    REQUIRE(params.future.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout);
  }
  // check results
  Params p(param_path);
  for (const auto &name : param_names) {
    REQUIRE(p.get(name) == "1");
  }
}