ragger 1.41.1__tar.gz → 1.41.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. {ragger-1.41.1 → ragger-1.41.2}/CHANGELOG.md +6 -0
  2. {ragger-1.41.1/src/ragger.egg-info → ragger-1.41.2}/PKG-INFO +1 -1
  3. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/__version__.py +3 -3
  4. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/conftest/base_conftest.py +54 -19
  5. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/error.py +8 -0
  6. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/utils/misc.py +3 -3
  7. {ragger-1.41.1 → ragger-1.41.2/src/ragger.egg-info}/PKG-INFO +1 -1
  8. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/utils/test_misc.py +2 -2
  9. {ragger-1.41.1 → ragger-1.41.2}/.codeql-config.yaml +0 -0
  10. {ragger-1.41.1 → ragger-1.41.2}/.gitattributes +0 -0
  11. {ragger-1.41.1 → ragger-1.41.2}/.github/workflows/build_and_tests.yml +0 -0
  12. {ragger-1.41.1 → ragger-1.41.2}/.github/workflows/codeql-analysis.yml +0 -0
  13. {ragger-1.41.1 → ragger-1.41.2}/.github/workflows/documentation.yml +0 -0
  14. {ragger-1.41.1 → ragger-1.41.2}/.github/workflows/fast-checks.yml +0 -0
  15. {ragger-1.41.1 → ragger-1.41.2}/.github/workflows/force-rebase.yml +0 -0
  16. {ragger-1.41.1 → ragger-1.41.2}/.gitignore +0 -0
  17. {ragger-1.41.1 → ragger-1.41.2}/LICENSE +0 -0
  18. {ragger-1.41.1 → ragger-1.41.2}/MANIFEST.in +0 -0
  19. {ragger-1.41.1 → ragger-1.41.2}/README.md +0 -0
  20. {ragger-1.41.1 → ragger-1.41.2}/doc/Makefile +0 -0
  21. {ragger-1.41.1 → ragger-1.41.2}/doc/_static/layout.css +0 -0
  22. {ragger-1.41.1 → ragger-1.41.2}/doc/_templates/layout.html +0 -0
  23. {ragger-1.41.1 → ragger-1.41.2}/doc/architecture.rst +0 -0
  24. {ragger-1.41.1 → ragger-1.41.2}/doc/conf.py +0 -0
  25. {ragger-1.41.1 → ragger-1.41.2}/doc/faq.rst +0 -0
  26. {ragger-1.41.1 → ragger-1.41.2}/doc/glossary.rst +0 -0
  27. {ragger-1.41.1 → ragger-1.41.2}/doc/images/navigate.draw +0 -0
  28. {ragger-1.41.1 → ragger-1.41.2}/doc/images/navigate.svg +0 -0
  29. {ragger-1.41.1 → ragger-1.41.2}/doc/images/ragger.png +0 -0
  30. {ragger-1.41.1 → ragger-1.41.2}/doc/images/stax_infos.png +0 -0
  31. {ragger-1.41.1 → ragger-1.41.2}/doc/images/stax_welcome.png +0 -0
  32. {ragger-1.41.1 → ragger-1.41.2}/doc/images/usage.draw +0 -0
  33. {ragger-1.41.1 → ragger-1.41.2}/doc/images/usage.svg +0 -0
  34. {ragger-1.41.1 → ragger-1.41.2}/doc/index.rst +0 -0
  35. {ragger-1.41.1 → ragger-1.41.2}/doc/installation.rst +0 -0
  36. {ragger-1.41.1 → ragger-1.41.2}/doc/rationale.rst +0 -0
  37. {ragger-1.41.1 → ragger-1.41.2}/doc/source.rst +0 -0
  38. {ragger-1.41.1 → ragger-1.41.2}/doc/tutorial.rst +0 -0
  39. {ragger-1.41.1 → ragger-1.41.2}/doc/tutorial_conftest.rst +0 -0
  40. {ragger-1.41.1 → ragger-1.41.2}/doc/tutorial_installation.rst +0 -0
  41. {ragger-1.41.1 → ragger-1.41.2}/doc/tutorial_screen.rst +0 -0
  42. {ragger-1.41.1 → ragger-1.41.2}/ledger_app.toml +0 -0
  43. {ragger-1.41.1 → ragger-1.41.2}/pyproject.toml +0 -0
  44. {ragger-1.41.1 → ragger-1.41.2}/setup.cfg +0 -0
  45. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/__init__.py +0 -0
  46. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/backend/__init__.py +0 -0
  47. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/backend/interface.py +0 -0
  48. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/backend/ledgercomm.py +0 -0
  49. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/backend/ledgerwallet.py +0 -0
  50. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/backend/physical_backend.py +0 -0
  51. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/backend/speculos.py +0 -0
  52. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/backend/stub.py +0 -0
  53. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/bip/__init__.py +0 -0
  54. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/bip/path.py +0 -0
  55. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/bip/seed.py +0 -0
  56. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/conftest/__init__.py +0 -0
  57. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/conftest/configuration.py +0 -0
  58. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/firmware/__init__.py +0 -0
  59. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/firmware/structs.py +0 -0
  60. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/firmware/touch/__init__.py +0 -0
  61. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/firmware/touch/element.py +0 -0
  62. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/firmware/touch/layouts.py +0 -0
  63. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/firmware/touch/positions.py +0 -0
  64. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/firmware/touch/screen.py +0 -0
  65. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/firmware/touch/use_cases.py +0 -0
  66. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/__init__.py +0 -0
  67. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/nanos_body.png +0 -0
  68. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/nanos_leftbutton.png +0 -0
  69. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/nanos_rightbutton.png +0 -0
  70. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/nanosp_body.png +0 -0
  71. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/nanosp_leftbutton.png +0 -0
  72. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/nanosp_rightbutton.png +0 -0
  73. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/nanox_body.png +0 -0
  74. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/nanox_leftbutton.png +0 -0
  75. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/nanox_rightbutton.png +0 -0
  76. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/stax_body.png +0 -0
  77. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/swipe_left_action.png +0 -0
  78. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/swipe_right_action.png +0 -0
  79. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/assets/touch_action.png +0 -0
  80. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/interface.py +0 -0
  81. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/gui/process.py +0 -0
  82. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/logger.py +0 -0
  83. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/navigator/__init__.py +0 -0
  84. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/navigator/instruction.py +0 -0
  85. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/navigator/nano_navigator.py +0 -0
  86. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/navigator/navigation_scenario.py +0 -0
  87. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/navigator/navigator.py +0 -0
  88. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/navigator/touch_navigator.py +0 -0
  89. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/py.typed +0 -0
  90. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/utils/__init__.py +0 -0
  91. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/utils/packing.py +0 -0
  92. {ragger-1.41.1 → ragger-1.41.2}/src/ragger/utils/structs.py +0 -0
  93. {ragger-1.41.1 → ragger-1.41.2}/src/ragger.egg-info/SOURCES.txt +0 -0
  94. {ragger-1.41.1 → ragger-1.41.2}/src/ragger.egg-info/dependency_links.txt +0 -0
  95. {ragger-1.41.1 → ragger-1.41.2}/src/ragger.egg-info/requires.txt +0 -0
  96. {ragger-1.41.1 → ragger-1.41.2}/src/ragger.egg-info/top_level.txt +0 -0
  97. {ragger-1.41.1 → ragger-1.41.2}/template/.dispatch_to_your_test_folder +0 -0
  98. {ragger-1.41.1 → ragger-1.41.2}/template/conftest.py +0 -0
  99. {ragger-1.41.1 → ragger-1.41.2}/template/usage.md +0 -0
  100. {ragger-1.41.1 → ragger-1.41.2}/tests/__init__.py +0 -0
  101. {ragger-1.41.1 → ragger-1.41.2}/tests/functional/__init__.py +0 -0
  102. {ragger-1.41.1 → ragger-1.41.2}/tests/functional/backend/__init__.py +0 -0
  103. {ragger-1.41.1 → ragger-1.41.2}/tests/functional/backend/test_speculos.py +0 -0
  104. {ragger-1.41.1 → ragger-1.41.2}/tests/functional/conftest.py +0 -0
  105. {ragger-1.41.1 → ragger-1.41.2}/tests/functional/navigator/__init__.py +0 -0
  106. {ragger-1.41.1 → ragger-1.41.2}/tests/functional/navigator/test_navigator.py +0 -0
  107. {ragger-1.41.1 → ragger-1.41.2}/tests/functional/test_boilerplate.py +0 -0
  108. {ragger-1.41.1 → ragger-1.41.2}/tests/pytest.ini +0 -0
  109. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/apex_p/waiting_screen/00000.png +0 -0
  110. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/apex_p/waiting_screen/00001.png +0 -0
  111. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/apex_p/waiting_screen/00002.png +0 -0
  112. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/apex_p/waiting_screen/00003.png +0 -0
  113. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/apex_p/waiting_screen/00004.png +0 -0
  114. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/flex/waiting_screen/00000.png +0 -0
  115. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/flex/waiting_screen/00001.png +0 -0
  116. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/flex/waiting_screen/00002.png +0 -0
  117. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/flex/waiting_screen/00003.png +0 -0
  118. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/flex/waiting_screen/00004.png +0 -0
  119. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/generic/00000.png +0 -0
  120. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/generic/00001.png +0 -0
  121. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/generic/00002.png +0 -0
  122. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/generic/00003.png +0 -0
  123. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/generic/00004.png +0 -0
  124. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare/00000.png +0 -0
  125. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare/00001.png +0 -0
  126. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare/00002.png +0 -0
  127. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare/00003.png +0 -0
  128. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare/00004.png +0 -0
  129. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare/00005.png +0 -0
  130. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare/00006.png +0 -0
  131. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare/00007.png +0 -0
  132. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare_no_golden/00000.png +0 -0
  133. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare_wrong_golden/00000.png +0 -0
  134. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_and_compare_wrong_golden/00001.png +0 -0
  135. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_until_text_and_compare/00000.png +0 -0
  136. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_until_text_and_compare/00001.png +0 -0
  137. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_until_text_and_compare/00002.png +0 -0
  138. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/nanos/test_navigate_until_text_and_compare/00003.png +0 -0
  139. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/stax/waiting_screen/00000.png +0 -0
  140. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/stax/waiting_screen/00001.png +0 -0
  141. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/stax/waiting_screen/00002.png +0 -0
  142. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/stax/waiting_screen/00003.png +0 -0
  143. {ragger-1.41.1 → ragger-1.41.2}/tests/snapshots/stax/waiting_screen/00004.png +0 -0
  144. {ragger-1.41.1 → ragger-1.41.2}/tests/stubs.py +0 -0
  145. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/__init__.py +0 -0
  146. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/backend/__init__.py +0 -0
  147. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/backend/test_interface.py +0 -0
  148. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/backend/test_ledgercomm.py +0 -0
  149. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/backend/test_ledgerwallet.py +0 -0
  150. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/backend/test_physical_backend.py +0 -0
  151. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/backend/test_speculos.py +0 -0
  152. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/backend/test_stub.py +0 -0
  153. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/bip/test_path.py +0 -0
  154. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/bip/test_seed.py +0 -0
  155. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/conftests/__init__.py +0 -0
  156. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/conftests/test_base_conftest.py +0 -0
  157. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/firmware/test_structs_Firmware.py +0 -0
  158. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/firmware/touch/test_element.py +0 -0
  159. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/firmware/touch/test_screen_FullScreen.py +0 -0
  160. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/firmware/touch/test_screen_MetaScreen.py +0 -0
  161. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/helpers.py +0 -0
  162. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/navigator/__init__.py +0 -0
  163. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/navigator/test_nano_navigator.py +0 -0
  164. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/navigator/test_navigation_scenario.py +0 -0
  165. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/navigator/test_navigator.py +0 -0
  166. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/navigator/test_touch_navigator.py +0 -0
  167. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/test_error_ApplicationError.py +0 -0
  168. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/utils/__init__.py +0 -0
  169. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/utils/test_packing.py +0 -0
  170. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/utils/test_path.py +0 -0
  171. {ragger-1.41.1 → ragger-1.41.2}/tests/unit/utils/test_structs.py +0 -0
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.41.2] - 2026-01-08
9
+
10
+ ### Fixed
11
+
12
+ - Only fail the test where elf file is missing
13
+
8
14
  ## [1.41.1] - 2025-12-12
