yandex / mapkit-ios-demo

MapKit iOS demo
Other
82 stars 25 forks source link

Запуск тестов на simulator c ios 15 #133

Closed Dezabro closed 1 year ago

Dezabro commented 2 years ago

Привет.

Возникла проблема с запуском тестов из development pods, содержащих dependency на YandexMapsMobile', '4.0.0-full'. Тесты просто не запускаются, висит бесконечно Testing, потом падает с выдачей spindump.

Screenshot 2021-11-01 at 11 53 31

Если убрать dependency или запустить на simulator ios 14 - то все ок.

Кажется, проблема точно такая же, как описана у Texture: https://github.com/TextureGroup/Texture/issues/2029 и на форуме apple - https://developer.apple.com/forums/thread/689592?answerId=688696022#688696022

Демо проект (добавил в ваш демо проект dev pod с dependecy на YandexMapsMobile) mapkit-ios-demodeadlock.zip (запуск TestFeatureTests на ios 15 симулятор)

Spindump: Bootstrap Hang_0_B6235CD3-8596-4D65-A094-F80F3168A10C.spindump.zip

Пробовал xcode 13 и xcode 13.1 - результат одинаковый

artyom-razinov commented 2 years ago

Такой бектрейс в мейнтреде?

  * frame #0: 0x00007fff6bf999ee libsystem_kernel.dylib`__ulock_wait + 10
    frame #1: 0x00007fff2011226a libdispatch.dylib`_dlock_wait + 45
    frame #2: 0x00007fff201121e8 libdispatch.dylib`_dispatch_once_wait + 80
    frame #3: 0x00007fff24ba3f88 UIKitCore`-[_UIApplicationConfigurationLoader _loadInitializationContext] + 103
    frame #4: 0x00007fff24ba4241 UIKitCore`-[_UIApplicationConfigurationLoader applicationInitializationContext] + 24
    frame #5: 0x00007fff24b8bee6 UIKitCore`-[_UIScreenInitialDisplayConfigurationLoader initialDisplayContext] + 176
    frame #6: 0x00007fff24b8c172 UIKitCore`+[UIScreen initialize] + 109
    frame #7: 0x00007fff20184f93 libobjc.A.dylib`CALLING_SOME_+initialize_METHOD + 17
    frame #8: 0x00007fff20185e88 libobjc.A.dylib`initializeNonMetaClass + 700
    frame #9: 0x00007fff20186f0a libobjc.A.dylib`initializeAndMaybeRelock(objc_class*, objc_object*, mutex_tt<false>&, bool) + 173
    frame #10: 0x00007fff20192ec7 libobjc.A.dylib`lookUpImpOrForward + 634
    frame #11: 0x00007fff20180e5b libobjc.A.dylib`_objc_msgSend_uncached + 75
    frame #12: 0x000000011b1543da AvitoFoundation`_GLOBAL__sub_I_text_image.mm + 42
    frame #13: 0x00000001096b6899 dyld_sim`invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const + 182
    frame #14: 0x00000001096d2941 dyld_sim`invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const + 129
    frame #15: 0x00000001096cbe09 dyld_sim`invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 564
    frame #16: 0x00000001096caf5f dyld_sim`dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const + 129
    frame #17: 0x00000001096cbb93 dyld_sim`dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 179
    frame #18: 0x00000001096d23a2 dyld_sim`dyld3::MachOAnalyzer::forEachInitializerPointerSection(Diagnostics&, void (unsigned int, unsigned int, unsigned char const*, bool&) block_pointer) const + 118
    frame #19: 0x00000001096d25e4 dyld_sim`dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const + 386
    frame #20: 0x00000001096b67cc dyld_sim`dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const + 144
    frame #21: 0x00000001096b6958 dyld_sim`dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array<dyld4::Loader const*>&) const + 178
    frame #22: 0x00000001096b693b dyld_sim`dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array<dyld4::Loader const*>&) const + 149
    frame #23: 0x00000001096b693b dyld_sim`dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array<dyld4::Loader const*>&) const + 149
    frame #24: 0x00000001096b69f6 dyld_sim`dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const + 102
    frame #25: 0x00000001096c1e7b dyld_sim`dyld4::APIs::dlopen_from(char const*, int, void*) + 563
    frame #26: 0x00007fff2033481a CoreFoundation`_CFBundleDlfcnLoadBundle + 149
    frame #27: 0x00007fff2030553b CoreFoundation`_CFBundleLoadExecutableAndReturnError + 256
    frame #28: 0x00007fff2070f509 Foundation`-[NSBundle loadAndReturnError:] + 448
    frame #29: 0x000000010986152f libXCTestBundleInject.dylib`__XCTestBundleInject + 727
    frame #30: 0x00000001096b6899 dyld_sim`invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const + 182
    frame #31: 0x00000001096d2941 dyld_sim`invocation function for block in dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const + 129
    frame #32: 0x00000001096cbe09 dyld_sim`invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 564
    frame #33: 0x00000001096caf5f dyld_sim`dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const + 129
    frame #34: 0x00000001096cbb93 dyld_sim`dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 179
    frame #35: 0x00000001096d23a2 dyld_sim`dyld3::MachOAnalyzer::forEachInitializerPointerSection(Diagnostics&, void (unsigned int, unsigned int, unsigned char const*, bool&) block_pointer) const + 118
    frame #36: 0x00000001096d25e4 dyld_sim`dyld3::MachOAnalyzer::forEachInitializer(Diagnostics&, dyld3::MachOAnalyzer::VMAddrConverter const&, void (unsigned int) block_pointer, void const*) const + 386
    frame #37: 0x00000001096b67cc dyld_sim`dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const + 144
    frame #38: 0x00000001096b6958 dyld_sim`dyld4::Loader::runInitializersBottomUp(dyld4::RuntimeState&, dyld3::Array<dyld4::Loader const*>&) const + 178
    frame #39: 0x00000001096b69f6 dyld_sim`dyld4::Loader::runInitializersBottomUpPlusUpwardLinks(dyld4::RuntimeState&) const + 102
    frame #40: 0x00000001096c52d8 dyld_sim`dyld4::APIs::runAllInitializersForMain() + 222
    frame #41: 0x00000001096a9920 dyld_sim`dyld4::prepare(dyld4::APIs&, dyld3::MachOAnalyzer const*) + 2306
    frame #42: 0x00000001096a9d3f dyld_sim`_dyld_sim_prepare + 379
    frame #43: 0x000000010d673c27 dyld`dyld::useSimulatorDyld(int, macho_header const*, char const*, int, char const**, char const**, char const**, unsigned long*, unsigned long*) + 2093
    frame #44: 0x000000010d67115e dyld`dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 1191
    frame #45: 0x000000010d66b224 dyld`dyldbootstrap::start(dyld3::MachOLoaded const*, int, char const**, dyld3::MachOLoaded const*, unsigned long*) + 450
    frame #46: 0x000000010d66b025 dyld`_dyld_start + 37
