|
| 1 | +package viper.silver.testing |
| 2 | + |
| 3 | +import org.scalatest.{BeforeAndAfterAllConfigMap, ConfigMap, FunSuite, Matchers} |
| 4 | +import viper.silver.ast.{AnySetContains, Assert, EqCmp, Exp, Field, FieldAccess, FieldAccessPredicate, FullPerm, Function, Inhale, IntLit, LocalVarAssign, LocalVarDecl, Method, Program, Ref, Result, BackendFuncApp, Seqn, SetType, Stmt} |
| 5 | +import viper.silver.ast.utility.{BVFactory, FloatFactory, RoundingMode} |
| 6 | +import viper.silver.verifier.{Failure, Success, Verifier} |
| 7 | +import viper.silver.verifier.errors.{AssertFailed, PostconditionViolated} |
| 8 | + |
| 9 | +trait BackendTypeTest extends FunSuite with Matchers with BeforeAndAfterAllConfigMap { |
| 10 | + |
| 11 | + def generateTypeCombinationTest(success: Boolean) : (Program, Assert) = { |
| 12 | + val t = if (success) BVFactory(23).typ else FloatFactory(23, 11, RoundingMode.RNE).typ |
| 13 | + val p1_decl = LocalVarDecl("three", t)() |
| 14 | + val p1_ref = p1_decl.localVar |
| 15 | + val p2_decl = LocalVarDecl("lol", SetType(t))() |
| 16 | + val p2_ref= p2_decl.localVar |
| 17 | + val element_in_param = AnySetContains(p1_ref, p2_ref)() |
| 18 | + |
| 19 | + val assume = Inhale(element_in_param)() |
| 20 | + val assert = Assert(element_in_param)() |
| 21 | + val body = if (success) Seq(assume, assert) else Seq(assert) |
| 22 | + (wrapInProgram(body, Seq(p1_decl, p2_decl), Seq()), assert) |
| 23 | + } |
| 24 | + |
| 25 | + def generateFieldTypeTest(success: Boolean) : (Program, Assert) = { |
| 26 | + val t = if (!success) BVFactory(23).typ else FloatFactory(23, 11, RoundingMode.RNE).typ |
| 27 | + val field = Field("f", t)() |
| 28 | + val p1_decl = LocalVarDecl("three", Ref)() |
| 29 | + val p1_ref = p1_decl.localVar |
| 30 | + val p2_decl = LocalVarDecl("lol", SetType(t))() |
| 31 | + val p2_ref= p2_decl.localVar |
| 32 | + val fieldAcc = FieldAccess(p1_ref, field)() |
| 33 | + val perm = FieldAccessPredicate(fieldAcc, FullPerm()())() |
| 34 | + val element_in_param = AnySetContains(fieldAcc, p2_ref)() |
| 35 | + |
| 36 | + val getPerm = Inhale(perm)() |
| 37 | + val assume = Inhale(element_in_param)() |
| 38 | + val assert = Assert(element_in_param)() |
| 39 | + val body = if (success) Seq(getPerm, assume, assert) else Seq(getPerm, assert) |
| 40 | + (wrapInProgram(body, Seq(p1_decl, p2_decl), Seq(), fields = Seq(field)), assert) |
| 41 | + } |
| 42 | + |
| 43 | + def generateFloatOpTest(success: Boolean) : (Program, Assert) = { |
| 44 | + val rne = RoundingMode.RNE |
| 45 | + val fp = FloatFactory(24, 8, rne) |
| 46 | + val first = 1081081856 // 3.75 |
| 47 | + val second = 1103888384 // 25.5 |
| 48 | + val result = 1105854464 // 29.25 |
| 49 | + val bv32 = BVFactory(32) |
| 50 | + val from_int = bv32.from_int("toBV32") |
| 51 | + val to_fp = fp.from_bv("tofp") |
| 52 | + val fp_eq = fp.eq("fp_eq") |
| 53 | + val fp_add = fp.add("fp_add") |
| 54 | + |
| 55 | + val first_float = BackendFuncApp(to_fp, Seq(BackendFuncApp(from_int, Seq(IntLit(first)()))()))() |
| 56 | + val second_float = BackendFuncApp(to_fp, Seq(BackendFuncApp(from_int, Seq(IntLit(second)()))()))() |
| 57 | + val result_float = BackendFuncApp(to_fp, Seq(BackendFuncApp(from_int, Seq(IntLit(result)()))()))() |
| 58 | + |
| 59 | + val zero_float = BackendFuncApp(to_fp, Seq(BackendFuncApp(from_int, Seq(IntLit(0)()))()))() |
| 60 | + |
| 61 | + val addition = BackendFuncApp(fp_add, Seq(first_float, second_float))() |
| 62 | + val result_addition = BackendFuncApp(fp_add, Seq(result_float, if (success) zero_float else first_float))() |
| 63 | + |
| 64 | + val equality = BackendFuncApp(fp_eq, Seq(addition, result_addition))() |
| 65 | + val assert = Assert(equality)() |
| 66 | + (wrapInProgram(Seq(assert), Seq(), Seq()), assert) |
| 67 | + } |
| 68 | + |
| 69 | + def generateFloatOpFunctionTest(success: Boolean) : (Program, Function, Exp) = { |
| 70 | + val rne = RoundingMode.RNE |
| 71 | + val fp = FloatFactory(24, 8, rne) |
| 72 | + val first = 1081081856 // 3.75 |
| 73 | + val second = 1103888384 // 25.5 |
| 74 | + val result = 1105854464 // 29.25 |
| 75 | + val bv32 = BVFactory(32) |
| 76 | + val from_int = bv32.from_int("toBV32") |
| 77 | + val to_fp = fp.from_bv("tofp") |
| 78 | + val fp_eq = fp.eq("fp_eq") |
| 79 | + val fp_add = fp.add("fp_add") |
| 80 | + |
| 81 | + val first_float = BackendFuncApp(to_fp, Seq(BackendFuncApp(from_int, Seq(IntLit(first)()))()))() |
| 82 | + val second_float = BackendFuncApp(to_fp, Seq(BackendFuncApp(from_int, Seq(IntLit(second)()))()))() |
| 83 | + val result_float = BackendFuncApp(to_fp, Seq(BackendFuncApp(from_int, Seq(IntLit(result)()))()))() |
| 84 | + |
| 85 | + val zero_float = BackendFuncApp(to_fp, Seq(BackendFuncApp(from_int, Seq(IntLit(0)()))()))() |
| 86 | + |
| 87 | + val addition = BackendFuncApp(fp_add, Seq(first_float, second_float))() |
| 88 | + val result_addition = BackendFuncApp(fp_add, Seq(result_float, if (success) zero_float else first_float))() |
| 89 | + |
| 90 | + val equality = BackendFuncApp(fp_eq, Seq(Result(fp.typ)(), result_addition))() |
| 91 | + |
| 92 | + val fun = Function("test", Seq(), fp.typ, Seq(), Seq(equality), Some(addition))() |
| 93 | + val program = Program(Seq(), Seq(), Seq(fun), Seq(), Seq(), Seq())() |
| 94 | + (program, fun, equality) |
| 95 | + } |
| 96 | + |
| 97 | + def generateBvOpTest(success: Boolean) : (Program, Assert) = { |
| 98 | + val bv23 = BVFactory(23) |
| 99 | + val from_int = bv23.from_int("toBV23") |
| 100 | + val two_lit = IntLit(2)() |
| 101 | + val three_lit = IntLit(3)() |
| 102 | + val one_lit = IntLit(1) () |
| 103 | + val two = BackendFuncApp(from_int, Seq(two_lit))() |
| 104 | + val three = BackendFuncApp(from_int, Seq(three_lit))() |
| 105 | + val one = BackendFuncApp(from_int, Seq(one_lit))() |
| 106 | + val result_decl = LocalVarDecl("three", bv23.typ)() |
| 107 | + val result_ref = result_decl.localVar |
| 108 | + val assign = LocalVarAssign(result_ref, if (success) three else one)() |
| 109 | + val xor = bv23.xor("xorBV23") |
| 110 | + val xor_app = BackendFuncApp(xor, Seq(one, two))() |
| 111 | + val equality1 = EqCmp(result_ref, xor_app)() |
| 112 | + val assertion1 = Assert(equality1)() |
| 113 | + (wrapInProgram(Seq(assign, assertion1), Seq(), Seq(result_decl)), assertion1) |
| 114 | + } |
| 115 | + |
| 116 | + def wrapInProgram(stmts: Seq[Stmt], params: Seq[LocalVarDecl], vars: Seq[LocalVarDecl], fields: Seq[Field] = Seq()): Program = { |
| 117 | + val block = Seqn(stmts, vars)() |
| 118 | + val method = Method("test", params, Seq(), Seq(), Seq(), Some(block))() |
| 119 | + Program(Seq(), fields, Seq(), Seq(), Seq(method), Seq())() |
| 120 | + } |
| 121 | + |
| 122 | + val verifier : Verifier |
| 123 | + |
| 124 | + override def beforeAll(configMap: ConfigMap) { |
| 125 | + verifier.parseCommandLine(Seq("dummy.vpr")) |
| 126 | + verifier.start() |
| 127 | + } |
| 128 | + |
| 129 | + override def afterAll(configMap: ConfigMap) { |
| 130 | + verifier.stop() |
| 131 | + } |
| 132 | + |
| 133 | + test("typeCombinationSuccess") { |
| 134 | + val (prog, assertNode) = generateTypeCombinationTest(true) |
| 135 | + val res = verifier.verify(prog) |
| 136 | + assert(res == Success) |
| 137 | + } |
| 138 | + |
| 139 | + test("typeCombinationFail") { |
| 140 | + val (prog, assertNode) = generateTypeCombinationTest(false) |
| 141 | + val res = verifier.verify(prog) |
| 142 | + assert(res match { |
| 143 | + case Failure(Seq(AssertFailed(a, _, _))) if a == assertNode => true |
| 144 | + case _ => false |
| 145 | + }) |
| 146 | + } |
| 147 | + |
| 148 | + test("fieldTypeSuccess") { |
| 149 | + val (prog, assertNode) = generateFieldTypeTest(true) |
| 150 | + val res = verifier.verify(prog) |
| 151 | + assert(res == Success) |
| 152 | + } |
| 153 | + |
| 154 | + test("fieldTypeFail") { |
| 155 | + val (prog, assertNode) = generateFieldTypeTest(false) |
| 156 | + val res = verifier.verify(prog) |
| 157 | + assert(res match { |
| 158 | + case Failure(Seq(AssertFailed(a, _, _))) if a == assertNode => true |
| 159 | + case _ => false |
| 160 | + }) |
| 161 | + } |
| 162 | + |
| 163 | + test("bvOpSuccess") { |
| 164 | + val (prog, assertNode) = generateBvOpTest(true) |
| 165 | + val res = verifier.verify(prog) |
| 166 | + assert(res == Success) |
| 167 | + } |
| 168 | + |
| 169 | + test("bvOpFail") { |
| 170 | + val (prog, assertNode) = generateBvOpTest(false) |
| 171 | + val res = verifier.verify(prog) |
| 172 | + assert(res match { |
| 173 | + case Failure(Seq(AssertFailed(a, _, _))) if a == assertNode => true |
| 174 | + case _ => false |
| 175 | + }) |
| 176 | + } |
| 177 | + |
| 178 | + test("floatOpSuccess") { |
| 179 | + val (prog, assertNode) = generateFloatOpTest(true) |
| 180 | + val res = verifier.verify(prog) |
| 181 | + assert(res == Success) |
| 182 | + } |
| 183 | + |
| 184 | + test("floatOpFail") { |
| 185 | + val (prog, assertNode) = generateFloatOpTest(false) |
| 186 | + val res = verifier.verify(prog) |
| 187 | + assert(res match { |
| 188 | + case Failure(Seq(AssertFailed(a, _, _))) if a == assertNode => true |
| 189 | + case _ => false |
| 190 | + }) |
| 191 | + } |
| 192 | + |
| 193 | + test("floatOpFunctionSuccess") { |
| 194 | + val (prog, fun, exp) = generateFloatOpFunctionTest(true) |
| 195 | + val res = verifier.verify(prog) |
| 196 | + assert(res == Success) |
| 197 | + } |
| 198 | + |
| 199 | + test("floatOpFunctionFail") { |
| 200 | + val (prog, fun, exp) = generateFloatOpFunctionTest(false) |
| 201 | + val res = verifier.verify(prog) |
| 202 | + assert(res match { |
| 203 | + case Failure(Seq(PostconditionViolated(e, f, _, _))) if e == exp && fun == f => true |
| 204 | + case _ => false |
| 205 | + }) |
| 206 | + } |
| 207 | + |
| 208 | +} |
0 commit comments