Простой Emscripten автотест для ChromeDriver

В данной заметке я опишу реализацию запуска автотеста для ChromeDriver браузера Chrome, который запускает транслированный из C++ автотест модуля с помощью Emscripten, считывает вывод консоли и возвращает результат проверки.
Для начала нужно установить selenium, для питона3-убунту это делается так:


pip3 install selenium

Далее скачиваем ChromeDriver с официального сайта, кладем chromedriver например в /usr/local/bin, после этого можно приступать к реализации автотеста.
Ниже я приведу код автотеста, который запускает браузер Chrome с открытой страницей автотеста на Emscripten, проверяет наличие текста “Window test succeded”:


import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

capabilities = DesiredCapabilities.CHROME
capabilities['goog:loggingPrefs'] = { 'browser':'ALL' }
driver = webdriver.Chrome()
driver.get("http://localhost/windowInitializeTest/indexFullscreen.html")

time.sleep(2)

exitCode = 1

for entry in driver.get_log('browser'):
    if entry["source"] == "console-api":
        message = entry["message"]
        if "Window test succeded" in message:
            print("Test succeded")
            exitCode = 0

driver.close()
exit(exitCode)

Сохраняем тест как main.py и запускаем python3 main.py

Сборка проекта с зависимостями для Emscripten

В этой заметке я опишу сборку проекта состоящего из нескольких библиотек с помощью Emscripten.
На данный момент Emscripten не поддерживает сборку shared библиотек, поэтому первым делом переводим все библиотеки из Shared в Static. Emscripten работает со своими include файлами, поэтому нужно решить вопрос с видимостью заголовочных файлов, я решил это с помощью проброса симлинка из системной директории в тулчейн Emscripten:


ln -s /usr/local/include/FlameSteelFramework $EMSDK/fastcomp/emscripten/system/include/FlameSteelFramework

Если вы используете CMake, то нужно поменять SHARED->STATIC в CMakeLists.txt файле метода add_library. Собрать библиотеку/приложение для дальнейшей статической линковки можно с помощью команд:


emcmake cmake .
emmake make

Далее нужно будет собрать основное приложение с указанием *.a файлов библиотек на этапе линковки. Относительный путь указать мне не удалось, сборка завершилась корректно только после указания полных путей в файле CMakeLists.txt:


elseif(EMSCRIPTEN)
target_link_libraries(${FSEGT_PROJECT_NAME} GL GLEW 
/home/demensdeum/Sources/cube-art-project-bootstrap/cube-art-project/sharedLib/libCubeArtProject.a 
/home/demensdeum/Sources/cube-art-project-bootstrap/FlameSteelFramework/FlameSteelEngineGameToolkitFSGL/libFlameSteelEngineGameToolkitFSGL.a 
/home/demensdeum/Sources/cube-art-project-bootstrap/FlameSteelFramework/FlameSteelEngineGameToolkit/libFlameSteelEngineGameToolkit.a 
/home/demensdeum/Sources/cube-art-project-bootstrap/FlameSteelFramework/FlameSteelCore/libFlameSteelCore.a 
/home/demensdeum/Sources/cube-art-project-bootstrap/FlameSteelFramework/FlameSteelBattleHorn/libFlameSteelBattleHorn.a 
/home/demensdeum/Sources/cube-art-project-bootstrap/FlameSteelFramework/FSGL/libFSGL.a 
/home/demensdeum/Sources/cube-art-project-bootstrap/FlameSteelFramework/FlameSteelCommonTraits/libFlameSteelCommonTraits.a)
else()

Источники

https://emscripten.org/docs/compiling/Building-Projects.html#using-libraries

Потерянные исключения Emscripten и проблемы regex

Потерянные exception

Интересная особенность Emscripten, при запуске игрового цикла через emscripten_set_main_loop, следует помнить о том что хэндлинг исключений должен быть заново добавлен через try catch прямо в методе цикла, т.к. рантайм теряет блок try catch извне.
Проще всего выводить текст ошибки силами браузера, используя javascript alert:


            catch (const std::exception &exc)
            {
                const char *errorText = exc.what();
                cout << "Exception: " << errorText << "; Stop execution" << endl;

                EM_ASM_(
                {
                    var errorText = UTF8ToString($0);
                    alert(errorText);

                }, errorText);

                abort();

Слишком сложный regexp

Релизация regex в std может кинуть исключение error_complexity, если посчитает регулярное выражение слишком сложным. Такое происходит в текущей реализации emscripten, так что предлагаю вам реализовать тесты для парсинга через регулярки, либо использовать сторонние реализации regex.