среда, 13 декабря 2017 г.

Используем bisect для поиска регрессий в коде LibreOffice

Регрессия в программном коде - это, когда после внесения изменений в программу, перестаёт работать то, что должно было продолжать работать. Например, разработчик написал код, добавляющий новую фичу (или исправляющий ошибку) в одном месте программы, а в другом месте программы из-за этого возникла другая ошибка, например стал неправильно отображаться формат ячейки или некорректно стало считаться некое вычисляемое значение, да и вообще всё, что угодно.
Когда обнаруживается такая регрессия (в 7.0. работало, в 7.1 перестало работать или работает с ошибками), то для облегчения жизни кодерам (и для сокращения затрат их времени) люди из QA команды делают bisecting.
Bisect - это инструмент из Git, который используется для определения момента, когда ошибка впервые появилась в LibreOffice. То есть мы будем искать первый коммит, который привел к появлению некой ошибки.
В вики проекта есть страничка с описанием процесса для ОС Windows (на английском языке), а также для Linux и для macOS.
Итак, начнем:
Шаг № 1. Скачиваем Git for Windows и устанавливаем его.
Шаг №2. Для корректной работы LibreOffice в Windows необходимы библиотеки типа msvcrXXX.dll от Visual C++ Redistributable Packages for Visual Studio соответствующих версий. Скачать их можно с сайта MicroSoft. Если вы ищете ошибку в той версии офиса, которая уже установлена и работает, то скорее всего нужные библиотеки от MS уже установлены. Если решили проверить альфу или бету версию офиса, то нужно уточнить у разработчиков, какие библиотеки нужны и нужны ли вообще.
Шаг №3. Нужно скачать репозиторий бинарников для той версии офиса, в которой вы собираетесь искать регрессию. Создаем каталог, где будут храниться репы, например E:\libo. Запускаем наш Git for Windows, откроется окно терминала:

нужно перейти в наш рабочий каталог, выполнив команду cd /e/libo, приглашение командной строки изменится на соответствующий путь.
Далее выполняем команду git clone https://bibisect.libreoffice.org/win64-7.1.git (последние две цифры 7.1 означают номер версии LibreOffice, которую мы будем исследовать, если вы работаете с иной версией LibreOffice измените последние две цифры на нужную версию).
Ждем достаточно долгое время, пока сформируется архив на сервере, пока он выкачается к Вам на компьютер, а затем распакуется. В терминале все эти шаги будут отражаться.
Есть и альтернативный способ получения репозитория: переходим по ссылке типа https://bibisect.libreoffice.org/win64-7.1, где win64 - это операционная система и разрядность, а 7.1 - это версия LibreOffice. Там на страничке есть фраза "Download the 5.81Gb bundl...". со ссылкой, щёлкаете по этой ссылке, скачиваете этот самый bundle в (нашем примере) каталог E:/libo и даете в терминале команду git clone -o bundle win64-7.1.git-bundle win64-7.1. Естественно вы должны в этот момент находится в каталоге, куда скачали bundle. По сути это архив, а команда выше распаковывает его в подкаталог win64-7.1.
Внимание! Сборки в bisect repo не содержат русского языка для интерфейса пользователя! А иногда бывает, что проблема проявляется с русским UI и не проявляется с английским UI.
Чтобы добавить русский интерфейс в сборку LibreOffice из bisect repo, необходимо скопировать некоторые каталоги и отдельные файлы из установленного стандартного LibreOffice в те же места в bisect экземпляр:
\LibreOffice\program\resource\ru - копировать весь каталог
\LibreOffice\share\registry\res\registry_ru.xcd
\LibreOffice\share\registry\res\fcfg_langpack_ru.xcd
\LibreOffice\share\registry\Langpack-ru.xcd
Шаг №4. Начинаем собственно процесс поиска плохого коммита. Переходим в каталог с репой бисектинга для нужной версии, даем команду cd win64-7.1.
Приглашение командной строки соответственно изменится на /e/libo/win64-7.1.
Теоретически, нужно проделать 12 итераций (но по факту их может быть и на один или два больше!) - запусков сборок LibreOffice из репы-bisect, для каждой из которых нужно проверить наличие или отсутствие ошибки. Git сам в итоге выведет итоговый коммит, который приводит к сбою.
Сначала нужно убедиться, что мы используем нужную репу для поиска нашей регрессии. Мы проверим, что в последнем билде в данной ветке наша ошибка уже присутствует, а в первой еще нет. Для этого введите команду git checkout master, оно чуть подумает и выведет некий результат:
Если вывод в терминале будет раскрашен в красный цвет или будет пестрить фразами типа error, значит что-то пошло не так и нужно разбираться и просить помощи (как это делал я, когда мучался в начале процесса).
Следующая команда instdir/program/soffice (в macOS выполните команду open LibreOffice.app/) запустит последнюю сборку (или билд - от английского build) LibreOffice в данной версии bisect-репозитория. Теперь в этом запущенном экземпляре LibreOffice вы делаете те действия, которые приводят к Вашей ошибке. Это нужно, чтобы убедиться, что ошибка УЖЕ есть в данном билде.
ВНИМАНИЕ! Часто бывает, что команда instdir/program/soffice не запускает LibreOffice и ничего не выводит в консоль. Дайте эту команду повторно. И только если и после второй попытки запуска LibreOffice не запустился, то можно говорить о том, что есть проблема либо с репозиторием, либо с git, либо что-то ещё.
ПРИМЕЧАНИЕ: если в последнем билде Вашей ошибки нет, это значит, что вы ищете регрессию не в той версии!
ПРИМЕЧАНИЕ: Вы должны искать только Вашу ошибку, на иные ошибки не обращайте внимание, за один цикл итераций (см.ниже) вы находите одну конкретную регрессию, которая привела именно к Вашей ошибке.
Убедились, что ошибка есть? Хорошо. Следующая команда будет git checkout oldest. И следом за ней сразу instdir/program/soffice. Эта последовательность запустит самый первый билд в версии. Выполните снова действия, которые приводят к Вашей ошибке. Убедитесь, что ошибки ЕЩЁ НЕТ! Если это так (в последнем билде есть ошибка, а в первом нет), то регрессия была внесена где-то между этими билдами. И мы начинаем самое главное.
Даем команду git bisect start master oldest.
И начинаем выполнять следующие действия раз за разом:
1. Вводим команду instdir/program/soffice - запускаем LibreOffice, проверяем на наличие ошибки, просто закрываем LibreOffice (либо, если ошибка критическая, то он сам закроется), и
2. - если ошибка есть, даем команду git bisect bad
    - если ошибки нет, даем команду git bisect good
