def parse(self, spec_name, spec_text): specification = Specification(spec_name) import ipdb preface = [] procedure_lines = [] for i, line in enumerate(spec_text): if line.strip().startswith('@invariant'): invariant = self.extract_function(spec_text[i + 1:], i + 2) specification.set_invariant(invariant) if line.strip().startswith('@gteq'): gteq = self.extract_function(spec_text[i + 1:], i + 2) specification.set_gteq(gteq) if line.strip().startswith('@merge'): end = self.get_end(spec_text[i + 1:], i + 1) procedure_lines = procedure_lines + list(range(i + 1, end + 1)) merge = self.extract_procedure(spec_text[i + 1:end + 1], i + 1) specification.set_merge(merge) if line.strip().startswith('procedure ') and not spec_text[ i - 1].startswith('@merge'): end = self.get_end(spec_text[i:], i) procedure_lines = procedure_lines + list(range(i, end + 1)) procedure = self.extract_procedure(spec_text[i:end + 1], i) specification.add_procedure(procedure) if line.strip().startswith('@'): preface.append('//' + line) elif i in procedure_lines: preface.append('//' + line) else: preface.append(line) if line.strip().startswith('var ') and i not in procedure_lines: variable = self.extract_variable(spec_text[i:], i + 1) specification.add_variable(variable) specification.set_preface(''.join(preface)) return specification
def get_spec(self): spec = Specification('sample') spec.add_variable(Variable('set', '[int]bool', 1)) procedure = Procedure('merge_6', 15) procedure.add_parameter(Parameter('set1', '[int]bool')) procedure.add_modifies('set') procedure.add_ensures( '(forall i:int :: set[i] == (old(set)[i] || set1[i]))') procedure.set_implementation('assume false;') spec.set_merge(procedure) gteq = Function('gteq', 5) gteq.add_param(Parameter('set1', '[int]bool')) gteq.add_param(Parameter('set2', '[int]bool')) gteq.set_return('bool') spec.set_gteq(gteq) spec.set_preface( 'var set:[int]bool;\n//@gteq\nfunction gteq(set1:[int]bool, set2:[int]bool) returns(bool)\n{(forall i:int :: set2[i] ==> set1[i])}' ) procedure = Procedure('add', 15) procedure.add_parameter(Parameter('value', 'int')) procedure.add_modifies('set') procedure.add_ensures( '(forall i:int :: (i == value ==> set[i] == true) && (i != value ==> set[i] == old(set)[i]))' ) procedure.set_implementation('set[value] := true;') spec.add_procedure(procedure) return spec
def get_compliant_spec(self): spec = Specification('name') spec.add_variable(Variable('one', 'int', 4)) gteq = Function('gteq', 2) gteq.parameters.append(Parameter('one1', 'int')) gteq.parameters.append(Parameter('one2', 'int')) gteq.returndt = 'bool' spec.set_gteq(gteq) inv = Function('inv', 2) inv.returndt = 'bool' inv.parameters.append(Parameter('one', 'int')) spec.set_invariant(inv) merge = Procedure('merge_proc', 10) merge.add_parameter(Parameter('one1', 'int')) merge.add_modifies('one') spec.set_merge(merge) return spec
def test_check_not_monotonicity(self): spec = Specification('sample') spec.add_variable(Variable('set', '[int]bool', 1)) procedure = Procedure('remove', 15) procedure.add_parameter(Parameter('value', 'int')) procedure.add_modifies('set') procedure.set_implementation('set[value] := false;') spec.add_procedure(procedure) gteq = Function('gteq', 5) gteq.add_param(Parameter('one', '[int]bool')) gteq.add_param(Parameter('two', '[int]bool')) gteq.set_return('bool') spec.set_gteq(gteq) spec.set_preface( 'var set:[int]bool;\n//@gteq\nfunction gteq(set1:[int]bool, set2:[int]bool) returns(bool)\n{(forall i:int :: set2[i] ==> set1[i])}' ) checker = ConvergenceChecker() with pytest.raises(ConvergenceError): checker.check_monotonicity(spec, procedure)
def test_check_lub(self): spec = Specification('sample') spec.add_variable(Variable('set', '[int]bool', 1)) procedure = Procedure('merge_6', 15) procedure.add_parameter(Parameter('set1', '[int]bool')) procedure.add_modifies('set') procedure.add_ensures( '(forall i:int :: set[i] == (old(set)[i] || set1[i]))') procedure.set_implementation('assume false;') spec.set_merge(procedure) gteq = Function('gteq', 5) gteq.add_param(Parameter('set1', '[int]bool')) gteq.add_param(Parameter('set2', '[int]bool')) gteq.set_return('bool') spec.set_gteq(gteq) spec.set_preface( 'var set:[int]bool;\n//@gteq\nfunction gteq(set1:[int]bool, set2:[int]bool) returns(bool)\n{(forall i:int :: set2[i] ==> set1[i])}' ) checker = ConvergenceChecker() assert checker.check_lub(spec) == True
def test_stable_pair(self): spec = Specification('sample') spec.add_variable(Variable('counter', 'int', 1)) procedure = Procedure('inc', 15) procedure.add_parameter(Parameter('value', 'int')) procedure.add_modifies('counter') procedure.add_requires('value > 0') procedure.set_implementation('counter := counter + value;') spec.add_procedure(procedure) merge = Procedure('merge', 15) merge.add_parameter(Parameter('counter1', 'int')) merge.add_modifies('counter') merge.set_implementation('counter := (if counter1 > counter then counter1 else counter);') spec.set_merge(merge) invariant = Function('inv', 10) invariant.add_param(Parameter('counter', 'int')) invariant.set_return('bool') spec.set_invariant(invariant) spec.set_preface('var counter :int;\n//@invariant\nfunction inv(counter:int) returns(bool)\n{\n counter >= 0\n}') checker = SafetyChecker() assert checker.check_stability(spec, procedure) == True
def test_unsafe_proc(self): spec = Specification('sample') spec.add_variable(Variable('counter', 'int', 1)) procedure = Procedure('dec', 15) procedure.add_parameter(Parameter('value', 'int')) procedure.add_modifies('counter') procedure.set_implementation('counter := counter - value;') spec.add_procedure(procedure) merge = Procedure('merge', 15) merge.add_parameter(Parameter('counter1', 'int')) merge.add_modifies('counter') merge.set_implementation('counter := (if counter1 > counter then counter1 else counter);') spec.set_merge(merge) invariant = Function('inv', 10) invariant.add_param(Parameter('counter', 'int')) invariant.set_return('bool') spec.set_invariant(invariant) spec.set_preface('var counter :int;\n//@invariant\nfunction inv(counter:int) returns(bool)\n{\n counter >= 0\n}') checker = SafetyChecker() with pytest.raises(SafetyError): checker.check_safety(spec, procedure)
def test_check_monotonicity(self): spec = Specification('sample') spec.add_variable(Variable('set', '[int]bool', 1)) procedure = Procedure('add', 15) procedure.add_parameter(Parameter('value', 'int')) procedure.add_modifies('set') procedure.add_ensures( '(forall i:int :: (i == value ==> set[i] == true) && (i != value ==> set[i] == old(set)[i]))' ) procedure.set_implementation('set[value] := true;') spec.add_procedure(procedure) gteq = Function('gteq', 5) gteq.add_param(Parameter('set1', '[int]bool')) gteq.add_param(Parameter('set2', '[int]bool')) gteq.set_return('bool') spec.set_gteq(gteq) spec.set_preface( 'var set:[int]bool;\n//@gteq\nfunction gteq(set1:[int]bool, set2:[int]bool) returns(bool)\n{(forall i:int :: set2[i] ==> set1[i])}' ) checker = ConvergenceChecker() assert checker.check_monotonicity(spec, procedure) == True