can-utils/tests/test_can_calc_bit_timing.py

172 lines
5.8 KiB
Python

# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (c) 2025 Linux CAN project
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
import pytest
import subprocess
import os
import re
# --- Helper Functions ---
def run_ccbt(bin_path, args):
"""
Helper to run can-calc-bit-timing.
Returns the subprocess.CompletedProcess object.
"""
cmd = [os.path.join(bin_path, "can-calc-bit-timing")] + args
return subprocess.run(cmd, capture_output=True, text=True)
# --- Tests ---
def test_usage_on_invalid_option(bin_path):
"""
Description:
Tests that providing an invalid option (like -h) results in an error
message and prints the usage information.
Note: The tool does not support -h explicitly, it treats it as invalid.
Manual reproduction:
$ can-calc-bit-timing -h
> invalid option -- 'h'
> Usage: can-calc-bit-timing [options] ...
"""
result = run_ccbt(bin_path, ["-h"])
# Expect failure code usually for invalid options
assert result.returncode != 0
assert "Usage: can-calc-bit-timing" in result.stderr or "Usage: can-calc-bit-timing" in result.stdout
def test_list_controllers(bin_path):
"""
Description:
Tests the -l option to list all supported CAN controller names.
Manual reproduction:
$ can-calc-bit-timing -l
> ...
> mcp251x
> ...
"""
result = run_ccbt(bin_path, ["-l"])
assert result.returncode == 0
# Check for a common controller known to be in the list (e.g., mcp251x or sja1000)
# The list is usually quite long.
assert "mcp251x" in result.stdout or "sja1000" in result.stdout
def test_basic_calculation_stdout(bin_path):
"""
Description:
Tests a basic bit timing calculation for a standard bitrate (500k)
and clock (8MHz). Verifies that a table is produced.
Manual reproduction:
$ can-calc-bit-timing -c 8000000 -b 500000
> Bit rate : 500000 Rate error : 0.00% ...
"""
# 8MHz clock, 500kbit/s
result = run_ccbt(bin_path, ["-c", "8000000", "-b", "500000"])
assert result.returncode == 0
# Output should contain column headers like "SampP" (Sample Point) and the bitrate
assert "SampP" in result.stdout
assert "500000" in result.stdout
def test_quiet_mode(bin_path):
"""
Description:
Tests the -q option (quiet mode), which should suppress the header line.
Manual reproduction:
$ can-calc-bit-timing -q -c 8000000 -b 500000
> (Output should start with data, not the 'Bit timing parameters...' header)
"""
# Run without -q first to confirm header exists
res_std = run_ccbt(bin_path, ["-c", "8000000", "-b", "500000"])
assert "Bit timing parameters" in res_std.stdout
# Run with -q
res_quiet = run_ccbt(bin_path, ["-q", "-c", "8000000", "-b", "500000"])
assert res_quiet.returncode == 0
assert "Bit timing parameters" not in res_quiet.stdout
# Data should still be there
assert "500000" in res_quiet.stdout
def test_verbose_output(bin_path):
"""
Description:
Tests the -v option for verbose output.
Manual reproduction:
$ can-calc-bit-timing -v -c 8000000 -b 500000
"""
result = run_ccbt(bin_path, ["-v", "-c", "8000000", "-b", "500000"])
assert result.returncode == 0
# Verbose mode usually prints more details, but the table should definitely be there.
# We check for "SampP" to ensure valid calculation output.
assert "SampP" in result.stdout
def test_data_bitrate_fd(bin_path):
"""
Description:
Tests the -d option to specify a data bitrate (CAN FD).
Manual reproduction:
$ can-calc-bit-timing -c 40000000 -b 1000000 -d 2000000
"""
# 40MHz clock, 1M nominal, 2M data
result = run_ccbt(bin_path, ["-c", "40000000", "-b", "1000000", "-d", "2000000"])
assert result.returncode == 0
# Should calculate for both
assert "SampP" in result.stdout
assert "1000000" in result.stdout
assert "2000000" in result.stdout
def test_specific_sample_point(bin_path):
"""
Description:
Tests the -s option to define a specific sample point (e.g., 875 for 87.5%).
Manual reproduction:
$ can-calc-bit-timing -c 8000000 -b 500000 -s 875
> ... Sample Point : 87.5% ...
"""
# 875 means 87.5%
result = run_ccbt(bin_path, ["-c", "8000000", "-b", "500000", "-s", "875"])
assert result.returncode == 0
assert "87.5%" in result.stdout
def test_specific_algorithm(bin_path):
"""
Description:
Tests the --alg option to select a different algorithm.
Assuming 'v4_8' is a valid algorithm key based on source files
(can-calc-bit-timing-v4_8.c). Note: Valid keys depend on compilation.
We check if it accepts the flag without crashing, even if default is used.
Manual reproduction:
$ can-calc-bit-timing -c 8000000 -b 500000 --alg v4.8
(Note: algorithm naming convention might vary, using a safe check)
"""
# Trying to list supported algorithms first would be ideal if possible,
# but based on file list, let's try a standard calculation with a potentially valid alg string.
# If the alg string is invalid, it usually warns or errors.
# We simply check that the flag is parsed.
# "default" should always be valid.
result = run_ccbt(bin_path, ["-c", "8000000", "-b", "500000", "--alg", "default"])
assert result.returncode == 0