11import logging
2+ from signal import SIGTERM
23import sys
34import threading
45from importlib .util import find_spec
56
67import pytest
78import pexpect
9+ import yaml
810
911from labgrid import Target
1012from labgrid .driver import SerialDriver
@@ -98,10 +100,33 @@ def serial_driver_no_name(target, serial_port, mocker):
98100 return s
99101
100102@pytest .fixture (scope = 'function' )
101- def crossbar (tmpdir , pytestconfig ):
103+ def crossbar_config (tmpdir , pytestconfig ):
104+ crossbar_config = '.crossbar/config.yaml'
105+
106+ pytestconfig .rootdir .join (crossbar_config ).copy (tmpdir .mkdir ('.crossbar' ))
107+
108+ # crossbar runs labgrid's coordinator component as a guest, record its coverage
109+ if pytestconfig .pluginmanager .get_plugin ('pytest_cov' ):
110+ with open (tmpdir .join (crossbar_config ), 'r+' ) as stream :
111+ conf = yaml .safe_load (stream )
112+
113+ for worker in conf ['workers' ]:
114+ if worker ['type' ] == 'guest' :
115+ worker ['executable' ] = 'coverage'
116+ worker ['arguments' ].insert (0 , 'run' )
117+ worker ['arguments' ].insert (1 , '--parallel-mode' )
118+ # pytest-cov combines coverage files in root dir automatically, so copy it there
119+ coverage_data = pytestconfig .rootdir .join ('.coverage' )
120+ worker ['arguments' ].insert (2 , f'--data-file={ coverage_data } ' )
121+
122+ stream .seek (0 )
123+ yaml .safe_dump (conf , stream )
124+
125+ @pytest .fixture (scope = 'function' )
126+ def crossbar (tmpdir , crossbar_config ):
102127 if not find_spec ('crossbar' ):
103128 pytest .skip ("crossbar not found" )
104- pytestconfig . rootdir . join ( '.crossbar/config.yaml' ). copy ( tmpdir . mkdir ( '.crossbar' ))
129+
105130 spawn = pexpect .spawn (
106131 'crossbar start --color false --logformat none' ,
107132 logfile = Prefixer (sys .stdout .buffer , 'crossbar' ),
@@ -116,9 +141,14 @@ def crossbar(tmpdir, pytestconfig):
116141 reader = threading .Thread (target = keep_reading , name = 'crossbar-reader' , args = (spawn ,), daemon = True )
117142 reader .start ()
118143 yield spawn
144+
145+ # let coverage write its data:
146+ # https://coverage.readthedocs.io/en/latest/subprocess.html#process-termination
119147 print ("stopping crossbar" )
120- spawn .close (force = True )
121- assert not spawn .isalive ()
148+ spawn .kill (SIGTERM )
149+ spawn .expect (pexpect .EOF )
150+ spawn .wait ()
151+
122152 reader .join ()
123153
124154@pytest .fixture (scope = 'function' )
0 commit comments