Repocop: различия между версиями
(typo fixes) |
|||
Строка 1: | Строка 1: | ||
[[ | [[Категория:Sisyphus]] | ||
[[ | [[Категория:Devel]] | ||
<!--MovedFromFreesourceInfo|AltLinux/Sisyphus/Tools/Repocop--> | <!--MovedFromFreesourceInfo|AltLinux/Sisyphus/Tools/Repocop--> | ||
{| | {| | ||
Строка 7: | Строка 7: | ||
[[Изображение:Robocop-12inch-5-01.jpg]] | [[Изображение:Robocop-12inch-5-01.jpg]] | ||
| | | | ||
[http://absurdopedia.wikia.com/wiki/%D0%9E%D0%B3%D1%80%D0%BE%D0%BC%D0%BD%D1%8B%D0%B9_%D0%B1%D0%BE%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%BE%D0%B1%D0%BE%D1%82 | [http://absurdopedia.wikia.com/wiki/%D0%9E%D0%B3%D1%80%D0%BE%D0%BC%D0%BD%D1%8B%D0%B9_%D0%B1%D0%BE%D0%B5%D0%B2%D0%BE%D0%B9_%D1%80%D0%BE%D0%B1%D0%BE%D1%82 Малый огромный боевой робот], созданный [http://absurdopedia.wikia.com/wiki/%D0%91%D0%B5%D0%B7%D1%83%D0%BC%D0%BD%D1%8B%D0%B5_%D1%83%D1%87%D0%B5%D0%BD%D1%8B%D0%B5 безумными учёными] | ||
для тестирования отдельных rpm пакетов или всего Сизифа. | для тестирования отдельных rpm пакетов или всего Сизифа. | ||
В отличие от [[sisyphus_check|sisyphus_check]], который настолько суров, что сначала убивает возможного | В отличие от [[sisyphus_check|sisyphus_check]], который настолько суров, что сначала убивает возможного | ||
нарушителя, а потом его допрашивает, repocop в открытый бой не вступает, ограничиваясь | нарушителя, а потом его допрашивает, repocop в открытый бой не вступает, ограничиваясь | ||
невнятными выкриками на американском английском и показом красных и желтых карточек. | невнятными выкриками на американском английском и показом красных и желтых карточек. | ||
Другими словами, repocop представляет собой платформу для запуска интеграционных тестов. | Другими словами, repocop представляет собой платформу для запуска интеграционных тестов. | ||
Результаты ежедневного тестирования Sisyphus публикуются на [http://repocop.altlinux.org/pub/repocop/reports/ repocop.altlinux.org] | Результаты ежедневного тестирования Sisyphus публикуются на [http://repocop.altlinux.org/pub/repocop/reports/ repocop.altlinux.org] | ||
Строка 51: | Строка 51: | ||
* Пример запуска repocop для тестирования свежесобранных пакетов: | * Пример запуска repocop для тестирования свежесобранных пакетов: | ||
:<pre>repocop-run ~/hasher/repo/*/RPMS.hasher/*.rpm</pre> | : <pre>repocop-run ~/hasher/repo/*/RPMS.hasher/*.rpm</pre> | ||
* Пример запуска repocop для тестирования репозитория: | * Пример запуска repocop для тестирования репозитория: | ||
:<pre>repocop-run /var/ftp/pub/Linux/ALT/Sisyphus/files/{noarch,i586}/RPMS</pre> | : <pre>repocop-run /var/ftp/pub/Linux/ALT/Sisyphus/files/{noarch,i586}/RPMS</pre> | ||
При повторном запуске будут тестироваться только новые пакеты, так как результаты тестов кешируются | При повторном запуске будут тестироваться только новые пакеты, так как результаты тестов кешируются | ||
Строка 76: | Строка 76: | ||
полезная опция <tt>-l (--last-run)</tt> означает | полезная опция <tt>-l (--last-run)</tt> означает «все пакеты, которые repocop-run тестировал при последнем запуске». | ||
Таким образом, сразу после запуска repocop-run для проверки всего репозитория имеет смысл вызвать | Таким образом, сразу после запуска repocop-run для проверки всего репозитория имеет смысл вызвать | ||
<tt>repocop-purge-except --last-run</tt>, чтобы устаревшие данные из кеша не попали в отчет, | <tt>repocop-purge-except --last-run</tt>, чтобы устаревшие данные из кеша не попали в отчет, | ||
а сразу после запуска repocop-run для проверки пробной сборки имеет смысл вызвать | а сразу после запуска repocop-run для проверки пробной сборки имеет смысл вызвать | ||
<tt>repocop-purge-given --last-run</tt>, чтобы удалить из кеша данные о пробной сборке, еще не попавшей в репозиторий. | <tt>repocop-purge-given --last-run</tt>, чтобы удалить из кеша данные о пробной сборке, еще не попавшей в репозиторий. | ||
Результаты тестов можно просмотреть либо непосредственно в кеше, либо воспользоваться каким-либо | Результаты тестов можно просмотреть либо непосредственно в кеше, либо воспользоваться каким-либо | ||
генератором отчетов, например, <tt>repocop-report-txt</tt>. | генератором отчетов, например, <tt>repocop-report-txt</tt>. | ||
<tt>repocop-report-txt</tt> обработает кеш и сложит результаты тестов в читабельном виде | <tt>repocop-report-txt</tt> обработает кеш и сложит результаты тестов в читабельном виде | ||
в подпапку <repocop cache dir>/reports/txt/. | в подпапку <repocop cache dir>/reports/txt/. | ||
==== | ==== Тестирование свежесобранных пакетов с помощью repocop-check ==== | ||
Утилита <tt>repocop-check</tt> | Утилита <tt>repocop-check</tt> — busybox для занятого майнтайнера. Позволяет в одном вызове проверить | ||
свежесобранные пакеты. (Сделано по заявке Дамира @damir). | свежесобранные пакеты. (Сделано по заявке Дамира @damir). | ||
Строка 95: | Строка 95: | ||
repocop-check /hasher/repo/*/RPMS/hasher /hasher/repo/SRPMS/hasher | repocop-check /hasher/repo/*/RPMS/hasher /hasher/repo/SRPMS/hasher | ||
Опция <tt>--newer <filename></tt> позволяет дополнительно отфильтровать те пакеты, которые новее, чем | Опция <tt>--newer <filename></tt> позволяет дополнительно отфильтровать те пакеты, которые новее, чем | ||
указанный <filename>. | указанный <filename>. | ||
Строка 104: | Строка 104: | ||
repocop-purge-given --no-db-vacuum -q "$@"</pre> | repocop-purge-given --no-db-vacuum -q "$@"</pre> | ||
==== | ==== Уход за кешем с помощью repocop-purge-* ==== | ||
Для ухода за кешем используются утилиты <tt>repocop-purge-* </tt>. | Для ухода за кешем используются утилиты <tt>repocop-purge-* </tt>. | ||
Строка 121: | Строка 121: | ||
опция <tt>-l (--last-run)</tt> означает | опция <tt>-l (--last-run)</tt> означает «все пакеты, которые repocop-run тестировал при последнем запуске». | ||
Опция <tt>-l</tt> по своей природе очень коварна, так как человек через минуту забывает, что именно он | Опция <tt>-l</tt> по своей природе очень коварна, так как человек через минуту забывает, что именно он | ||
запускал последний раз. Так что рекомендуется использовать ее больше в скриптах. | запускал последний раз. Так что рекомендуется использовать ее больше в скриптах. | ||
Строка 128: | Строка 128: | ||
repocop-purge-except /var/ftp/pub/Linux/ALT/Sisyphus/files/{SRPMS,i586/RPMS,i386/RPMS,noarch/RPMS} | repocop-purge-except /var/ftp/pub/Linux/ALT/Sisyphus/files/{SRPMS,i586/RPMS,i386/RPMS,noarch/RPMS} | ||
==== Пример автоматизации тестирования репозитария с помощью repocop | ==== Пример автоматизации тестирования репозитария с помощью repocop ==== | ||
Указанный скрипт можно запускать после каждого обновления дистрибутива, | Указанный скрипт можно запускать после каждого обновления дистрибутива, | ||
Строка 153: | Строка 153: | ||
qa-robot -m <sisyphus-cybertalk@???> -s repocop-bugreport repocop-report-qa-robot-fail</pre> | qa-robot -m <sisyphus-cybertalk@???> -s repocop-bugreport repocop-report-qa-robot-fail</pre> | ||
=== Как писать тесты для repocop | === Как писать тесты для repocop === | ||
Тест в общем случае состоит из нескольких исполняемых файлов и файлов данных со специальными именами, | Тест в общем случае состоит из нескольких исполняемых файлов и файлов данных со специальными именами, | ||
которые собраны в одном каталоге вида <tt><testname>/</tt>. | которые собраны в одном каталоге вида <tt><testname>/</tt>. | ||
Исполняемые файлы, входящие в тест, получают аргументы через переменные. | Исполняемые файлы, входящие в тест, получают аргументы через переменные. | ||
Тест возвращают значение через вызов одной из команд repocop-test-skip, repocop-test-ok, repocop-test-warn, repocop-test-fail. | Тест возвращают значение через вызов одной из команд repocop-test-skip, repocop-test-ok, repocop-test-warn, repocop-test-fail. | ||
Возвратить значение для каждого пакета нужно ровно 1 раз. | Возвратить значение для каждого пакета нужно ровно 1 раз. | ||
Строка 196: | Строка 196: | ||
repocop-test-info, repocop-test-warn, repocop-test-fail в качестве аргументов принимают сообщение об ошибке. | repocop-test-info, repocop-test-warn, repocop-test-fail в качестве аргументов принимают сообщение об ошибке. | ||
Дополнительная опция -k |--key <REPOCOP_PKG_KEY> позволяет явно указать пакет. | Дополнительная опция -k |--key <REPOCOP_PKG_KEY> позволяет явно указать пакет. | ||
Подробнее использоание этой опции будет разобрано в разделе | Подробнее использоание этой опции будет разобрано в разделе «Тесты -постпроцессоры». | ||
Многие тесты совместно используют одни и те же данные. Примером может служить база данных rpm.db, | Многие тесты совместно используют одни и те же данные. Примером может служить база данных rpm.db, | ||
которая создается в процессе работы repocop. Для каждого пакета в ней содержатся список файлов, значения | которая создается в процессе работы repocop. Для каждого пакета в ней содержатся список файлов, значения | ||
полей Group:, URL:, Requires:, Provides, скрипты %postun, | полей Group:, URL:, Requires:, Provides, скрипты %postun, и т. д., то есть вся информация, которая содержится | ||
в заголовке rpm пакета. | в заголовке rpm пакета. | ||
Кроме того, логика обработки данных меняется гораздо чаще, чем структура хранения данных. | Кроме того, логика обработки данных меняется гораздо чаще, чем структура хранения данных. | ||
Чтобы повысить повторную используемость кода и не прогонять весь репозиторий через тесты каждый раз, | Чтобы повысить повторную используемость кода и не прогонять весь репозиторий через тесты каждый раз, | ||
когда в тесте меняется логика, в repocop 0.07 введена новая | когда в тесте меняется логика, в repocop 0.07 введена новая сущность — коллекторы (сборщики данных). | ||
Коллекторы устроены в точности как тесты, но не возвращают никаких результатов, только собирают данные для своей базы. | Коллекторы устроены в точности как тесты, но не возвращают никаких результатов, только собирают данные для своей базы. | ||
Собранные коллекторами данные могут использоваться в тестах при вызове скриптов <testname>/done. | Собранные коллекторами данные могут использоваться в тестах при вызове скриптов <testname>/done. | ||
Строка 212: | Строка 212: | ||
в тестах использовать дешевые вызовы <testname>/done. | в тестах использовать дешевые вызовы <testname>/done. | ||
Рекомендуемый формат хранения собранных коллектором | Рекомендуемый формат хранения собранных коллектором данных — файл SQLite. Архитектура repocop | ||
не запрещает альтернативные форматы хранения, но разнородные форматы данных могут затруднить | не запрещает альтернативные форматы хранения, но разнородные форматы данных могут затруднить | ||
обработку данных тестами. Например, данные из разных файлов SQLite можно обработать одним запросом | обработку данных тестами. Например, данные из разных файлов SQLite можно обработать одним запросом | ||
SQLite, чего не скажешь о разнородных форматах. | SQLite, чего не скажешь о разнородных форматах. | ||
==== Предопределенные имена для файлов, входящих в тест | ==== Предопределенные имена для файлов, входящих в тест ==== | ||
{| border="1" | {| border="1" | ||
|- | |- | ||
Строка 232: | Строка 232: | ||
644 | 644 | ||
| | | | ||
инициализация схемы БД под SQLite. | инициализация схемы БД под SQLite. X — версия схемы. | ||
|- | |- | ||
| | | | ||
Строка 239: | Строка 239: | ||
644 | 644 | ||
| | | | ||
скрипты обновления схемы БД до версии Y на | скрипты обновления схемы БД до версии Y на SQL. | ||
|- | |- | ||
| | | | ||
Строка 337: | Строка 337: | ||
==== Тесты без состояния | ==== Тесты без состояния ==== | ||
простейшим примером тестов являются тесты без состояния, | простейшим примером тестов являются тесты без состояния, | ||
которые помнят только текущий пакет и сразу выдают сообщение об ошибке. | которые помнят только текущий пакет и сразу выдают сообщение об ошибке. | ||
Таким тестам не нужны <tt><testname>/init</tt> и <tt><testname>/done</tt>. | Таким тестам не нужны <tt><testname>/init</tt> и <tt><testname>/done</tt>. | ||
Они состоят из единственного скрипта <tt><testname>/test</tt>. | Они состоят из единственного скрипта <tt><testname>/test</tt>. | ||
Строка 349: | Строка 349: | ||
Аргументы <tt><testname>/test</tt>: | Аргументы <tt><testname>/test</tt>: | ||
REPOCOP_PKG_ROOT — директория, в которую распаковано содержимое пакета. | |||
REPOCOP_PKG_KEY — внутренний id пакета в базах repocop. Используется в тестах с состоянием. | |||
REPOCOP_PKG — полный путь к пакету. | |||
также доступны | также доступны | ||
REPOCOP_PKG_NAME | REPOCOP_PKG_NAME | ||
Строка 358: | Строка 358: | ||
REPOCOP_PKG_EPOCH | REPOCOP_PKG_EPOCH | ||
тест без состояния упаковывается в rpm как %_datadir/repocop/pkgtests/%testname/test | тест без состояния упаковывается в rpm как %_datadir/repocop/pkgtests/%testname/test | ||
либо как %_libdir/repocop/pkgtests/%testname/test, в зависимости от языка, на котором он написан. | либо как %_libdir/repocop/pkgtests/%testname/test, в зависимости от языка, на котором он написан. | ||
Строка 400: | Строка 400: | ||
%changelog</pre> | %changelog</pre> | ||
==== Тесты с состоянием | ==== Тесты с состоянием ==== | ||
Тест общего вида инициализирует свое состояние с помощью <tt><testname>/init.sql.*</tt>, (в общем | Тест общего вида инициализирует свое состояние с помощью <tt><testname>/init.sql.*</tt>, (в общем случае — при вызове <tt><testname>/init</tt>). | ||
По мере прохождения тест может накапливать информацию о пакетах, исспользуя <testname>/test, | По мере прохождения тест может накапливать информацию о пакетах, исспользуя <testname>/test, | ||
а в конце работы обработать ее и сообщить о найденных ошибках в скрипте <testname>/done. | а в конце работы обработать ее и сообщить о найденных ошибках в скрипте <testname>/done. | ||
Строка 437: | Строка 437: | ||
в переменной REPOCOP_TEST_CACHEDIR тесту передается его личная постоянная директория, | в переменной REPOCOP_TEST_CACHEDIR тесту передается его личная постоянная директория, | ||
чтобы он мог хранить в ней свое состояние как между вызовами <testname>/test так и между | чтобы он мог хранить в ней свое состояние как между вызовами <testname>/test так и между | ||
вызовами repocop-run. а в переменной REPOCOP_TEST_TMPDIR тесту передается его личная | вызовами repocop-run. а в переменной REPOCOP_TEST_TMPDIR тесту передается его личная | ||
временная директория, которая сохраняется между вызовами <testname>/test и в конце | временная директория, которая сохраняется между вызовами <testname>/test и в конце | ||
гарантированно удаляется силами repocop-run. | гарантированно удаляется силами repocop-run. | ||
Строка 497: | Строка 497: | ||
===== Инициализация коллектора | ===== Инициализация коллектора ===== | ||
Рекомендуемый формат хранения базы данных, собираемой коллектором --- файл SQLite с именем <tt><testname>.db</tt>, | Рекомендуемый формат хранения базы данных, собираемой коллектором --- файл SQLite с именем <tt><testname>.db</tt>, | ||
расположенный в REPOCOP_TEST_DBDIR. repocop в значительной мере упрощает инициализацию баз данных такого | расположенный в REPOCOP_TEST_DBDIR. repocop в значительной мере упрощает инициализацию баз данных такого | ||
вида. При наличии файла <tt><testname>/init.sql.x</tt> | вида. При наличии файла <tt><testname>/init.sql.x</tt> (инициализация схемы БД под SQLite. x — версия схемы.) repocop | ||
проверяет, есть ли уже файл REPOCOP_TEST_DBDIR/<testname>.db и при необходимости создает из указанной схемы. | проверяет, есть ли уже файл REPOCOP_TEST_DBDIR/<testname>.db и при необходимости создает из указанной схемы. | ||
Если файл базы уже есть, то repocop запрашивает ее версию командой | Если файл базы уже есть, то repocop запрашивает ее версию командой «PRAGMA user_version». Если эта версия и число x | ||
совпадают, на этом инициализация заканчивается. Если текущая версия больше х, то происходит аварийный останов. | совпадают, на этом инициализация заканчивается. Если текущая версия больше х, то происходит аварийный останов. | ||
Если текущая версия больше х, то ищутся скрипты <tt><testname>/upgrade.sql.Y</tt>, где Y от currrent version+1 до x, и | Если текущая версия больше х, то ищутся скрипты <tt><testname>/upgrade.sql.Y</tt>, где Y от currrent version+1 до x, и | ||
последовательно выполняются. Если найден скрипт <tt><testname>/upgrade</tt>, то он тоже выполняется. | последовательно выполняются. Если найден скрипт <tt><testname>/upgrade</tt>, то он тоже выполняется. | ||
Если же скриптов обновления не найдено, то старая база удаляется. Также, если это тест, то его результаты тоже удаляются. | Если же скриптов обновления не найдено, то старая база удаляется. Также, если это тест, то его результаты тоже удаляются. | ||
Строка 514: | Строка 514: | ||
В этом случае для инициализации предусмотрен скрипт <tt><testname>/init</tt>. | В этом случае для инициализации предусмотрен скрипт <tt><testname>/init</tt>. | ||
===== Обработка коллектором пакетов | ===== Обработка коллектором пакетов ===== | ||
Обработка коллектором пакетов производится через вызовы <tt><testname>/test</tt> полностью аналогично тестам | Обработка коллектором пакетов производится через вызовы <tt><testname>/test</tt> полностью аналогично тестам | ||
без состояния. Единственное отличие в том, что коллектор использует переменную окружения REPOCOP_PKG_KEY | без состояния. Единственное отличие в том, что коллектор использует переменную окружения REPOCOP_PKG_KEY | ||
— внутренний id пакета в базах repocop. Коллектор не должен изобретать свои собственные идентификаторы пакета, | |||
а должен сохранять всю собранную информацию с этим REPOCOP_PKG_KEY. | а должен сохранять всю собранную информацию с этим REPOCOP_PKG_KEY. | ||
===== Завершение работы коллектора | ===== Завершение работы коллектора ===== | ||
Если после работы коллектора остался какой-то мусор, его можно удалить в скрипте <tt><testname>/done</tt>. | Если после работы коллектора остался какой-то мусор, его можно удалить в скрипте <tt><testname>/done</tt>. | ||
===== Уход за базой данных коллектора | ===== Уход за базой данных коллектора ===== | ||
Со временем БД коллектора накапливает устаревшие записи о пакетах, которых больше нет в репозитории. | Со временем БД коллектора накапливает устаревшие записи о пакетах, которых больше нет в репозитории. | ||
Если коллектор хранит данные в базе вида REPOCOP_TEST_DBDIR/<testname>.db, то утилиты repocop-purge-* | Если коллектор хранит данные в базе вида REPOCOP_TEST_DBDIR/<testname>.db, то утилиты repocop-purge-* | ||
удалят из всех таблиц, содержащих колонку PKGID (название заглавными буквами) строки, соответствующие | удалят из всех таблиц, содержащих колонку PKGID (название заглавными буквами) строки, соответствующие | ||
устаревшим pkgid. ( | устаревшим pkgid. (pkgid — это то, что передается коллектору в переменной окружения REPOCOP_PKG_KEY). | ||
После этого дополнительно вызывается SQL скрипт <tt><testname>/purge.sql</tt>, если он существует. | После этого дополнительно вызывается SQL скрипт <tt><testname>/purge.sql</tt>, если он существует. | ||
Если же коллектор использует свое собственное хранилище, для удаления устаревших записей из собственного | Если же коллектор использует свое собственное хранилище, для удаления устаревших записей из собственного | ||
кеша теста он должен предоставить скрипт <tt><testname>/purge</tt>. | кеша теста он должен предоставить скрипт <tt><testname>/purge</tt>. | ||
утилиты repocop-purge-* вызовут этот скрипт автоматически. | утилиты repocop-purge-* вызовут этот скрипт автоматически. | ||
Строка 539: | Строка 539: | ||
==== Тесты -постпроцессоры ==== | ==== Тесты -постпроцессоры ==== | ||
Постпроцессор — это тест, который '''не''' тестирует отдельные пакеты, а использует готовые базы данных, | |||
собранные коллекторами. Такой тест состоит из единственного скрипта <tt><testname>/done</tt>. | собранные коллекторами. Такой тест состоит из единственного скрипта <tt><testname>/done</tt>. | ||
Допустимо, что тест-постпроцессор не использует статус skip для пакетов, которые не попадают под действие теста, | Допустимо, что тест-постпроцессор не использует статус skip для пакетов, которые не попадают под действие теста, | ||
в связи с тем, что статус skip им присваивается по умолчанию. Однако не желательно, | в связи с тем, что статус skip им присваивается по умолчанию. Однако не желательно, | ||
хотя и допустимо , что тест-постпроцессор не использует статус ok. | хотя и допустимо, что тест-постпроцессор не использует статус ok. | ||
Поскольку при вызове <tt>repocop-test-*</tt> отсутствует естественный контекст (текущий пакет), то постпроцессор | Поскольку при вызове <tt>repocop-test-*</tt> отсутствует естественный контекст (текущий пакет), то постпроцессор | ||
должен явно указывать пакет, на который вешается статус. Для этого утилитам <tt>repocop-test-*</tt> передается | должен явно указывать пакет, на который вешается статус. Для этого утилитам <tt>repocop-test-*</tt> передается | ||
опция <tt>-k|--key <pkgid></tt>, где <pkgid> в свое время был получен соответствующим коллектором через | опция <tt>-k|--key <pkgid></tt>, где <pkgid> в свое время был получен соответствующим коллектором через | ||
переменную окружения REPOCOP_PKG_KEY и сохранен им в своей базе. | переменную окружения REPOCOP_PKG_KEY и сохранен им в своей базе. | ||
Строка 561: | Строка 561: | ||
for i in `cat $REPOCOP_TEST_TMPDIR/ok`; do repocop-test-ok -k $i; done | for i in `cat $REPOCOP_TEST_TMPDIR/ok`; do repocop-test-ok -k $i; done | ||
rm $REPOCOP_TEST_TMPDIR/*</pre> | rm $REPOCOP_TEST_TMPDIR/*</pre> | ||
==== Тесты пакетов с исходниками | |||
==== Тесты пакетов с исходниками ==== | |||
тесты пакетов с исходниками аналогичны тестам бинарных пакетов, за исключением того, что | тесты пакетов с исходниками аналогичны тестам бинарных пакетов, за исключением того, что | ||
они устанавливаются в <tt>%_datadir/repocop/srctests/</tt>. | они устанавливаются в <tt>%_datadir/repocop/srctests/</tt>. | ||
тестам передается в переменной | тестам передается в переменной | ||
REPOCOP_PKG — полный путь к src.rpm пакету. | |||
REPOCOP_PKG_ROOT — директория, в которую распаковано содержимое пакета. | |||
(для пакетов с исходниками по умолчанию распаковывается только spec-файл. | (для пакетов с исходниками по умолчанию распаковывается только spec-файл. | ||
содержимомое src. | содержимомое src.rpm — нужно ли это будет кому-то?) | ||
Дополнительно в переменной REPOCOP_PKG_SPECFILE передается полный путь к спек-файлу. | Дополнительно в переменной REPOCOP_PKG_SPECFILE передается полный путь к спек-файлу. | ||
также доступны | также доступны | ||
Строка 576: | Строка 577: | ||
REPOCOP_PKG_RELEASE | REPOCOP_PKG_RELEASE | ||
REPOCOP_PKG_EPOCH | REPOCOP_PKG_EPOCH | ||
и т. д., полностью аналогично тестам бинарных пакетов. | |||
пример простейшего теста. | пример простейшего теста. |
Версия от 10:08, 2 сентября 2008
Малый огромный боевой робот, созданный безумными учёными для тестирования отдельных rpm пакетов или всего Сизифа. В отличие от sisyphus_check, который настолько суров, что сначала убивает возможного нарушителя, а потом его допрашивает, repocop в открытый бой не вступает, ограничиваясь невнятными выкриками на американском английском и показом красных и желтых карточек. Другими словами, repocop представляет собой платформу для запуска интеграционных тестов. Результаты ежедневного тестирования Sisyphus публикуются на repocop.altlinux.org а так же доступны через web-интерфейс prometeus на http://sisyphus.ru/. |
Установка
установка repocop на локальной машине:
$ apt-get install repocop repocop-unittest
repocop состоит из следующих пакетов:
repocop |
основной пакет. |
---|---|
repocop-prometeus |
Плагин к prometeus. не нужен при обычнй установке. |
Сами тесты вместе с пакетом не идут, их надо устанавливать отдельно.
Полный список тестов можно посмотреть на http://sisyphus.ru/find.shtml?request=repocop-unittest.
Для удобства виртуальный пакет repocop-unittest позволяет установить все официальные тесты, которые используются в cybertalk@ и на http://sisyphus.ru/.
Запуск
- Пример запуска repocop для тестирования свежесобранных пакетов:
repocop-run ~/hasher/repo/*/RPMS.hasher/*.rpm
- Пример запуска repocop для тестирования репозитория:
repocop-run /var/ftp/pub/Linux/ALT/Sisyphus/files/{noarch,i586}/RPMS
При повторном запуске будут тестироваться только новые пакеты, так как результаты тестов кешируются в <repocop cache dir>. По умолчанию <repocop cache dir> равно ~/.repocop. Значение по умолчанию для <repocop cache dir> можно переопределить с помощью опции -c <repocop cache dir> либо поменять с помощью переменной окружения REPOCOP_CACHEDIR. Например, так: export REPOCOP_CACHEDIR=/tmp/.private/user/repocop.
Для ухода за кешем используются утилиты repocop-purge-* .
repocop-purge-except |
очистить все записи, кроме относящихся к пакетам, данным как аргументы. |
repocop-purge-given |
очистить все записи, относящиеся к пакетам, данным как аргументы. |
полезная опция -l (--last-run) означает «все пакеты, которые repocop-run тестировал при последнем запуске».
Таким образом, сразу после запуска repocop-run для проверки всего репозитория имеет смысл вызвать
repocop-purge-except --last-run, чтобы устаревшие данные из кеша не попали в отчет,
а сразу после запуска repocop-run для проверки пробной сборки имеет смысл вызвать
repocop-purge-given --last-run, чтобы удалить из кеша данные о пробной сборке, еще не попавшей в репозиторий.
Результаты тестов можно просмотреть либо непосредственно в кеше, либо воспользоваться каким-либо генератором отчетов, например, repocop-report-txt. repocop-report-txt обработает кеш и сложит результаты тестов в читабельном виде в подпапку <repocop cache dir>/reports/txt/.
Тестирование свежесобранных пакетов с помощью repocop-check
Утилита repocop-check — busybox для занятого майнтайнера. Позволяет в одном вызове проверить свежесобранные пакеты. (Сделано по заявке Дамира @damir).
Пример вызова: repocop-check /hasher/repo/*/RPMS/hasher /hasher/repo/SRPMS/hasher
Опция --newer <filename> позволяет дополнительно отфильтровать те пакеты, которые новее, чем указанный <filename>.
Исходный код.
#!/bin/sh -e repocop-run -q "$@" repocop-report-stdout "$@" repocop-purge-given --no-db-vacuum -q "$@"
Уход за кешем с помощью repocop-purge-*
Для ухода за кешем используются утилиты repocop-purge-* .
repocop-purge-except |
очистить все записи, кроме относящихся к пакетам, данным как аргументы. |
repocop-purge-given |
очистить все записи, относящиеся к пакетам, данным как аргументы. |
опция -l (--last-run) означает «все пакеты, которые repocop-run тестировал при последнем запуске».
Опция -l по своей природе очень коварна, так как человек через минуту забывает, что именно он
запускал последний раз. Так что рекомендуется использовать ее больше в скриптах.
пример вызова repocop-purge-* для очистки кеша от устаревших пакетов: repocop-purge-except /var/ftp/pub/Linux/ALT/Sisyphus/files/{SRPMS,i586/RPMS,i386/RPMS,noarch/RPMS}
Пример автоматизации тестирования репозитария с помощью repocop
Указанный скрипт можно запускать после каждого обновления дистрибутива, руками или через cron.
#!/bin/sh # you may choose alternative path to cachedir export REPOCOP_CACHEDIR=~/.repocop # edit paths to repository below !!! repocop-run /var/ftp/pub/Linux/ALT/Sisyphus/files/{noarch,i586}/RPMS repocop-purge-except --last-run repocop-report-txt >/dev/null ## sample code for publishing txt reports (by repocop-report-txt) on ftp ## # uncomment and fix it. # FTP_HOME=/var/ftp/pub/people/repocop # rm -rf $FTP_HOME/reports/txt # mkdir -p $FTP_HOME/reports # cp -a $REPOCOP_CACHEDIR/reports/txt $FTP_HOME/reports/ ## code for qa-robot mail scam. see man qa-robot for details qa-robot -m <sisyphus-cybertalk@???> -s repocop-warning repocop-report-qa-robot-warn qa-robot -m <sisyphus-cybertalk@???> -s repocop-bugreport repocop-report-qa-robot-fail
Как писать тесты для repocop
Тест в общем случае состоит из нескольких исполняемых файлов и файлов данных со специальными именами, которые собраны в одном каталоге вида <testname>/. Исполняемые файлы, входящие в тест, получают аргументы через переменные. Тест возвращают значение через вызов одной из команд repocop-test-skip, repocop-test-ok, repocop-test-warn, repocop-test-fail. Возвратить значение для каждого пакета нужно ровно 1 раз.
repocop-test-skip |
тесту нечего проверять в данном пакете. |
repocop-test-ok |
пакет попадает под определение теста и с ним все в порядке. |
repocop-test-experimental |
ошибок нет, но тест советует сделать экспериментальное/разрабатываемое изменение. |
repocop-test-info |
ошибок нет, есть замечания к пакету, пакет можно сделать лучше. |
repocop-test-warn |
несущественная ошибка, пакет можно сделать лучше. |
repocop-test-fail |
найдена существенная ошибка. |
repocop-test-info, repocop-test-warn, repocop-test-fail в качестве аргументов принимают сообщение об ошибке. Дополнительная опция -k |--key <REPOCOP_PKG_KEY> позволяет явно указать пакет. Подробнее использоание этой опции будет разобрано в разделе «Тесты -постпроцессоры».
Многие тесты совместно используют одни и те же данные. Примером может служить база данных rpm.db, которая создается в процессе работы repocop. Для каждого пакета в ней содержатся список файлов, значения полей Group:, URL:, Requires:, Provides, скрипты %postun, и т. д., то есть вся информация, которая содержится в заголовке rpm пакета.
Кроме того, логика обработки данных меняется гораздо чаще, чем структура хранения данных. Чтобы повысить повторную используемость кода и не прогонять весь репозиторий через тесты каждый раз, когда в тесте меняется логика, в repocop 0.07 введена новая сущность — коллекторы (сборщики данных). Коллекторы устроены в точности как тесты, но не возвращают никаких результатов, только собирают данные для своей базы. Собранные коллекторами данные могут использоваться в тестах при вызове скриптов <testname>/done.
Это позволяет дорогие по машинному времени вызовы <testname>/test сосредоточить в коллекторах, а в тестах использовать дешевые вызовы <testname>/done.
Рекомендуемый формат хранения собранных коллектором данных — файл SQLite. Архитектура repocop не запрещает альтернативные форматы хранения, но разнородные форматы данных могут затруднить обработку данных тестами. Например, данные из разных файлов SQLite можно обработать одним запросом SQLite, чего не скажешь о разнородных форматах.
Предопределенные имена для файлов, входящих в тест
имя |
mode |
функция |
<testname>/init.sql.x |
644 |
инициализация схемы БД под SQLite. X — версия схемы. |
<testname>/upgrade.sql.Y |
644 |
скрипты обновления схемы БД до версии Y на SQL. |
<testname>/upgrade |
755 |
общий скрипт обновления схемы БД. Используется в случае, когда SQL недостаточно. |
<testname>/init |
755 |
Инициализатор. Запускается 1 раз при запуске repocop. |
<testname>/test |
755 |
Обработчик пакетов. Будет запуcкаться для каждого обрабатываемого пакета. |
<testname>/done |
755 |
Подведение итогов и деструктор. запускается 1 раз в конце работы repocop. |
<testname>/purge |
755 |
Удаление устаревших записей из собственного кеша теста. Вызывается утилитами repocop-purge-*. |
<testname>/purge.sql |
644 |
Удаление устаревших записей из собственной БД теста. Вызывается утилитами repocop-purge-*. |
<testname>/description |
644 |
Описание теста. Не используется, но возможно использование в будущем. |
Упаковка тестов в пакеты rpm
%_datadir/repocop/pkgtests/%testname/* |
тест бинарных пакетов |
%_libdir/repocop/pkgtests/%testname/* |
тест бинарных пакетов |
%_datadir/repocop/pkgcollectors/%testname/* |
коллектор бинарных пакетов |
%_libdir/repocop/pkgcollectors/%testname/* |
коллектор бинарных пакетов |
%_datadir/repocop/srctests/%testname/* |
тест исходных пакетов |
%_libdir/repocop/srctests/%testname/* |
тест исходных пакетов |
%_datadir/repocop/srccollectors/%testname/* |
коллектор исходных пакетов |
%_libdir/repocop/srccollectors/%testname/* |
коллектор исходных пакетов |
Тесты без состояния
простейшим примером тестов являются тесты без состояния, которые помнят только текущий пакет и сразу выдают сообщение об ошибке. Таким тестам не нужны <testname>/init и <testname>/done. Они состоят из единственного скрипта <testname>/test.
<testname>/test вызывается для тех пакетов, которые еще не обрабатывались этим тестом. Если файл <testname>/test новее, чем результаты тестов, то они удаляются как устаревшие и соответствующие пакеты проходят тест заново.
Аргументы <testname>/test: REPOCOP_PKG_ROOT — директория, в которую распаковано содержимое пакета. REPOCOP_PKG_KEY — внутренний id пакета в базах repocop. Используется в тестах с состоянием. REPOCOP_PKG — полный путь к пакету. также доступны REPOCOP_PKG_NAME REPOCOP_PKG_VERSION REPOCOP_PKG_RELEASE REPOCOP_PKG_EPOCH
тест без состояния упаковывается в rpm как %_datadir/repocop/pkgtests/%testname/test либо как %_libdir/repocop/pkgtests/%testname/test, в зависимости от языка, на котором он написан.
Простейший тест на shell:
#!/bin/sh grep -s -q -r $REPOCOP_PKG_NAME-buildroot $REPOCOP_PKG_ROOT/ && \ exec repocop-test-fail "found paths to buildroot:" || exec repocop-test-ok
тест не совсем корректный, так как на самом деле нужно искать $REPOCOP_SRC_NAME-buildroot (damir@)
Пример спек-файла для упаковки теста repocop без состояния.
%define testname sampletest Name: repocop-unittest-%testname Version: 0.01 Release: alt1 BuildArch: noarch Packager: Igor Yu. Vlasenko <viy@altlinux.org> Summary: %testname intergration tests for repocop test platform. Group: Development/Other License: GPL or Artistic %description The test warns packages that ... %prep %build cat > test <<'EOF' #!/bin/bash # enter your test here EOF %install mkdir -p %buildroot%_datadir/repocop/pkgtests/%testname/ install -m 755 test %buildroot%_datadir/repocop/pkgtests/%testname/ %files %_datadir/repocop/pkgtests/%testname %changelog
Тесты с состоянием
Тест общего вида инициализирует свое состояние с помощью <testname>/init.sql.*, (в общем случае — при вызове <testname>/init). По мере прохождения тест может накапливать информацию о пакетах, исспользуя <testname>/test, а в конце работы обработать ее и сообщить о найденных ошибках в скрипте <testname>/done.
Полезные переменные.
REPOCOP_TEST_CACHEDIR |
личная постоянная директория. |
REPOCOP_TEST_TMPDIR |
личная временная директория. |
REPOCOP_TEST_NAME |
<testname>. |
REPOCOP_TEST_DBDIR |
каталог с базами данных SQLite установленных коллекторов. |
REPOCOP_TEST_DB |
личная база данных SQLite теста или коллектора. |
в переменной REPOCOP_TEST_CACHEDIR тесту передается его личная постоянная директория, чтобы он мог хранить в ней свое состояние как между вызовами <testname>/test так и между вызовами repocop-run. а в переменной REPOCOP_TEST_TMPDIR тесту передается его личная временная директория, которая сохраняется между вызовами <testname>/test и в конце гарантированно удаляется силами repocop-run.
Тест общего вида может быть одновременно и коллектором, и постпроцессором, однако удобно, когда эти задачи разнесены в отдельные пакеты.
Коллекторы
Коллектор отличается от теста тем, что он никогда не вызывает repocop-test-*, и, следовательно, единственным резудльтатом работы коллектора является создание базы данных. Также, для упаковки коллекторов предусмотрены каталоги
%_datadir/repocop/pkgcollectors/%testname/* |
коллектор бинарных пакетов |
%_libdir/repocop/pkgcollectors/%testname/* |
коллектор бинарных пакетов |
%_datadir/repocop/srccollectors/%testname/* |
коллектор исходных пакетов |
%_libdir/repocop/srccollectors/%testname/* |
коллектор исходных пакетов |
а для тестов -
%_datadir/repocop/pkgtests/%testname/* |
тест бинарных пакетов |
%_libdir/repocop/pkgtests/%testname/* |
тест бинарных пакетов |
%_datadir/repocop/srctests/%testname/* |
тест исходных пакетов |
%_libdir/repocop/srctests/%testname/* |
тест исходных пакетов |
Инициализация коллектора
Рекомендуемый формат хранения базы данных, собираемой коллектором --- файл SQLite с именем <testname>.db, расположенный в REPOCOP_TEST_DBDIR. repocop в значительной мере упрощает инициализацию баз данных такого вида. При наличии файла <testname>/init.sql.x (инициализация схемы БД под SQLite. x — версия схемы.) repocop проверяет, есть ли уже файл REPOCOP_TEST_DBDIR/<testname>.db и при необходимости создает из указанной схемы.
Если файл базы уже есть, то repocop запрашивает ее версию командой «PRAGMA user_version». Если эта версия и число x совпадают, на этом инициализация заканчивается. Если текущая версия больше х, то происходит аварийный останов. Если текущая версия больше х, то ищутся скрипты <testname>/upgrade.sql.Y, где Y от currrent version+1 до x, и последовательно выполняются. Если найден скрипт <testname>/upgrade, то он тоже выполняется. Если же скриптов обновления не найдено, то старая база удаляется. Также, если это тест, то его результаты тоже удаляются. repocop автоматически помечает базу версией x и при апгрейде, и при созданиии.
Альтернативно, коллектор может вести свою базу в REPOCOP_TEST_CACHEDIR в каком угодно формате. В этом случае для инициализации предусмотрен скрипт <testname>/init.
Обработка коллектором пакетов
Обработка коллектором пакетов производится через вызовы <testname>/test полностью аналогично тестам без состояния. Единственное отличие в том, что коллектор использует переменную окружения REPOCOP_PKG_KEY — внутренний id пакета в базах repocop. Коллектор не должен изобретать свои собственные идентификаторы пакета, а должен сохранять всю собранную информацию с этим REPOCOP_PKG_KEY.
Завершение работы коллектора
Если после работы коллектора остался какой-то мусор, его можно удалить в скрипте <testname>/done.
Уход за базой данных коллектора
Со временем БД коллектора накапливает устаревшие записи о пакетах, которых больше нет в репозитории. Если коллектор хранит данные в базе вида REPOCOP_TEST_DBDIR/<testname>.db, то утилиты repocop-purge-* удалят из всех таблиц, содержащих колонку PKGID (название заглавными буквами) строки, соответствующие устаревшим pkgid. (pkgid — это то, что передается коллектору в переменной окружения REPOCOP_PKG_KEY). После этого дополнительно вызывается SQL скрипт <testname>/purge.sql, если он существует.
Если же коллектор использует свое собственное хранилище, для удаления устаревших записей из собственного кеша теста он должен предоставить скрипт <testname>/purge. утилиты repocop-purge-* вызовут этот скрипт автоматически.
Тесты -постпроцессоры
Постпроцессор — это тест, который не тестирует отдельные пакеты, а использует готовые базы данных, собранные коллекторами. Такой тест состоит из единственного скрипта <testname>/done. Допустимо, что тест-постпроцессор не использует статус skip для пакетов, которые не попадают под действие теста, в связи с тем, что статус skip им присваивается по умолчанию. Однако не желательно, хотя и допустимо, что тест-постпроцессор не использует статус ok. Поскольку при вызове repocop-test-* отсутствует естественный контекст (текущий пакет), то постпроцессор должен явно указывать пакет, на который вешается статус. Для этого утилитам repocop-test-* передается опция -k|--key <pkgid>, где <pkgid> в свое время был получен соответствующим коллектором через переменную окружения REPOCOP_PKG_KEY и сохранен им в своей базе.
Пример простого теста-постпроцессора.
#!/bin/sh sqlite3 "$REPOCOP_TEST_DBDIR/altlinux-alternatives.db" <<EOSQL .mode tabs .output $REPOCOP_TEST_TMPDIR/warn select distinct pkgid from altlinux_alternatives where altisxml>0; .output $REPOCOP_TEST_TMPDIR/ok select distinct pkgid from altlinux_alternatives where altisxml=0; EOSQL for i in `cat $REPOCOP_TEST_TMPDIR/warn`; do repocop-test-warn -k $i "xml format of alternatives is obsolete"; done for i in `cat $REPOCOP_TEST_TMPDIR/ok`; do repocop-test-ok -k $i; done rm $REPOCOP_TEST_TMPDIR/*
Тесты пакетов с исходниками
тесты пакетов с исходниками аналогичны тестам бинарных пакетов, за исключением того, что они устанавливаются в %_datadir/repocop/srctests/. тестам передается в переменной REPOCOP_PKG — полный путь к src.rpm пакету. REPOCOP_PKG_ROOT — директория, в которую распаковано содержимое пакета. (для пакетов с исходниками по умолчанию распаковывается только spec-файл. содержимомое src.rpm — нужно ли это будет кому-то?) Дополнительно в переменной REPOCOP_PKG_SPECFILE передается полный путь к спек-файлу. также доступны REPOCOP_PKG_NAME REPOCOP_PKG_VERSION REPOCOP_PKG_RELEASE REPOCOP_PKG_EPOCH и т. д., полностью аналогично тестам бинарных пакетов.
пример простейшего теста.
if OUTPUT=`rpmquery -p --requires $REPOCOP_PKG | egrep '(xorg-x11-devel|XFree86-devel)'`; then exec repocop-test-warn "Please, refresh your BuildRequires: using buildreq." \ " The following obsolete dependencies blow up the build:" $OUTPUT else exec repocop-test-skip fi
Исходный код
Можно получить в Sisyphus и в git.