9
15
 
10
16
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ragger
3
- Version: 1.41.1
3
+ Version: 1.41.2
4
4
  Summary: Testing framework using Speculos and LedgerComm as backends
5
5
  Author-email: Ledger <hello@ledger.fr>
6
6
  Project-URL: Homepage, https://github.com/LedgerHQ/ragger
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.41.1'
32
- __version_tuple__ = version_tuple = (1, 41, 1)
31
+ __version__ = version = '1.41.2'
32
+ __version_tuple__ = version_tuple = (1, 41, 2)
33
33
 
34
- __commit_id__ = commit_id = 'g1f5eb0699'
34
+ __commit_id__ = commit_id = 'g9c99cb587'
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  import pytest
3
3
  import logging
4
+ import warnings
4
5
  from dataclasses import fields
5
6
  from ledgered.devices import Device, Devices
6
7
  from ledgered.manifest import Manifest
@@ -14,6 +15,7 @@ from ragger.logger import init_loggers, standalone_conf_logger
14
15
  from ragger.navigator import Navigator, NanoNavigator, TouchNavigator, NavigateWithScenario
15
16
  from ragger.utils import find_project_root_dir, find_library_application, find_application
16
17
  from ragger.utils.misc import get_current_app_name_and_version, exit_current_app, open_app_from_dashboard
