def test_basic(self): p1 = AbortingGetter('p1', count=2, vals=Numbers(-10, 10), set_cmd=None) sv = p1[1:3:1] loop = Loop(sv) # not sure why you'd do it, but you *can* snapshot a Loop expected = { '__class__': 'qcodes.loops.Loop', 'sweep_values': sv.snapshot(), 'delay': 0, 'then_actions': [] } self.assertEqual(loop.snapshot(), expected) loop = loop.then(Task(p1.set, 0), Wait(0.123)) expected['then_actions'] = [{ 'type': 'Task', 'func': repr(p1.set) }, { 'type': 'Wait', 'delay': 0.123 }] # then test snapshot on an ActiveLoop breaker = BreakIf(lambda: p1.get_latest() > 3) self.assertEqual(breaker.snapshot()['type'], 'BreakIf') loop = loop.each(p1, breaker) expected['__class__'] = 'qcodes.loops.ActiveLoop' expected['actions'] = [p1.snapshot(), breaker.snapshot()] self.assertEqual(loop.snapshot(), expected)
def test_then_construction(self): loop = Loop(self.p1[1:6:1]) task1 = Task(self.p1.set, 2) task2 = Wait(0.02) loop2 = loop.then(task1) loop3 = loop2.then(task2, task1) loop4 = loop3.then(task2, overwrite=True) loop5 = loop4.each(self.p1, BreakIf(lambda: self.p1.get() >= 3)) loop6 = loop5.then(task1) loop7 = loop6.then(task1, overwrite=True) # original loop is untouched, same as .each and .loop self.assertEqual(loop.then_actions, ()) # but loop2 has the task we asked for self.assertEqual(loop2.then_actions, (task1, )) # loop3 gets the other tasks appended self.assertEqual(loop3.then_actions, (task1, task2, task1)) # loop4 gets only the new one self.assertEqual(loop4.then_actions, (task2, )) # tasks survive .each self.assertEqual(loop5.then_actions, (task2, )) # and ActiveLoop.then works the same way as Loop.then self.assertEqual(loop6.then_actions, (task2, task1)) self.assertEqual(loop7.then_actions, (task1, )) # .then rejects Loops and others that are valid loop actions for action in (loop2, loop7, BreakIf(lambda: self.p1() >= 3), self.p1, True, 42): with self.assertRaises(TypeError): loop.then(action)
def test_basic(self): p1 = AbortingGetter('p1', count=2, vals=Numbers(-10, 10)) sv = p1[1:3:1] loop = Loop(sv) # not sure why you'd do it, but you *can* snapshot a Loop expected = { '__class__': 'qcodes.loops.Loop', 'sweep_values': sv.snapshot(), 'delay': 0, 'then_actions': [] } self.assertEqual(loop.snapshot(), expected) loop = loop.then(Task(p1.set, 0), Wait(0.123)) expected['then_actions'] = [{ 'type': 'Task', 'func': repr(p1.set) }, { 'type': 'Wait', 'delay': 0.123 }] # then test snapshot on an ActiveLoop breaker = BreakIf(p1.get_latest > 3) self.assertEqual(breaker.snapshot()['type'], 'BreakIf') # TODO: once we have reprs for DeferredOperations, test that # the right thing shows up in breaker.snapshot()['condition'] loop = loop.each(p1, breaker) expected['__class__'] = 'qcodes.loops.ActiveLoop' expected['actions'] = [p1.snapshot(), breaker.snapshot()] self.assertEqual(loop.snapshot(), expected)
def test_tasks_waits(self): delay0 = 0.01 delay1 = 0.03 loop = Loop(self.p1[1:3:1], delay0).each(Task(self.p2.set, -1), Wait(delay1), self.p2, Task(self.p2.set, 1), self.p2) delay_array = [] loop._monitor = FakeMonitor(delay_array) # give it a "process" as if it was run in the bg before, # check that this gets cleared loop.process = 'TDD' data = loop.run_temp() self.assertFalse(hasattr(loop, 'process')) self.assertEqual(data.p1_set.tolist(), [1, 2]) self.assertEqual(data.p2_2.tolist(), [-1, -1]) self.assertEqual(data.p2_4.tolist(), [1, 1]) self.assertEqual(len(delay_array), 4) for i, delay in enumerate(delay_array): target = delay1 if i % 2 else delay0 self.assertLessEqual(delay, target) self.assertGreater(delay, target - 0.001)
def test_bad_delay(self): for val, err in [(-1, ValueError), (-0.1, ValueError), (None, TypeError), ('forever', TypeError)]: with self.assertRaises(err): Loop(self.p1[1:3:1], val) with self.assertRaises(err): Wait(val)
def test_bare_wait(self): # Wait gets transformed to a Task, but is also callable on its own t0 = time.perf_counter() Wait(0.05)() delay = time.perf_counter() - t0 # TODO: On Mac delay is always at least the time you waited, but on # Windows it is sometimes less? need to investigate the precision here. self.assertGreaterEqual(delay, 0.04) self.assertLessEqual(delay, 0.06)
def test_bare_wait(self): # Wait gets transformed to a Task, but is also callable on its own t0 = time.perf_counter() Wait(0.05)() delay = time.perf_counter() - t0 # TODO: On Mac delay is always at least the time you waited, but on # Windows it is sometimes less? need to investigate the precision here. self.assertGreaterEqual(delay, 0.04) # On slow CI machines, there can be a significant additional delay. # So what are we even testing here..? self.assertLessEqual(delay, 0.07)
def test_then_action(self): self.maxDiff = None nan = float('nan') self.p1.set(5) f_calls, g_calls = [], [] def f(): f_calls.append(1) def g(): g_calls.append(1) breaker = BreakIf(lambda: self.p1() >= 3) ts1 = datetime.now().strftime('%Y-%m-%d %H:%M:%S') # evaluate param snapshots now since later value will change p1snap = self.p1.snapshot() self.p2.set(2) p2snap = self.p2.snapshot() self.p3.set(3) p3snap = self.p3.snapshot() data = Loop(self.p1[1:6:1]).each(self.p1, breaker).then(Task(self.p1.set, 2), Wait(0.01), Task(f)).run_temp() ts2 = datetime.now().strftime('%Y-%m-%d %H:%M:%S') self.assertEqual(repr(data.p1.tolist()), repr([1., 2., 3., nan, nan])) self.assertEqual(self.p1.get(), 2) self.assertEqual(len(f_calls), 1) # this loop makes use of all the features, so use it to test # DataSet metadata loopmeta = data.metadata['loop'] default_meas_meta = data.metadata['station']['default_measurement'] # assuming the whole loop takes < 1 sec, all timestamps # should each be the same as one of the bounding times self.check_snap_ts(loopmeta, 'ts_start', (ts1, ts2)) self.check_snap_ts(loopmeta, 'ts_end', (ts1, ts2)) self.check_snap_ts(loopmeta['sweep_values']['parameter'], 'ts', (ts1, ts2)) self.check_snap_ts(loopmeta['actions'][0], 'ts', (ts1, ts2)) self.check_snap_ts(default_meas_meta[0], 'ts', (ts1, ts2, None)) self.check_snap_ts(default_meas_meta[1], 'ts', (ts1, ts2, None)) del p1snap['ts'], p2snap['ts'], p3snap['ts'] self.assertEqual( data.metadata, { 'station': { 'instruments': {}, 'parameters': {}, 'components': {}, 'default_measurement': [p2snap, p3snap] }, 'loop': { 'use_threads': False, '__class__': 'qcodes.loops.ActiveLoop', 'sweep_values': { 'parameter': p1snap, 'values': [{ 'first': 1, 'last': 5, 'num': 5, 'type': 'linear' }] }, 'delay': 0, 'actions': [p1snap, breaker.snapshot()], 'then_actions': [{ 'type': 'Task', 'func': repr(self.p1.set) }, { 'type': 'Wait', 'delay': 0.01 }, { 'type': 'Task', 'func': repr(f) }] } }) # now test a nested loop with .then inside and outside f_calls[:] = [] Loop(self.p1[1:3:1]).each( Loop(self.p2[1:3:1]).each(self.p2).then(Task(g))).then( Task(f)).run_temp() self.assertEqual(len(f_calls), 1) self.assertEqual(len(g_calls), 2) # Loop.loop nesting always just makes the .then actions run after # the outer loop f_calls[:] = [] Loop(self.p1[1:3:1]).then(Task(f)).loop(self.p2[1:3:1]).each( self.p1).run_temp() self.assertEqual(len(f_calls), 1) f_calls[:] = [] Loop(self.p1[1:3:1]).loop(self.p2[1:3:1]).then(Task(f)).each( self.p1).run_temp() self.assertEqual(len(f_calls), 1) f_calls[:] = [] Loop(self.p1[1:3:1]).loop(self.p2[1:3:1]).each(self.p1).then( Task(f)).run_temp() self.assertEqual(len(f_calls), 1)