1616import platform
1717import signal
1818import shutil
19+ import time
1920from pathlib import Path
2021
2122import pytest
2223import simplejson as json
2324from invoke import Local
2425from invoke .context import Context
2526import tempfile
27+ from filelock import FileLock
2628
2729from .common import Board
2830
@@ -54,22 +56,32 @@ def data_dir(tmpdir_factory):
5456 if platform .system () == "Windows" :
5557 with tempfile .TemporaryDirectory () as tmp :
5658 yield tmp
57- shutil .rmtree (tmp , ignore_errors = True )
59+ # shutil.rmtree(tmp, ignore_errors=True)
5860 else :
5961 data = tmpdir_factory .mktemp ("ArduinoTest" )
6062 yield str (data )
61- shutil .rmtree (data , ignore_errors = True )
63+ # shutil.rmtree(data, ignore_errors=True)
6264
6365
6466@pytest .fixture (scope = "session" )
65- def downloads_dir (tmpdir_factory ):
67+ def downloads_dir (tmpdir_factory , worker_id ):
6668 """
6769 To save time and bandwidth, all the tests will access
6870 the same download cache folder.
6971 """
70- download_dir = tmpdir_factory .mktemp ("ArduinoTest" )
72+ download_dir = tmpdir_factory .mktemp ("ArduinoTest" , numbered = False )
73+
74+ # This folders should be created only once per session, if we're running
75+ # tests in parallel using multiple processes we need to make sure this
76+ # this fixture is executed only once, thus the use of the lockfile
77+ if not worker_id == "master" :
78+ lock = Path (download_dir / "lock" )
79+ with FileLock (lock ):
80+ if not lock .is_file ():
81+ lock .touch ()
82+
7183 yield str (download_dir )
72- shutil .rmtree (download_dir , ignore_errors = True )
84+ # shutil.rmtree(download_dir, ignore_errors=True)
7385
7486
7587@pytest .fixture (scope = "function" )
@@ -81,7 +93,7 @@ def working_dir(tmpdir_factory):
8193 """
8294 work_dir = tmpdir_factory .mktemp ("ArduinoTestWork" )
8395 yield str (work_dir )
84- shutil .rmtree (work_dir , ignore_errors = True )
96+ # shutil.rmtree(work_dir, ignore_errors=True)
8597
8698
8799@pytest .fixture (scope = "function" )
@@ -208,61 +220,16 @@ def copy_sketch(working_dir):
208220
209221
210222@pytest .fixture (scope = "function" )
211- def core_update_index (run_command , data_dir , downloads_dir , working_dir , tmpdir_factory ):
212- """
213- To save time and bandwidth we install and cache cores indexes and copy them to each individual test environment
214- """
215-
216- def _update_index ():
217- index_dir = tmpdir_factory .getbasetemp () / "core-indexes"
218- if not index_dir .exists ():
219- index_dir .mkdir ()
220- env = {
221- "ARDUINO_DATA_DIR" : str (index_dir ),
222- "ARDUINO_DOWNLOADS_DIR" : downloads_dir ,
223- }
224- run_command ("core update-index" , working_dir , env )
225- shutil .copytree (index_dir , data_dir , dirs_exist_ok = True )
226-
227- return _update_index
228-
229-
230- @pytest .fixture (scope = "function" )
231- def lib_update_index (run_command , data_dir , downloads_dir , working_dir , tmpdir_factory ):
232- """
233- To save time and bandwidth we install and cache libraries indexes and copy them to each individual test environment
234- """
235-
236- def _update_index ():
237- index_dir = tmpdir_factory .getbasetemp () / "lib-indexes"
238- if not index_dir .exists ():
239- index_dir .mkdir ()
240- env = {
241- "ARDUINO_DATA_DIR" : str (index_dir ),
242- "ARDUINO_DOWNLOADS_DIR" : downloads_dir ,
243- }
244- run_command ("lib update-index" , working_dir , env )
245- shutil .copyfile (index_dir / "library_index.json" , Path (data_dir ) / "library_index.json" )
246-
247- return _update_index
248-
249-
250- @pytest .fixture (scope = "function" )
251- def core_install (run_command , data_dir , downloads_dir , working_dir , tmpdir_factory ):
252- """
253- To save time and bandwidth we install and cache cores and copy them to each individual test environment
254- """
255- data_dir = Path (data_dir ) / "packages"
256-
257- def _install (core ):
258- core_dir = tmpdir_factory .getbasetemp () / core .replace (":" , "" )
259- if not core_dir .exists ():
260- core_dir .mkdir ()
261- env = {
262- "ARDUINO_DATA_DIR" : str (core_dir ),
263- "ARDUINO_DOWNLOADS_DIR" : downloads_dir ,
264- }
265- run_command (f"core install { core } " , working_dir , env )
266- shutil .copytree (core_dir / "packages" , data_dir , dirs_exist_ok = True )
267-
268- return _install
223+ def wait_for_board (run_command ):
224+ def _waiter (seconds = 10 ):
225+ # Waits for the specified amount of second for a board to be visible.
226+ # This is necessary since it might happen that a board is not immediately
227+ # available after a test upload and subsequent tests might consequently fail.
228+ time_end = time .time () + seconds
229+ while time .time () < time_end :
230+ result = run_command ("board list --format json" )
231+ ports = json .loads (result .stdout )
232+ if len ([p .get ("boards" , []) for p in ports ]) > 0 :
233+ break
234+
235+ return _waiter
0 commit comments