UNPKG

@informalsystems/quint

Version:

Core tool for the Quint specification language

107 lines (104 loc) 5.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const mocha_1 = require("mocha"); const chai_1 = require("chai"); const src_1 = require("../../src"); const NondetChecker_1 = require("../../src/effects/NondetChecker"); const inferrer_1 = require("../../src/types/inferrer"); (0, mocha_1.describe)('checkNondets', () => { function parseAndTypecheck(text) { const idGen = (0, src_1.newIdGenerator)(); const fake_path = { normalizedPath: 'fake_path', toSourceName: () => 'fake_path' }; const { modules, table, errors } = (0, src_1.parse)(idGen, 'fake_location', fake_path, text); chai_1.assert.isEmpty(errors, `Unexpected parse errors: ${[...errors].map(src_1.quintErrorToString)}`); const typeInferrer = new inferrer_1.TypeInferrer(table); const [typeErrors, types] = typeInferrer.inferTypes(modules[0].declarations); chai_1.assert.isEmpty(typeErrors, `Unexpected type errors: ${[...typeErrors.values()].map(src_1.errorTreeToString)}`); return { module: modules[0], table, types }; } (0, mocha_1.it)('returns empty map for effects with no problems', () => { const text = `module A { val a = 1 var x: int action foo = { nondet bar = Set(1,2).oneOf() x' = bar } }`; const { module, table, types } = parseAndTypecheck(text); const errors = new NondetChecker_1.NondetChecker(table).checkNondets(types, module.declarations); chai_1.assert.isEmpty(errors, `Should find no errors, found: ${[...errors.values()].map(src_1.quintErrorToString)}`); }); (0, mocha_1.it)('finds an error when oneOf is used in a val', () => { const text = `module A { val a = Set(1,2).oneOf() }`; const { module, table, types } = parseAndTypecheck(text); const errors = new NondetChecker_1.NondetChecker(table).checkNondets(types, module.declarations); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT203', message: "'oneOf' must be used inside a nondet definition", reference: 4n, data: {} }, ]); }); (0, mocha_1.it)('finds an error when oneOf is not the outermost expression', () => { const text = `module A { var x: int action foo = { nondet bar = Set(1,2).oneOf() + 1 { x' = bar } } }`; const { module, table, types } = parseAndTypecheck(text); const errors = new NondetChecker_1.NondetChecker(table).checkNondets(types, module.declarations); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT204', message: "the outermost expression in a nondet definition must be either 'oneOf' or 'apalache::generate'", reference: 8n, data: {}, }, ]); }); (0, mocha_1.it)('find an error when nondet is a top-level definition', () => { const text = `module A { var x: int nondet top_level = Set(1,2).oneOf() }`; const { module, table, types } = parseAndTypecheck(text); const errors = new NondetChecker_1.NondetChecker(table).checkNondets(types, module.declarations); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT206', message: "'nondet' can only be used inside actions, not at the top level", reference: 7n, data: {}, }, ]); }); (0, mocha_1.it)('finds an error when the scope expression for the nondet binding is not boolean', () => { // FIXME: ideally this should also complain about the top-level def not // being an action. This requires the introduction of a new effect, which is // not trivial. For now, checking for boolean returns should already help a // lot. const text = `module A { // error: nondet bindings can only be used with boolean expressions val non_action = { nondet bar = Set(1,2).oneOf() bar } }`; const { module, table, types } = parseAndTypecheck(text); const errors = new NondetChecker_1.NondetChecker(table).checkNondets(types, module.declarations); chai_1.assert.sameDeepMembers(errors, [ { code: 'QNT205', message: 'nondet bindings can only be used with boolean expressions, but expression has type: int', reference: 7n, data: {}, }, ]); }); (0, mocha_1.it)('can survive missing types and lookup table entries', () => { const text = `module A { var x: int nondet top_level = Set(1,2).oneOf() val non_action = { nondet bar = Set(1,2).oneOf() bar } }`; const { module } = parseAndTypecheck(text); const table = new Map(); const types = new Map(); const errors = new NondetChecker_1.NondetChecker(table).checkNondets(types, module.declarations); chai_1.assert.sameDeepMembers(errors, []); }); }); //# sourceMappingURL=NondetChecker.test.js.map