8
8
from datetime import timedelta
9
9
from threading import Thread
10
10
from time import sleep
11
- from typing import Any , Callable
11
+ from typing import Callable
12
12
13
13
import h5py
14
14
from parameterized import parameterized
36
36
37
37
38
38
def nexus_file_with_retry (
39
- instrument : str , run_number : int , test_func : Callable [[h5py .File ], None ]
39
+ instrument : str , run_number : int , test_func : Callable [[h5py .File , int ], None ]
40
40
) -> None :
41
41
# isisicp writes files asynchronously, so need to retry file read
42
42
# in case file not completed and still locked
@@ -46,7 +46,8 @@ def nexus_file_with_retry(
46
46
for i in range (num_of_tries ):
47
47
try :
48
48
with h5py .File (nexus_file , "r" ) as f :
49
- test_func (f )
49
+ test_func (f , run_number )
50
+ break
50
51
except IOError :
51
52
if i == num_of_tries - 1 :
52
53
print ("{} not found, giving up" .format (nexus_file ))
@@ -153,6 +154,52 @@ def test_GIVEN_running_instrument_WHEN_pars_changed_THEN_pars_saved_in_file(self
153
154
else :
154
155
self .assertEqual (0 , saved_beamstop )
155
156
157
+ def test_GIVEN_running_instrument_WHEN_block_logging_but_not_changing_THEN_block_value_saved_in_file (
158
+ self ,
159
+ ):
160
+ load_config_if_not_already_loaded ("rcptt_simple" )
161
+ self .fail_if_not_in_setup ()
162
+ set_genie_python_raises_exceptions (True )
163
+ test_block_name = "FLOAT_BLOCK"
164
+ r_cnt_start = g .get_pv ("DAE:_RESTART_ARCHIVER_CNT" , is_local = True )
165
+ fr_cnt_start = g .get_pv ("DAE:_FR_ARCHIVER_CNT" , is_local = True )
166
+ ncheck = 10
167
+ # block is not changing but check we get at least one value logged
168
+ # test quick begin/end and some with delays
169
+ # there is a 5 second flush time in archiver -> mysql hence
170
+ # trying shorter and longer delays
171
+ delays = [(10 , 10 ), (2 , 10 ), (10 , 2 ), (2 , 2 ), (2 , 0 ), (0 , 2 ), (0 , 0 )]
172
+ for delay in delays :
173
+ print (f"Testing (pre, post) delay { delay } " )
174
+ for _ in range (ncheck ):
175
+ sleep (delay [0 ])
176
+ g .begin ()
177
+ sleep (delay [1 ])
178
+ run_number = g .get_runnumber ()
179
+ g .end ()
180
+ g .waitfor_runstate ("SETUP" , maxwaitsecs = self .TIMEOUT )
181
+ nexus_path = r"/raw_data_1/selog/{}/value_log" .format (test_block_name )
182
+
183
+ def test_function (f : h5py .File , run_number : int ) -> None :
184
+ # if no values are logged this will fail with a
185
+ # "Unable to synchronously open object (component not found)" exception
186
+ values = [val for val in f [nexus_path + r"/value" ][:]]
187
+ print (
188
+ f"Found { len (values )} value(s) for block { test_block_name } run { run_number } "
189
+ )
190
+ self .assertTrue (
191
+ len (values ) > 0 ,
192
+ f"Not enough values logged to file with delay { delay } " ,
193
+ )
194
+
195
+ nexus_file_with_retry (g .adv .get_instrument (), run_number , test_function )
196
+ # check archiver has restarted expected number of times and no force restarts
197
+ # ARBLOCK restarted on begin and end hence factor 2
198
+ r_cnt = g .get_pv ("DAE:_RESTART_ARCHIVER_CNT" , is_local = True )
199
+ fr_cnt = g .get_pv ("DAE:_FR_ARCHIVER_CNT" , is_local = True )
200
+ self .assertEqual (r_cnt , r_cnt_start + 2 * ncheck * len (delays ))
201
+ self .assertEqual (fr_cnt , fr_cnt_start )
202
+
156
203
def test_GIVEN_running_instrument_WHEN_block_logging_THEN_block_saved_in_file (self ):
157
204
load_config_if_not_already_loaded ("rcptt_simple" )
158
205
self .fail_if_not_in_setup ()
@@ -195,7 +242,7 @@ def test_GIVEN_running_instrument_WHEN_block_logging_THEN_block_saved_in_file(se
195
242
196
243
nexus_path = r"/raw_data_1/selog/{}/value_log" .format (test_block_name )
197
244
198
- def test_function (f : Any ) -> None :
245
+ def test_function (f : h5py . File , run_number : int ) -> None :
199
246
value_valid = f [nexus_path + r"/value_valid" ][:]
200
247
is_valid = [sample == 1 for sample in value_valid ]
201
248
values = [int (val ) for val in f [nexus_path + r"/value" ][:]]
@@ -270,7 +317,7 @@ def _assert_title_correct(self, test_title, expected_title):
270
317
271
318
g .waitfor_runstate ("SETUP" , maxwaitsecs = self .TIMEOUT )
272
319
273
- def test_func (f ) :
320
+ def test_func (f : h5py . File , run_number : int ) -> None :
274
321
saved_title = f ["/raw_data_1/title" ][0 ].decode ()
275
322
self .assertEqual (expected_title , saved_title )
276
323
@@ -567,7 +614,10 @@ def _adjust_icp_begin_delay(self, delay_seconds):
567
614
568
615
begindelay_property = "isisicp.begindelay"
569
616
config_line = "{} = {}\r \n " .format (begindelay_property , delay_seconds )
570
- if g .get_runstate () != "SETUP" :
617
+ g .waitfor_runstate ("PROCESSING" , maxwaitsecs = 30 , onexit = True )
618
+ runstate = g .get_runstate ()
619
+ if runstate != "SETUP" :
620
+ print (f"Aborting run as currently { runstate } " )
571
621
g .abort () # make sure not left in a funny state from e.g. previous aborted test
572
622
573
623
with g ._genie_api .dae .temporarily_kill_icp ():
@@ -813,9 +863,7 @@ def test_GIVEN_change_title_called_WHEN_valid_argument_THEN_get_title_correct_im
813
863
g .change_title (title )
814
864
self .assertEqual (g .get_title (), title )
815
865
816
- def test_GIVEN_dae_setup_WHEN_read_x_and_xe_THEN_centre_and_edges_correct (
817
- self
818
- ) -> None :
866
+ def test_GIVEN_dae_setup_WHEN_read_x_and_xe_THEN_centre_and_edges_correct (self ) -> None :
819
867
set_genie_python_raises_exceptions (True )
820
868
# check x and xe are correct length
821
869
ntc = g .get_number_timechannels ()
@@ -826,12 +874,10 @@ def test_GIVEN_dae_setup_WHEN_read_x_and_xe_THEN_centre_and_edges_correct(
826
874
# check x is a bin centre of xe edges
827
875
x = g .get_pv ("DAE:SPEC:1:1:X" , is_local = True )
828
876
xe = g .get_pv ("DAE:SPEC:1:1:XE" , is_local = True )
829
- self .assertAlmostEqual (x [0 ], (xe [0 ] + xe [1 ]) / 2.0 , delta = .001 )
877
+ self .assertAlmostEqual (x [0 ], (xe [0 ] + xe [1 ]) / 2.0 , delta = 0 .001 )
830
878
set_genie_python_raises_exceptions (False )
831
879
832
- def test_GIVEN_dae_setup_WHEN_paused_THEN_period_values_correct (
833
- self
834
- ) -> None :
880
+ def test_GIVEN_dae_setup_WHEN_paused_THEN_period_values_correct (self ) -> None :
835
881
set_genie_python_raises_exceptions (True )
836
882
sleep_time = 5
837
883
num_periods = 2
0 commit comments