3. Возвращаемся к пункту 1.
ВНИМАНИЕ! Обратите внимание на то, что ошибка обязательно должна проявиться при выполнении этих итераций хотя бы пару раз. Если у вас все время ответ будет good, это значит, что что-то пошло не так и нужно разбираться со знающими людьми! 
ВНИМАНИЕ! Может случится так, что LibreOffice не будет стартовать вовсе или с какими-то ошибками, это может означать, что билд был неработоспособный. В таком случае необходимо дать команду git bisect skip, и вернуться к пункту 1.
По мере выполнения этих шагов git будет писать нечто вроде "Осталось 11 (10, 9......2, 1) шагов до конца". Может писать и "Осталось 0 шагов до конца, но при этом не покажет финальный результат (о нем чуть ниже), поэтому процесс нужно продолжать до тех пор, пока git не покажет примерно такой вывод в консоли:
sourse-sha: 531eaa9b92090606efdb8c04dfd6de591e93842b
Это sha хэш проблемного коммита для нашей регрессии. Это то, что мы должны показать в багзилле в качестве результата проведенной операции bibisecting'a.
Теперь нужно найти собственно коммит и автора коммита.
Открываем браузер и в адресной строке пишем gerrit.libreoffice.org и жмём энтер.
Справа вверху будет поле для поиска (со значком лупы), копируем и вставляем в это поле полученный хэш - 531eaa9b92090606efdb8c04dfd6de591e93842b и жмём энтер.
Сайт покажет коммит, в левой части которого будут строки Owner и Committer. Чаще всего, это один человек, но иногда бывает, что патч написал один человек, у нет прав на принятие патчей и тогда другой человек, опытный разработчик с правами, делает код ревью и вливает патч в исходники. Соответственно автора и коммиттера надо подписать в багзилле на баг, добавив их в поле СС.
В багзиллу проекта, помимо описания бага, Вы должны после bisecting'a написать нечто вроде: "I bisected this bug. First bad commit is 531eaa9b92090606efdb8c04dfd6de591e93842b." И в доказательство привести вывод из вашей консоли git с результатом bibisecting'a.
Также жедательно в баг репорте оставить ссылку на патч, который вы нашли в геррит. 
В конце в терминале дайте команду git bisect reset и затем git checkout master чтобы выйти из режима.

2 комментария:

  1. Спасибо Роману и всем, кто, прочитав это, сделает хотя бы один бибисект!

    > нужно перейти в наш рабочий каталог, выполнив команду cd /cygdrive/e/libo

    Сейчас в cygwin работает также указание путей без cygdrive в таком виде:

    cd e:/libo

    То есть достаточно взять Windows-путь, и все обратные слеши заменить на прямые.

    > Далее выполняем команду git clone git://gerrit.libreoffice.org/bibisect-win32-5.4

    Примечание: Адреса репозиториев для разных версий указаны на страничке, указанной вначале, а также можно посмотреть релевантные репозитории здесь: https://gerrit.libreoffice.org/#/admin/projects/?filter=bibisect

    ОтветитьУдалить
  2. После того, как виви... сорри, бибисекция окончена, её нужно закрыть. Для этого используется команда

    git bisect reset

    После её выполнения можно начать новую бибисекцию. Выполнение этой команды вернёт репозиторий в то состояние (к тому коммиту), которое было на момент выполнения git bisect start ... (вероятно, это самый первый коммит в репозитории (т.е. oldest), если всё выполнено согласно приведённой инструкции). Если нужно вернуться к определённому коммиту, например, самому последнему, нужно указать его так:

    git bisect reset master

    ОтветитьУдалить

Внимание! Сообщения проходят премодерацию!