def test_prepare_with_multiple_require_errors(self): """Test multiple require dependencies errors at different levels.""" serv_base_error = Service('A') serv_ok_warnings = Service('B') serv_error = Service('C') serv_timeout = Service('D') ac_suc = Action(name='start', command='/bin/true') ac_suc2 = Action(name='start', command='/bin/true') ac_suc3 = Action(name='start', command='/bin/true') ac_tim = Action(name='start', command='sleep 3', timeout=0.3) serv_base_error.add_action(ac_suc) serv_ok_warnings.add_action(ac_suc2) serv_error.add_action(ac_suc3) serv_timeout.add_action(ac_tim) serv_base_error.add_dep(serv_ok_warnings) serv_base_error.add_dep(serv_error) serv_ok_warnings.add_dep(serv_timeout, REQUIRE_WEAK) serv_error.add_dep(serv_timeout) serv_base_error.run('start') self.assertEqual(serv_base_error.status, DEP_ERROR) self.assertEqual(serv_ok_warnings.status, DONE) self.assertEqual(serv_error.status, DEP_ERROR) self.assertEqual(serv_timeout.status, TIMEOUT)
def test_missing_action(self): """Test prepare with service with missing action is ok""" # Graph leaf has no 'status' action s1 = Service("1") s1.add_action(Action('start', command='/bin/true')) s1.add_action(Action('status', command='/bin/true')) s2 = Service("2") s2.add_action(Action('start', command='/bin/true')) s2.add_dep(s1) s2.run('status') self.assertEqual(s1.status, DONE) self.assertEqual(s2.status, MISSING) s1.reset() s2.reset() self.assertEqual(s1.status, NO_STATUS) self.assertEqual(s2.status, NO_STATUS) # 'status' action is propagated to leaf even if '2' has not the # requested action. s3 = Service("3") s3.add_action(Action('start', command='/bin/true')) s3.add_action(Action('status', command='/bin/true')) s3.add_dep(s2) s3.run('status') self.assertEqual(s1.status, DONE) self.assertEqual(s2.status, MISSING) self.assertEqual(s3.status, DONE)
def test_prepare_multiple_delay(self): '''Test prepare with dependencies and multiple delays''' serv = Service('BASE_DELAYED') serv_a = Service('A_NOT_DELAYED') serv_b = Service('B_DELAYED') serv_c = Service('C_DELAYED') act_a = Action(name='start', command='/bin/true') act_serv = Action(name='start', command='/bin/true', delay=0.3) act_b = Action(name='start', command='/bin/true', delay=0.3) act_c = Action(name='start', command='/bin/true', delay=0.5) serv.add_action(act_serv) serv_a.add_action(act_a) serv_b.add_action(act_b) serv_c.add_action(act_c) serv.add_dep(serv_a) serv.add_dep(serv_b) serv_a.add_dep(serv_c) serv_b.add_dep(serv_c) serv.run('start') self.assertEqual(serv.status, DONE) self.assert_near(0.3, 0.2, act_serv.duration) self.assertEqual(serv_a.status, DONE) self.assert_near(0.0, 0.2, act_a.duration) self.assertEqual(serv_b.status, DONE) self.assert_near(0.3, 0.2, act_b.duration) self.assertEqual(serv_c.status, DONE) self.assert_near(0.5, 0.2, act_c.duration)
def test_prepare_errors_same_level(self): """Test prepare behaviour with two errors at the same level""" serv = Service('BASE') serv_a = Service('DEP_A') serv_b = Service('DEP_B') serv_c = Service('DEP_C') ac_suc = Action(name='start', command='/bin/true') ac_suc2 = Action(name='start', command='/bin/true') ac_err = Action(name='start', command='/bin/false') ac_err2 = Action(name='start', command='dlvlfvlf') serv.add_action(ac_suc) serv_a.add_action(ac_suc2) serv_b.add_action(ac_err) serv_c.add_action(ac_err2) serv.add_dep(serv_a) serv_a.add_dep(serv_b) serv_a.add_dep(serv_c) serv.run('start') self.assertEqual(serv.status, DEP_ERROR) self.assertEqual(serv_a.status, DEP_ERROR) self.assertEqual(serv_b.status, ERROR) self.assertEqual(serv_c.status, ERROR)
def test_nb_errors_remote2(self): """Test the method nb_errors() with no error (remote).""" action = Action(name="test", target=HOSTNAME, command="/bin/true") service = Service("test_service") service.add_action(action) service.run("test") self.assertEqual(action.nb_errors(), 0) self.assertEqual(action.status, DONE)
def test_prepare_single_service(self): """Test prepare without dependencies between services.""" serv_test = Service('test_service') ac_start = Action(name='start', command='/bin/true') serv_test.add_action(ac_start) serv_test.run('start') self.assertTrue(serv_test.origin) self.assertEqual(serv_test.status, DONE)
def test_prepare_delayed_action(self): """Test prepare Service with a delayed action""" serv = Service('DELAYED_SERVICE') act = Action(name='start', command='/bin/true', delay=1) serv.add_action(act) serv.run('start') self.assertEqual(serv.status, DONE) self.assert_near(1.0, 0.3, act.duration)
def test_nb_timeout_remote(self): """Test nb_timeout() method (remote mode)""" action = Action(name="start", target=HOSTNAME, command="sleep 3", timeout=0.5) service = Service("test_service") service.add_action(action) service.run("start") self.assertEqual(action.nb_timeout(), 1) self.assertEqual(action.status, TIMEOUT)
def test_perform_action_bad_service(self): '''test perform action with a simulate service hooked to the action''' action = Action(name='start', command=':') ser = Service('TEST') ser.simulate = True ser.add_action(action) ser.run('start') task_manager = action_manager_self() self.assertEqual(task_manager.tasks_done_count, 0)
def test_nb_timeout_local(self): """Test nb_timeout() method (local)""" action = Action(name="start", command="sleep 3", timeout=0.3) service = Service("test_service") service.add_action(action) service.run("start") self.assertEqual(action.nb_errors(), 0) self.assertEqual(action.nb_timeout(), 1) self.assertEqual(action.status, TIMEOUT)
def test_run_reverse_single_service(self): """Test run action stop on service (reverse algorithm)""" ser = Service('REVERSE') ser.algo_reversed = True stop = Action('stop', command='/bin/true') ser.add_action(stop) ser.run('stop') self.assertEqual(ser.status, DONE) self.assertTrue(stop.duration)
def test_nb_errors_remote2(self): """Test the method nb_errors() with no error (remote).""" action = Action(name='test', target=HOSTNAME, command='/bin/true') service = Service('test_service') service.add_action(action) service.run('test') self.assertEqual(action.nodes_error(), NodeSet()) self.assertEqual(action.nb_errors(), 0) self.assertEqual(action.status, DONE)
def test_perform_action(self): """test perform an action without any delay""" action = Action("start", command="/bin/true") ser = Service("TEST") ser.add_action(action) ser.run("start") task_manager = action_manager_self() self.assertEqual(task_manager.tasks_done_count, 1) self.assertTrue(action.duration < 0.5, "Too long: %.2f > 0.5" % action.duration)
def test_nb_errors_remote(self): """Test the method nb_errors() (remote).""" action = Action(name="start", target="aury[12,13,21]", command="/bin/false") action.errors = 2 service = Service("test_service") service.add_action(action) service.run("start") self.assertEqual(action.nb_errors(), 3) self.assertEqual(action.status, ERROR)
def test_perform_action_bad_service(self): """test perform action with a simulate service hooked to the action""" action = Action(name="start", command=":") ser = Service("TEST") ser.simulate = True ser.add_action(action) ser.run("start") task_manager = action_manager_self() self.assertEqual(task_manager.tasks_done_count, 0)
def test_perform_delayed_action(self): """test perform an action with a delay""" action = Action('start', command='sleep 0.3') ser = Service('TEST') ser.add_action(action) ser.run('start') task_manager = action_manager_self() ActionManager._instance = None self.assertEqual(task_manager.tasks_done_count, 1) self.assert_near(0.3, 0.1, action.duration)
def test_perform_action(self): """test perform an action without any delay""" action = Action('start', command='/bin/true') ser = Service('TEST') ser.add_action(action) ser.run('start') task_manager = action_manager_self() self.assertEqual(task_manager.tasks_done_count, 1) self.assertTrue(action.duration < 0.5, "Too long: %.2f > 0.5" % action.duration)
def test_run_skipped(self): """Run a service with empty target is SKIPPED""" svc = Service('test_service') action = Action('start', target="TEMPNODE", command=":") svc.add_action(action) action.update_target("TEMPNODE", 'DIF') svc.run('start') self.assertEqual(action.status, SKIPPED) self.assertEqual(svc.status, SKIPPED)
def test_nb_timeout_remote(self): """Test nb_timeout() method (remote mode)""" action = Action(name='start', target=HOSTNAME, command='sleep 3', timeout=0.5) service = Service('test_service') service.add_action(action) service.run('start') self.assertEqual(action.nodes_timeout(), NodeSet(HOSTNAME)) self.assertEqual(action.nb_timeout(), 1) self.assertEqual(action.status, TIMEOUT)
def test_nb_timeout_local(self): """Test nb_timeout() method (local)""" action = Action(name='start', command='sleep 3', timeout=0.3) service = Service('test_service') service.add_action(action) service.run('start') self.assertEqual(action.nodes_error(), NodeSet()) self.assertEqual(action.nb_errors(), 0) self.assertEqual(action.nodes_timeout(), NodeSet("localhost")) self.assertEqual(action.nb_timeout(), 1) self.assertEqual(action.status, TIMEOUT)
def test_nb_errors_remote(self): """Test the method nb_errors() (remote).""" action = Action(name='start', target='badname[12,13,21]', command='/bin/false') action.errors = 2 service = Service('test_service') service.add_action(action) service.run('start') self.assertEqual(action.nodes_error(), NodeSet("badname[12,13,21]")) self.assertEqual(action.nb_errors(), 3) self.assertEqual(action.status, ERROR)
def test_retry_error(self): """Test retry behaviour when errors""" action = Action("start", command="/bin/false") action.delay = 0.1 action.maxretry = 3 service = Service("retry") service.add_action(action) service.run("start") self.assertEqual(action.tries, 4) self.assertEqual(action.status, ERROR) self.assertTrue(0.3 < action.duration < 0.5, "%.3f is not between 0.3 and 0.5" % action.duration)
def test_run_action_with_failed_subaction(self): """Test action running a failed sub action (start->status)""" serv = Service('BASE') act_start = Action('start', command='/bin/true') act_status_fail = Action('status', command='/bin/false') act_start.add_dep(target=act_status_fail) serv.add_actions(act_start, act_status_fail) serv.run('start') self.assertEqual(serv.status, DONE) self.assertTrue(act_start.duration) self.assertTrue(act_status_fail.duration)
def test_retry_timeout(self): """Test retry behaviour when timeout""" action = Action("start", command="/bin/sleep 0.5", timeout=0.1) action.delay = 0.1 action.maxretry = 2 service = Service("retry") service.add_action(action) service.run("start") self.assertEqual(action.tries, 3) self.assertEqual(action.status, TIMEOUT) self.assertTrue(0.6 < action.duration < 0.8, "%.3f is not between 0.6 and 0.8" % action.duration)
def test_retry_error(self): """Test retry behaviour when errors""" action = Action('start', command='/bin/false') action.delay = 0.1 action.maxretry = 3 service = Service('retry') service.add_action(action) service.run('start') self.assertEqual(action.tries, 4) self.assertEqual(action.status, ERROR) self.assertTrue(0.3 < action.duration < 0.5, "%.3f is not between 0.3 and 0.5" % action.duration)
def test_retry_timeout(self): """Test retry behaviour when timeout""" action = Action('start', command='/bin/sleep 0.5', timeout=0.1) action.delay = 0.1 action.maxretry = 2 service = Service('retry') service.add_action(action) service.run('start') self.assertEqual(action.tries, 3) self.assertEqual(action.status, TIMEOUT) self.assertTrue(0.59 <= action.duration <= 0.8, "%.3f is not between 0.59 and 0.8" % action.duration)
def test_filter_dep_no_error(self): """test FILTER dependency without error""" svc1 = Service('first') svc1.add_action(Action('start', command='/bin/true', target=HOSTNAME)) svc2 = Service('second') svc2.add_action(Action('start', command='/bin/true', target=HOSTNAME)) svc2.add_dep(svc1, sgth=FILTER) svc2.run('start') self.assertEqual(svc1.status, DONE) self.assertEqual(svc2.status, DONE)
def test_filter_mix_no_target(self): """service without target do not filter service with target""" svc1 = Service('top') svc1.add_action(Action('start', command='false')) svc2 = Service('bottom') svc2.add_action(Action('start', command='true', target='localhost')) svc2.add_dep(svc1, sgth=FILTER) svc2.run('start') self.assertEqual(svc1.status, ERROR) self.assertEqual(svc2.status, DONE)
def test_filter_dep_one_error(self): """error nodes are propagated along 'filter' dependencies""" svc1 = Service('first') svc1.add_action(Action('start', command='false', target=HOSTNAME)) svc2 = Service('second') svc2.add_action(Action('start', command='true', target=HOSTNAME)) svc2.add_dep(svc1, sgth=FILTER) svc2.run('start') self.assertEqual(svc1.status, ERROR) self.assertEqual(svc2.status, SKIPPED)
def test_filter_dep_timeout(self): """timeout nodes are propagated along 'filter' dependencies""" svc1 = Service('first') svc1.add_action(Action('start', command='sleep 1', target=HOSTNAME, timeout=0.1)) svc2 = Service('second') svc2.add_action(Action('start', command='true', target=HOSTNAME)) svc2.add_dep(svc1, sgth=FILTER) svc2.run('start') self.assertEqual(svc1.status, TIMEOUT) self.assertEqual(svc2.status, SKIPPED)
def test_filter_dep_error_propagation(self): """error nodes are propagated along 'filter' dependencies (one node)""" svc1 = Service('first') tgt = '%s,fakenode' % HOSTNAME svc1.add_action(Action('start', command='true', target=tgt)) svc2 = Service('second') svc2.add_action(Action('start', command='true', target=HOSTNAME)) svc2.add_dep(svc1, sgth=FILTER) svc2.run('start') self.assertEqual(svc1.status, ERROR) self.assertEqual(svc2.status, DONE)
def test_filter_dep_timeout(self): """timeout nodes are propagated along 'filter' dependencies""" svc1 = Service('first') svc1.add_action( Action('start', command='sleep 1', target=HOSTNAME, timeout=0.1)) svc2 = Service('second') svc2.add_action(Action('start', command='true', target=HOSTNAME)) svc2.add_dep(svc1, sgth=FILTER) svc2.run('start') self.assertEqual(svc1.status, TIMEOUT) self.assertEqual(svc2.status, SKIPPED)
def test_exec_mode(self): """Test exec mode""" action = Action(name='start', command='echo %%h %%rank', target='%s,localhost' % HOSTNAME) action.mode = 'exec' svc = Service('test') svc.add_action(action) svc.resolve_all() svc.run('start') # Need 2 checks because we do not know which target will be used first outputs = [action.worker.node_buffer(HOSTNAME), action.worker.node_buffer('localhost')] self.assertTrue(outputs == ["%s 0" % HOSTNAME, "localhost 1"] or outputs == ["%s 1" % HOSTNAME, "localhost 0"])
def test_skipped_action_overload(self): """Test action is not skipped if they overload target.""" # A dep on ERROR dep = Service('dep') dep.add_action(Action('start', command='/bin/false')) # A service running on empty nodeset... svc = Service('foo', target='@NOTEXIST') # ... with an action overloading the empty nodeset svc.add_action(Action('start', target=HOSTNAME, command=':')) svc.add_dep(dep) svc.run('start') self.assertEqual(dep.status, ERROR) self.assertEqual(svc.status, DEP_ERROR)
def test_run_reverse_with_dependencies(self): ser = Service('REVERSE_BASE') ser_dep = Service('REVERSE_DEP') ser.algo_reversed = True ser_dep.algo_reversed = True stop1 = Action('stop', command='/bin/true') stop2 = Action('stop', command='/bin/true') ser.add_action(stop1) ser_dep.add_action(stop2) ser.add_dep(ser_dep) ser_dep.run('stop') self.assertEqual(ser.status, DONE) self.assertTrue(stop1.duration) self.assertEqual(ser_dep.status, DONE) self.assertTrue(stop2.duration)
def test_filter_error_no_action(self): """ propagation along 'filter' dependencies works if action names mismatch """ svc1 = Service('first') svc1.add_action(Action('start', command='false', target=HOSTNAME)) svc2 = Service('second') svc2.add_action(Action('other', command='true', target=HOSTNAME)) svc2.add_dep(svc1, sgth=FILTER) svc2.run('start') self.assertEqual(svc1.status, ERROR) self.assertEqual(svc2.status, MISSING)
def test_perform_remote_false_action(self): """Test perform an action in remote mode=False""" action = Action('start', command='hostname -s', target='node1') action.remote = False svc = Service('Local') svc.add_action(action) mytopo = tempfile.NamedTemporaryFile('w') mytopo.write(u"[routes]\n%s: node1\n" % HOSTNAME) mytopo.flush() task_self().load_topology(mytopo.name) mytopo.close() svc.run('start') buff = action.worker.node_buffer('node1').decode() self.assertEqual(buff, HOSTNAME)
def test_prepare_one_dependency(self): """Test prepare with one dependency.""" # Define the main service serv_test = Service('test_service') start = Action(name='start', command='/bin/true') start2 = Action(name='start', command='/bin/true') serv_test.add_action(start) # Define the single dependency of the main service serv_dep = Service('dependency') serv_dep.add_action(start2) serv_test.add_dep(serv_dep) # Start preparing of the base service serv_test.run('start') self.assertEqual(serv_test.status, DONE) self.assertEqual(serv_dep.status, DONE)
def test_run_with_locked_service(self): '''Test run services with locked dependencies''' s1 = Service('S1') s2 = Service('S2') s3 = Service('S3') s4 = Service('S4') s5 = Service('S5') # Actions S1 start_s1 = Action('start', command='/bin/true') stop_s1 = Action('stop', command='/bin/true') s1.add_actions(start_s1, stop_s1) # Actions S2 start_s2 = Action('start', command='/bin/true') stop_s2 = Action('stop', command='/bin/true') s2.add_actions(start_s2, stop_s2) # Actions S3 start_s3 = Action('start', command='/bin/false') stop_s3 = Action('stop', command='/bin/false') s3.add_actions(start_s3, stop_s3) # Actions S4 start_s4 = Action('start', command='/bin/true') stop_s4 = Action('stop', command='/bin/true') s4.add_actions(start_s4, stop_s4) # Actions I1 start_s5 = Action('start', command='/bin/true') stop_s5 = Action('stop', command='/bin/true') s5.add_actions(start_s5, stop_s5) # Locked services s3.status = LOCKED # Build graph s1.add_dep(target=s2) s1.add_dep(target=s3) s3.add_dep(target=s4) s3.add_dep(target=s5) # Run service S1 s1.run('start') self.assertEqual(s1.status, DONE) self.assertEqual(s2.status, DONE) self.assertEqual(s3.status, LOCKED) self.assertEqual(s4.status, NO_STATUS) self.assertEqual(s5.status, NO_STATUS)
def test_exec_mode(self): """Test exec mode""" action = Action(name='start', command='echo %%h %%rank', target='%s,localhost' % HOSTNAME) action.mode = 'exec' svc = Service('test') svc.add_action(action) svc.resolve_all() svc.run('start') # Need 2 checks because we do not know which target will be used first outputs = [ action.worker.node_buffer(HOSTNAME).decode(), action.worker.node_buffer('localhost').decode() ] self.assertTrue(outputs == ["%s 0" % HOSTNAME, "localhost 1"] or outputs == ["%s 1" % HOSTNAME, "localhost 0"])