Как тестировать драйверы низкого уровня без наличия железа
Что проверяют
Понимаете ли вы, что без железа драйвер проверяется слоями и у каждого слоя свой предел доверия. Следом спрашивают, какие ошибки такие тесты гарантированно пропустят.
Как отвечать
Каркас строится от самого дешёвого уровня к самому близкому к железу:
- юнит-тесты на хосте: логику драйвера отделяют от доступа к регистрам слоем абстракции (HAL), а регистры и шину в тестах заменяет фейк или мок. Для C это Unity с CMock, CppUTest, GoogleTest с GoogleMock. Главная ценность здесь в инъекции ошибок: таймаут шины, флаг ошибки в статусном регистре, прерывание в неудобный момент;
- ядро Linux: KUnit для модульных тестов внутри ядра, kselftest и виртуальные устройства из самого ядра:
i2c-stub,gpio-sim,netdevsim,mac80211_hwsim,dummy_hcdдля USB; - эмуляция: QEMU для целых плат и периферии, Renode для микроконтроллеров со сценариями на Robot Framework, Simics для полносистемных моделей. Для своего чипа модель устройства часто пишут сами;
- анализ и отладочные сборки: статический анализ (sparse, Coccinelle, clang-tidy), а в ядре KASAN, KCSAN и lockdep ловят порчу памяти, гонки и взаимоблокировки;
- Windows: Driver Verifier ловит некорректную работу с памятью и IRQL.
Все эти этапы запускаются в CI, эмулятор поднимается в пайплайне как обычный процесс.
Отдельно проговорите ограничения. Эмулятор не повторяет реальные тайминги, электрические эффекты, особенности DMA и кешей, ошибки конкретной ревизии чипа. Поэтому финальный этап всё равно проходит на железе, часто на стенде hardware-in-the-loop, но туда попадает уже отфильтрованный код.
Где спотыкаются
Отвечают «запустим на виртуальной машине». Виртуалка без проброса устройства не даёт драйверу его железо, а для проброса железо уже нужно.
Проверяют только штатный путь. Большинство реальных падений драйверов живёт в обработке ошибок, и мок нужен именно для того, чтобы эти ошибки вызвать.
Выдают прохождение тестов в эмуляторе за готовность. Гонки и проблемы таймингов там часто не воспроизводятся, и об этом стоит сказать самому, не дожидаясь вопроса.