18
+ from ragger.error import MissingElfError
17
19
 
18
20
  from . import configuration as conf
19
21
 
@@ -47,6 +49,10 @@ def pytest_addoption(parser):
47
49
  const="apdu.log",
48
50
  help="Log the APDU in a file. If no pattern provided, uses 'apdu_xxx.log'.")
49
51
  parser.addoption("--seed", action="store", default=None, help="Set a custom seed")
52
+ parser.addoption("--ignore-missing-binaries",
53
+ action="store_true",
54
+ default=False,
55
+ help="Skip tests instead of failing when application binaries are missing")
50
56
  # Always allow "default" even if application conftest does not define it
51
57
  allowed_setups = conf.OPTIONAL.ALLOWED_SETUPS
52
58
  if "default" not in allowed_setups:
@@ -102,6 +108,11 @@ def cli_user_seed(pytestconfig):
102
108
  return pytestconfig.getoption("seed")
103
109
 
104
110
 
111
+ @pytest.fixture(scope="session")
112
+ def ignore_missing_binaries(pytestconfig):
113
+ return pytestconfig.getoption("ignore_missing_binaries")
114
+
115
+
105
116
  @pytest.fixture(scope="session")
106
117
  def pki_prod(pytestconfig):
107
118
  return pytestconfig.getoption("pki_prod")