artyom-razinov commented 2 years ago

Выпилил YandexMapKit, тесты заработали.

artyom-razinov commented 2 years ago

@Dezabro это похоже на баг в iOS 15, создали задачку эпплам, будем ждать фикса.

Любой вызов к UIKit в +(void)load в произвольном фреймворке приводит к дедлоку.

Ясное дело, конечно, что load и initialize - это антипаттерн и стыдобища (если это не для обхода багов эппла, конечно), но этот дедлок всё-таки больше баг эппла.

artyom-razinov commented 2 years ago

Костыль - в настройках схемы добавить DYLD_INSERT_LIBRARIES.

В нём прописать путь до бинаря фреймворка, в котором происходит вызов в +(void)load к другому фреймворку (например, к UIKit).

В нашем случае (мы мержим яндекс карты и прочие фреймворки в единый фреймворк для оптимизации быстродействия):

$(BUILT_PRODUCTS_DIR)/Avito.app/Frameworks/AvitoFoundation.framework/AvitoFoundation

Это решает проблему дедлока и тесты на iOS 15 запускаются.

beefon commented 2 years ago

Эпл ответили что теперь так и будет. Думаю, @yandex должен пофиксить.

Rabbit13245 commented 2 years ago

Подскажите, а будет какое-то решение запуска тестов без костылей?

navartis commented 2 years ago

Мы пофиксили у себя зависание тестов.

В нашем случае в приложении TheApp есть локальная зависимость InternalProjectDependency, которая зависит от YandexMaps

Мы прописали в настройки билдсхемы тестов Environment Variable DYLD_INSERT_LIBRARIES значение $(BUILT_PRODUCTS_DIR)/TheApp.app/Frameworks/InternalProjectDependency.framework/InternalProjectDependency

И тесты перестали зависать на 15x симуляторах.

Если у вас более сложная ситуация с зависимостями, то DYLD_INSERT_LIBRARIES поддерживает список. man dyld в помощь - там много полезных переменных для отладки компиляции проекта.

А можно просто перевести тесты на TestPlans и хак с зависанием тестов вам не потребуется;)

@artyom-razinov Спасибо за наводку!