def test_condition_else_fail(self): context = ExecutionContext() aA = jp.PathEqPredicate('a', 'A') bB = jp.PathEqPredicate('b', 'B') cC = jp.PathEqPredicate('c', 'C') ifAthenBelseC = jc.IF(aA, bB, cC) # False if all conditions are false # False if "if" is true and "then" is false even if "else" matches. test_cases = [{'a':'A', 'b':'X', 'c':'C'}, {'a':'X', 'b':'B', 'c':'D'}] for i in range(2): test = test_cases[i] tried = [aA(context, test)] if i < 1: # First has true IF so tries THEN tried.append(bB(context, test)) else: # Remainder has false IF so tries ELSE tried.append(cC(context, test)) expect = jc.CompositePredicateResult( valid=False, pred=ifAthenBelseC, results=tried) result = ifAthenBelseC(context, test) self.assertFalse(result) self.assertEqual(expect, result)
def test_condition_else_success(self): context = ExecutionContext(a='A', b='B', c='C') aA = jp.PathEqPredicate('a', lambda x: x['a']) bB = jp.PathEqPredicate('b', lambda x: x['b']) cC = jp.PathEqPredicate('c', lambda x: x['c']) ifAthenBelseC = jc.IF(aA, bB, cC) # True if all conditions are true. # True if "if" satisfied and "then" matches. # True if only else condition is true. test_cases = [_LETTER_DICT, {'a':'A', 'b':'B', 'c':'X'}, {'a':'X', 'b':'B', 'c':'C'}, {'a':'X', 'b':'X', 'c':'C'}, ] for i in range(3): test = test_cases[i] tried = [aA(context, test)] if i < 2: # First two have true IF to just execute THEN tried.append(bB(context, test)) else: # Remainder have false IF to just execute ELSE tried.append(cC(context, test)) expect = jc.CompositePredicateResult( valid=True, pred=ifAthenBelseC, results=tried) result = ifAthenBelseC(context, test) self.assertTrue(result) self.assertEqual(expect, result)
def test_condition_fail(self): aA = jp.PathEqPredicate('a', 'A') b2 = jp.PathEqPredicate('b', '2') ifAthen2 = jc.IF(aA, b2) demorgan = jc.OR([jc.NOT(aA), b2]) expect = demorgan(_LETTER_DICT) result = ifAthen2(_LETTER_DICT) self.assertFalse(result) self.assertEqual(expect, result)
def test_object_observation_verifier_with_conditional(self): # We need strict True here because we want each object to pass # the constraint test. Otherwise, if any object passes, then the whole # observation would pass. This causes a problem when we say that # we dont ever want to see 'name' unless it has a particular 'value'. # Without strict test, we'd allow this to occur as long as another object # satisfied that constraint. # When we use 'excludes', it applies to the whole observation since this # is normally the intent. However, here we are excluding values under # certain context -- "If the 'name' field is 'NAME' then it must contain # a value field 'VALUE'". Excluding name='NAME' everywhere would # not permit the context where value='VALUE' which we want to permit. verifier_builder = jc.ValueObservationVerifierBuilder( title='Test Conditional', strict=True) name_eq_pred = jp.PathEqPredicate('name', 'NAME') value_eq_pred = jp.PathEqPredicate('value', 'VALUE') conditional = jp.IF(name_eq_pred, value_eq_pred) pred_list = [jp.PathPredicate('', conditional)] verifier_builder.add_constraint(conditional) match_name_value_obj = {'name': 'NAME', 'value': 'VALUE'} match_value_not_name_obj = {'name': 'GOOD', 'value': 'VALUE'} match_neither_obj = {'name': 'GOOD', 'value': 'GOOD'} match_name_not_value_obj = {'name': 'NAME', 'value': 'BAD'} # bad test_cases = [(True, [match_name_value_obj, match_neither_obj]), (True, [match_value_not_name_obj, match_neither_obj]), (False, [match_neither_obj, match_name_not_value_obj])] context = ExecutionContext() verifier = verifier_builder.build() for test in test_cases: observation = jc.Observation() result_builder = jc.ObservationVerifyResultBuilder(observation) expect_valid = test[0] obj_list = test[1] observation.add_all_objects(obj_list) result_builder.add_observation_predicate_result( jc.ObservationValuePredicate(conditional)(context, observation)) # All of these tests succeed. verify_results = result_builder.build(expect_valid) try: self._try_verify(context, verifier, observation, expect_valid, verify_results) except: print 'testing {0}'.format(obj_list) raise
def test_condition_success(self): aA = jp.PathEqPredicate('a', 'A') bB = jp.PathEqPredicate('b', 'B') ifAthenB = jc.IF(aA, bB) demorgan = jc.OR([jc.NOT(aA), bB]) test_cases = [_LETTER_DICT, {'a': 'X', 'b': 'Y'}, {'a': 'X', 'b': 'B'}] for test in test_cases: expect = demorgan(test) result = ifAthenB(test) self.assertTrue(result) self.assertEqual(expect, result)
def test_condition_indirect_success(self): context = ExecutionContext(a='A', b='B') aA = jp.PathEqPredicate('a', lambda x: x['a']) bB = jp.PathEqPredicate('b', lambda x: x['b']) ifAthenB = jc.IF(aA, bB) demorgan = jc.OR([jc.NOT(aA), bB]) test_cases = [_LETTER_DICT, {'a':'X', 'b':'Y'}, {'a':'X', 'b':'B'}] for test in test_cases: expect = demorgan(context, test) result = ifAthenB(context, test) self.assertTrue(result) self.assertEqual(expect, result)
def terminate_instances(self, names, zone): """Creates test for removing specific instances. Args: names: A list of instance names to be removed. zone: The zone containing the instances. Returns: st.OperationContract """ builder = gcp.GcpContractBuilder(self.gcp_observer) clause = builder.new_clause_builder( "Instances Deleted", retryable_for_secs=30, strict=True).aggregated_list_resource("instances") for name in names: # If one of our instances still exists, it should be STOPPING. name_matches_pred = jp.PathContainsPredicate("name", name) is_stopping_pred = jp.PathEqPredicate("status", "STOPPING") # We want the condition to apply to all the observed objects so we'll # map the constraint over the observation. Otherwise, if dont map it, # then we'd expect the constraint to hold somewhere among the observed # objects, but not necessarily all of them. clause.AND( ov_factory.value_list_matches( [jp.IF(name_matches_pred, is_stopping_pred)], strict=True)) # pylint: disable=bad-continuation payload = self.agent.type_to_payload( "terminateInstances", { "instanceIds": names, "zone": zone, "credentials": self.bindings["SPINNAKER_GOOGLE_ACCOUNT"], }, ) return st.OperationContract( self.new_post_operation(title="terminate_instances", data=payload, path="gce/ops"), contract=builder.build(), )
def terminate_instances(self, names, zone): """Creates test for removing specific instances. Args: names: A list of instance names to be removed. zone: The zone containing the instances. Returns: st.OperationContract """ builder = gcp.GcpContractBuilder(self.gcp_observer) clause = (builder.new_clause_builder('Instances Deleted', retryable_for_secs=15, strict=True) .aggregated_list_resource('instances')) for name in names: # If one of our instances still exists, it should be STOPPING. name_matches_pred = jp.PathContainsPredicate('name', name) is_stopping_pred = jp.PathEqPredicate('status', 'STOPPING') # We want the condition to apply to all the observed objects so we'll # map the constraint over the observation. Otherwise, if dont map it, # then we'd expect the constraint to hold somewhere among the observed # objects, but not necessarily all of them. clause.add_constraint(jp.IF(name_matches_pred, is_stopping_pred)) # pylint: disable=bad-continuation payload = self.agent.type_to_payload( 'terminateInstances', { 'instanceIds': names, 'zone': zone, 'credentials': self.bindings['SPINNAKER_GOOGLE_ACCOUNT'] }) return st.OperationContract( self.new_post_operation( title='terminate_instances', data=payload, path='gce/ops'), contract=builder.build())