From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on sa.local.altlinux.org X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU autolearn=ham autolearn_force=no version=3.4.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dumalogiya.ru; s=mail; t=1522582695; bh=dnU2biW9YuW+aQanc6iQh87ixhL9ASolSnT4/fSW1UU=; h=To:From:Subject:Message-ID:Date; b=kqrY2SXIsqZWkE9VSNft8Sdc93k8ppyEp74sA4Vz5/4+KTtVT4C1xIU42itR4eEpx KPA0jEBQRAUy8MwDgSzP+TBY3WaTZ8AjqQx5Hl2eMfKnkkWgH3g7fVL8zeKR651Fw8 LK7CeWkRCka3UK5vyi41bcYwlzRNFCJJyWBC6SWM= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dumalogiya.ru; s=mail; t=1522582688; bh=dnU2biW9YuW+aQanc6iQh87ixhL9ASolSnT4/fSW1UU=; h=To:From:Subject:Message-ID:Date; b=UO6HMAtLfTCm5FPbMPVf9h93ifPDwU65dLAMg1i5mhxzX9GAG4RJTRPNxrN4ITEUe B/BrdS4moNjR9NLsvFFImQ6OLc2aAdmRR9Md1rjOHnjjQt+l6kuOizy9Kd2+Q5QzFh 593t8EcNvGFSb80uMxyMUKxPHQQFo0bGVSEcBsfk= Authentication-Results: smtp2p.mail.yandex.net; dkim=pass header.i=@dumalogiya.ru To: sisyphus@lists.altlinux.org From: =?UTF-8?B?0JzQuNGF0LDQuNC7INCd0L7QstC+0YHQtdC70L7Qsiwg0JTRg9C80LDQu9C+?= =?UTF-8?B?0LPQuNGP?= Message-ID: <95d4115a-f374-c6bf-2388-690fdde263c9@dumalogiya.ru> Date: Sun, 1 Apr 2018 14:38:08 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: ru-RU Subject: [sisyphus] =?utf-8?b?0JDQstGC0L7QvNCw0YLQuNC30LDRhtC40Y8g0YLQtdGB?= =?utf-8?b?0YLQuNGA0L7QstCw0L3QuNC1INGA0LDQsdC+0YLQvtGB0L/QvtGB0L7QsdC9?= =?utf-8?b?0L7RgdGC0Lgg0LPRgNCw0YTQuNGH0LXRgdC60LjRhSDQv9GA0L7Qs9GA0LA=?= =?utf-8?b?0LzQvCDQsiDRgNC10L/QvtC30LjRgtC+0YDQuNC4?= X-BeenThere: sisyphus@lists.altlinux.org X-Mailman-Version: 2.1.12 Precedence: list Reply-To: ALT Linux Sisyphus discussions List-Id: ALT Linux Sisyphus discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 01 Apr 2018 11:38:22 -0000 Archived-At: List-Archive: List-Post: Добрый день. Недавно Chromium 65 перестал запускаться на x86_32 (i586) (https://bugzilla.altlinux.org/show_bug.cgi?id=34722), в связи с этим подумал, что есть способ автоматически тестировать минимальную работоспособность почти каждого графического приложения после сборки перед отправкой в репозиторий с низкими накладными расходами на тестирование. Недавно для себя сделал скрипт, автоматизирующий контроль доступности вебинарной системы на базе BigBlueButton. Суть скрипта в том, что он через Xvfb или Xephyr запускает браузер в отдельном X-сервере с жестко заданным разрешением экрана, открывает в браузере нужный сайт, далее с помощью xdotool путем нажатий и ввода текста в нужные места открытой веб-страницы с заранее известными координатами заполняет форму входа на вебинарную площадку, ждет, пока прогрузится и делает скриншот в формате png (scrot --quality 100 filename.png). Далее этот скриншот обрезается по заданным координатам, с помощью утилиты compare из imagemagick сравнивается с заранее сделанным скриншотом, высчитывается количество несвопадающих пикселей. Если оно меньше эмпирически подобранного числа, то система считается работающей, иначе принимаются нужные действия. Сравнение скриншотов можно заменить на выделение нужного участка текста на веб-странице путем тройного клика левой мышью (xdotool X Y click 1 click 1 click 1) и сравнения текста в промежуточном буфере (xclip -o) с заранее известным текстом. В случае репозитория можно проверять: - код возврата запуска программы (echo $?) - ps aux | grep $(which chromium) или pgrep после запуска программы и некоторой паузы, чтобы проверить, работает ли она на самом деле - сравнивать скриншот мейнтейнера пакета и/или этой системы автотеста со скриншотом того, что запустилось. Скриншоты обрезать так, чтобы в них не было заголовков окна (хотя их нет при рабоет в Xfvb/Xephyr), скролл-баров и прочих элементов, внешний вид которых трудно проконтролировать, выделять нужно какую-то небольшую область, по которой можно определить, что программа работает, в случае с Chromium этим может быть содержимое стартовой страницы chrome://welcome. Если тесты не проходятся, то не отправлять пакет в репозиторий. Ниже код моего несложного скрипта почти без изменений, только заменил реальные числовые координаты на X1, Y2 и т.д., убрал вводимые пароли и вызываемую ссылку для оповещения. Обратите внимание, что если к серверу вообще не подключен монитор и/или не запущено DE, то Xvfb запускается не с заданным разрешением, а меньшим, думаю, это можно побороть, но у меня это работает на сервере с DE и подключенным физическим монитором, пока не разбирался. Если скрипт запустить с параметром xephyr (./bbb-autotest.sh xephyr), то откроется окно, в котором откроется тестируемая программа, при этом его можно свернуть, т.к. работает полностью автономно. Режим xephyr для запуска при разработке скрипта, Xfvb — на сервере, там вообще никакое окно не открывается. #!/bin/bash ################################################################################################################### # Dependencies: bash wget scrot imagemagick xephyr Xvfb xrandr xdotool firefox # Example crontab line: # */15 * * * * /bin/bash -c "export DISPLAY=:0; cd /home/username/bbb-autotest; ./bbb-autotest.sh" # Нужно создать директрию /var/log/bbb-autotest и сделать нашего пользователяее владельцем для прав на запись ################################################################################################################### # запомним директорию, откуда начинаем работать dir0="$(pwd)" # перед запуском сбросим значение переменной DISPLAY на стандартное (полезно при ручной отладке скрипта) export DISPLAY=:0 # будем запускать браузер с английской локалью, чтобы текст был гарантированно предсказуемым export LANG=c log_dir="/var/log/bbb-autotest" log_file="${log_dir}/bbb-autotest.log" # -w — это проверка, есть ли права на запись в указанный файл if [ -w "$log_dir" ]     then         # создать файл-лог, если он не существует         test -f "$log_file" || touch "$log_file"         # если есть права на запись в папку, то установить значение переменной         LOG_DIR_ENABLED=1     else         echo "Директория $log_dir недоступна для записи!" fi if [ -w "$log_file" ] then     echo "Пишем в лог $log_file" else     log_file_unavailable="$log_file"     log_file="/tmp/bbb-autotest.log"     echo "Основной лог (${log_file_unavailable}) недоступен для записи, пишем в $log_file"     # sleep, чтобы при запуске скрипта обратить внимание на это сообщение об ошибке     sleep 15 fi # проверим, есть ли необходимый нам для работы скриншот-образец if [ -f "${dir0}/screenshot_sample_cropped.png" ] then     echo "Скриншот-образец найден" else     echo "Скриншот-образец не найден! Завершаем работу."     exit 1 fi # номер бота; пока не знаю, зачем, может быть, пригодится bot_number="001" tmp_dir="/tmp/bbb-autotest" mkdir -p ${tmp_dir} rm -fvr ${tmp_dir}/* virt_display="$(( ( RANDOM % 100 )  + 1 ))" echo "Random DISPLAY = $virt_display" # Запустим отдельный икс-сервер, в котором без оконных менеджеров и прочих прибабмбасов будем запускать то, что нам нужно # Использование отдельного X-сервера с заранее известным размером окна позволит нам спокойно использовать единый набор координат для xdotool (в какие точки внутри этого окна нажимать), которые не будут зависеть от размера экрана и иных параметров системы, где запускается этот скрипт if [[ $@ == *xephyr* ]] # если в качестве аргумента скрипту передано "xephyr", то запускаем графическое окно с отдельным икс-сервером; это для разработки скрипта # иначе запускает фреймбуффер Xvfb, где не открывается никакое графическое окно; это для запуска на настоящем сервере     then         echo "Работаем в режиме Xephyr"         Xephyr -br -ac -noreset -screen 1024x720 ":${virt_display}" &     else         echo "Работаем в режиме Xvfb"         Xvfb ":${virt_display}" -screen 0 1024x720x24 & fi # PID запускаемых процессов записываем в файл, а не в переменную, чтобы можно было их все завершить даже после завершения этого скрипта, считав хранящиеся на диске значения echo $! >${tmp_dir}/X-server.pid # export DISPLAY делать ПОСЛЕ запуска Xephyr, иначе сам Xephyr пытается запуститсья на еще не существующем DISPLAY export DISPLAY=":${virt_display}" # теперь запустим Firefox; т.к. переменная окружения DISPLAY уже ранее была экспортирована, Firefox запустится именно в нашем виртуальном икс-сервере firefox --private-window "http://URL0" & echo $! >${tmp_dir}/firefox.pid sleep 20 # ждем, пока Firefox полностью запустится # чтобы получить текущее расположение мыши в Xephyr: sleep 5; xdotool getmouselocation --shell; за эти 5 сек перевести мышь в нужное место, в терминале с нужной переменной DISPLAY будут напечатаны координаты курсора мыши # вводим логин в форму входа xdotool mousemove X1 Y1 click 1 # теперь сотрем все, что ранее было написано в этом поле (на всякий случай) xdotool key Control+a xdotool key BackSpace xdotool type bbb-autotest-bot${bot_number} # теперь вводим пароль xdotool mousemove X2 Y2 click 1 xdotool type password # нажимаем на кнопку "Войти на вебинар" xdotool mousemove X3 Y3 click 1 # ждем, пока загрузится площадка на флеш-плеере sleep 50 # делаем скриншот вирутального экрана и вырезаем из него область с вопросом "Только слушать или микрофон?" scrot --quality 100 ${tmp_dir}/current_screenshot_full.png # уменьшаем кол-во цветом до двух, чтобы уменьшить влияние различий в рендеринге шрифтов convert -crop X4xY4+P1+P2 +dither -colors 2 "${tmp_dir}/current_screenshot_full.png" "${tmp_dir}/current_screenshot_cropped.png" # точно так же уменьшим кол-во цветом в скриншоте-образце convert +dither -colors 2 "${dir0}/screenshot_sample_cropped.png" "${tmp_dir}/screenshot_sample_cropped_colors2.png" ### вообще такой метод не очень, т.к. "convert +dither -colors 2" уменьшает кол-во цветом до двух исходя из расчитанного среднего цвета, а что, если из-за особенностей рендеринга шрифта средние цвета окажется разными, пусть и самую малость? Тогда можно не заниматься уменьшением кол-ва цветов, но пока забью на это. # теперь сравниваем 2 картинки, сколько пикселей различается (https://stackoverflow.com/questions/29229535/measure-similarity-of-two-images-in-java-or-imagemagick) screenshots_diff_value="$(compare -metric ae "${tmp_dir}/screenshot_sample_cropped_colors2.png" "${tmp_dir}/current_screenshot_cropped.png" null: 2>&1)" # 2>&1 обязательно, иначе выводимое значение не попадает в значение переменной echo screenshots_diff_value = "$screenshots_diff_value" # сохраним текущее время в переменную, чтобы в логе и названии файла-архива с запакованными скриншотами/логами была одна и та же дата date0="$(date +%d.%m.%Y_%H.%M.%S)" # если кол-во несовпадающих пикселей меньше 8000, то считаем проверку на работу площадки успешно пройденной; 8000 наполовину от балды, наполовину подобрано экспериментально # -le: less or equal, <= if [ "${screenshots_diff_value}" -le 8000 ]     then         echo "Площадка работает!"         echo "pass;;${screenshots_diff_value};;${date0}" >>"${log_file}"     else         echo "Площадка НЕ работает!"         echo "fail;;${screenshots_diff_value};;${date0}" >>"${log_file}"         # оповещаем         wget -qO- "URL" >/dev/null         if [ "$LOG_DIR_ENABLED" -eq 1 ]         # если существует папка для логов и у нас есть права на запись в нее, то в случае неудачной проверки заархивируем временную папку в нее, чтобы потом посмотреть на скриншоты для выяснения причин ошибки             then                 tar cfJ "${log_dir}/fail_${date0}.tar.xz" "${tmp_dir}" #>/dev/null         fi fi # убъем все запущенные в ходе проверки процессы; убиваем в конце, а не в начале, чтобы в начале случайно не убить вообще другой процесс, у которого совпадет PID for i in ${tmp_dir}/*.pid; do kill $(cat $i); done ################################################################################################################### В случае тестирования репозитория перед каждым запуском браузера делать пустую директорию значением $HOME, чтобы все программы запускались на заранее известной и, очень желательно, почти не изменяемой от релиза к релизу теме GTK/Qt. Значение разницы скриншотов в пикселях подобрать такое, чтобы нерадикальные изменения в интерфейсе программы укладывались в него, но, если программа не запустилась, запустилась с черным или белым экраном или выпало маленькое сообщение об ошибке вместо нее, чтобы срабатывало оповещение об ошибке. Что касается иных способов контроля, кроме уже описанных скриншотов и выделения текста. Я пробовал распознавать скриншоты Tesseract'ом, накладные расходы по времени и ресурсам небольшие, но, если распознавать стандартный скриншот с DPI 96 или включенным субпиксельным рендерингом шрифтов, то Tesseract может одно и то же распознавать по-разному раз от разу, например, цифру 6 то как 6, то как 5, точку как точку или как запятую. Поэтому скриншоты нужно увеличить примерно до DPI 300 или больше, как стандартный сканированный текст, и убрать цветные пиксели субпиксельного рендеринга путем уменьшения количества цветов скриншота. Пример: convert -crop ${crop_real_width}x${crop_real_height}+${crop_real_x}+${crop_real_y} +dither -colors 2 -resize 400% -depth 500 /tmp/checkresult.png /tmp/checkresult2.png Для стабильности работы такой системы в случае сравнения скриншотов нужно стандартизировать тему GTK (стандартная, которая серая, а не Adwaita, хорошо подойдет) и настройки рендеринга шрифтов, можно создать отдельный пакет с нужными настройками в /etc/skel. Как видите, накладные расходы низкие потому, что не нужно создавать и разворачивать контейнеры и виртуальные машины, достаточно создавать чистую или стандартизированную папку под $HOME. На тестированием одной программы с графическим интерфейсом будет уходить в среднем меньше минуты. Можно добавить, например, exit 0 в случае успешного тетсирования, exit 2 при такой-то ошибке и т.д. и эти кода возврата обрабатывать тем, что отвечает за репозиторий и запускает тестирование. -- ------ С уважением, Михаил Новоселов, https://nixtux.ru/ | mikhailnov@dumalogiya.ru | Telegram: mikhailnov@