@@ -238,7 +249,8 @@ def prepare_speculos_args(root_pytest_dir: Path,
238
249
  pki_prod: bool,
239
250
  cli_user_seed: str,
240
251
  additional_args: List[str],
241
- verbose_speculos: bool = False):
252
+ verbose_speculos: bool = False,
253
+ ignore_missing_binaries: bool = False):
242
254
  speculos_args = additional_args.copy()
243
255
 
244
256
  if display:
@@ -270,16 +282,14 @@ def prepare_speculos_args(root_pytest_dir: Path,
270
282
  f"Expected a single folder in {manifest.app.build_directory}, found {len(app_dir_subdirectories)}"
271
283
  )
272
284
  main_app_path = find_application(app_dir_subdirectories[0], device_name, "c")
273
- # If the app is standalone, the main app should be located in project_root_dir / manifest.app.build_directory
274
- else:
275
- main_app_path = find_application(project_root_dir / manifest.app.build_directory,
276
- device_name, manifest.app.sdk)
277
285
 
278
- # If this repository does not hold the main app, then we need to load this repository's application as a library
279
- if conf.OPTIONAL.MAIN_APP_DIR is not None:
280
286
  # This repo holds the library, not the standalone app: search in root_dir/build
281
287
  lib_path = find_application(project_root_dir, device_name, manifest.app.sdk)
282
288
  speculos_args.append(f"-l{lib_path}")
289
+ # If the app is standalone, the main app should be located in project_root_dir / manifest.app.build_directory
290
+ else:
291
+ main_app_path = find_application(project_root_dir / manifest.app.build_directory,
292
+ device_name, manifest.app.sdk)
283
293
 
284
294
  # Legacy lib method, remove once exchange is ported
285
295
  if len(conf.OPTIONAL.SIDELOADED_APPS) != 0:
@@ -290,8 +300,15 @@ def prepare_speculos_args(root_pytest_dir: Path,
290
300
  libs_dir = Path(project_root_dir / conf.OPTIONAL.SIDELOADED_APPS_DIR)
291
301
  # Add "-l Appname:filepath" to Speculos command line for every required lib app
292
302
  for coin_name, lib_name in conf.OPTIONAL.SIDELOADED_APPS.items():
293
- lib_path = find_library_application(libs_dir, coin_name, device_name)
294
- speculos_args.append(f"-l{lib_name}:{lib_path}")
303
+ try:
304
+ lib_path = find_library_application(libs_dir, coin_name, device_name)
305
+ speculos_args.append(f"-l{lib_name}:{lib_path}")
306
+ except MissingElfError as e:
307
+ if ignore_missing_binaries:
308
+ warnings.warn(f"Could not find sideloaded app library for '{lib_name}': {e}",
309
+ UserWarning)
310
+ else:
311
+ raise
295
312
  else:
296
313
  # Keep this method instead
297
314
  # Find all external libraries that have to be sideloaded
@@ -300,10 +317,17 @@ def prepare_speculos_args(root_pytest_dir: Path,
300
317
  subdirs = sorted(
301
318
  filter(lambda d: (sideloaded_dir / d).is_dir(), os.listdir(sideloaded_dir)))
302
319
  for subdir in subdirs:
303
- # Currently only C apps are used as additional binaries by ragger (Ethereum and Exchange)
304
- # TODO: add support for Rust SDK libraries if needed
305
- lib_path = find_application(sideloaded_dir / subdir, device_name, "c")
306
- speculos_args.append(f"-l{lib_path}")
320
+ try:
321
+ # Currently only C apps are used as additional binaries by ragger (Ethereum and Exchange)
322
+ # TODO: add support for Rust SDK libraries if needed
323
+ lib_path = find_application(sideloaded_dir / subdir, device_name, "c")
324
+ speculos_args.append(f"-l{lib_path}")
325
+ except MissingElfError as e:
326
+ if ignore_missing_binaries:
327
+ warnings.warn(f"Could not find sideloaded app binary for '{subdir}': {e}",
328
+ UserWarning)
329
+ else:
330
+ raise
307
331
 
308
332
  # Check if custom user seed has been provided through CLI or optional configuration.
309
333
  # CLI user seed has priority over the optional configuration seed.
@@ -326,7 +350,8 @@ def create_backend(root_pytest_dir: Path,
326
350
  log_apdu_file: Optional[Path],
327
351
  cli_user_seed: str,
328
352
  additional_speculos_arguments: List[str],
329
- verbose_speculos: bool = False) -> BackendInterface:
353
+ verbose_speculos: bool = False,
354
+ ignore_missing_binaries: bool = False) -> BackendInterface:
330
355
  if backend_name.lower() == "ledgercomm":
331
356
  return LedgerCommBackend(device=device,
332
357
  interface="hid",
@@ -338,7 +363,8 @@ def create_backend(root_pytest_dir: Path,
338
363
  main_app_path, speculos_args = prepare_speculos_args(root_pytest_dir, device, display,
339
364
  pki_prod, cli_user_seed,
340
365
  additional_speculos_arguments,
341
- verbose_speculos)
366
+ verbose_speculos,
367
+ ignore_missing_binaries)
342
368
  return SpeculosBackend(main_app_path,
343
369
  device=device,
344
370
  log_apdu_file=log_apdu_file,
@@ -353,12 +379,21 @@ def create_backend(root_pytest_dir: Path,
353
379
  @pytest.fixture(scope=conf.OPTIONAL.BACKEND_SCOPE)
354
380
  def backend(skip_tests_for_unsupported_devices, root_pytest_dir: Path, backend_name: str,
355
381
  device: Device, display: bool, pki_prod: bool, log_apdu_file: Optional[Path],
356
- cli_user_seed: str, additional_speculos_arguments: List[str],
357
- verbose_speculos: bool) -> Generator[BackendInterface, None, None]:
382
+ cli_user_seed: str, additional_speculos_arguments: List[str], verbose_speculos: bool,
383
+ ignore_missing_binaries: bool) -> Generator[BackendInterface, None, None]:
358
384
  # to separate the test name and its following logs
359
385
  print("")
360
- with create_backend(root_pytest_dir, backend_name, device, display, pki_prod, log_apdu_file,
361
- cli_user_seed, additional_speculos_arguments, verbose_speculos) as b:
386
+ backend_instance = None
387
+ try:
388
+ backend_instance = create_backend(root_pytest_dir, backend_name, device, display, pki_prod,
389
+ log_apdu_file, cli_user_seed,
390
+ additional_speculos_arguments, verbose_speculos,
391
+ ignore_missing_binaries)
392
+ except MissingElfError as e:
393
+ pytest.fail(f"Missing ELF: {e}")
394
+
395
+ assert backend_instance is not None, "Backend instance should be initialized"
396
+ with backend_instance as b:
362
397
  if backend_name.lower() != "speculos" and conf.OPTIONAL.APP_NAME:
363
398
  # Make sure the app is restarted as this is what is requested by the fixture scope
364
399
  app_name, version = get_current_app_name_and_version(b)
@@ -173,3 +173,11 @@ class ExceptionRAPDU(Exception):
173
173
 
174
174
  def __str__(self):
175
175
  return f"Error [0x{self.status:x}] {str(self.data)}"
176
+
177
+
178
+ class MissingElfError(Exception):
179
+ """Exception raised when an expected ELF binary is missing."""
180
+
181
+ def __init__(self, path: str):
182
+ super().__init__(f"File '{path}' missing. Did you compile for this target?")
183
+ self.path = path
@@ -16,7 +16,7 @@
16
16
  import toml
17
17
  from typing import Optional, Tuple, List
18
18
  from pathlib import Path
19
- from ragger.error import ExceptionRAPDU
19
+ from ragger.error import ExceptionRAPDU, MissingElfError
20
20
  import subprocess
21
21
  import json
22
22
 
@@ -48,7 +48,7 @@ def find_library_application(base_dir: Path, name: str, device: str) -> Path:
48
48
  raise AssertionError(f"{base_dir} is not a directory")
49
49
  lib = Path(base_dir / (name + "_" + device + ".elf")).resolve()
50
50
  if not lib.is_file():
51
- raise AssertionError(f"File '{lib}' missing. Did you compile for this target?")
51
+ raise MissingElfError(str(lib))
52
52
  return lib
53
53
 
54
54
 
@@ -91,7 +91,7 @@ def find_application(base_dir: Path, device: str, sdk: str) -> Path:
91
91
  else:
92
92
  app = app / "build" / device / "bin" / "app.elf"
93
93
  if not app.is_file():
94
- raise AssertionError(f"File '{app}' missing. Did you compile for this target?")
94
+ raise MissingElfError(str(app))
95
95
  return app
96
96
 
97
97
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ragger
3
- Version: 1.41.1
3
+ Version: 1.41.2
4
4
  Summary: Testing framework using Speculos and LedgerComm as backends
5
5
  Author-email: Ledger <hello@ledger.fr>
6
6
  Project-URL: Homepage, https://github.com/LedgerHQ/ragger
@@ -4,7 +4,7 @@ from pathlib import Path
4
4
  from unittest import TestCase
5
5
  from unittest.mock import MagicMock
6
6
 
7
- from ragger.error import ExceptionRAPDU
7
+ from ragger.error import ExceptionRAPDU, MissingElfError
8
8
  from ragger.utils import misc
9
9
 
10
10
  from ..helpers import temporary_directory
@@ -47,7 +47,7 @@ class TestMisc(TestCase):
47
47
  tmp_dir = (dir_path / "build" / device / "bin")
48
48
  tmp_dir.mkdir(parents=True, exist_ok=True)
49
49
  expected = tmp_dir / "app.elf"
50
- with self.assertRaises(AssertionError) as error:
50
+ with self.assertRaises(MissingElfError) as error:
51
51
  misc.find_application(dir_path, device, sdk)
52
52
  self.assertIn(str(expected), str(error.exception))
53
53
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes