expexp
Version:
The express model io and express model and data representation.
291 lines (254 loc) • 8.99 kB
JavaScript
import ist from 'ist'
import stringify from 'json-stable-stringify'
import {ModelDeserializer, Model} from '../dist/index.cjs'
import fs from 'fs'
import {loadCases, genCaseInfo, resolveElement} from './mniHelper.js'
function apply(name, inputStr, resScenarioJson) {
// Remind: resScenarioJson is in old format.
const atrTypToOldFmt = function(t) {
switch (t) {
case 'atr_dcl':
return 'attr'
case 'whr':
return 'where'
case 'inv':
return 'inverse'
case 'drv':
return 'derive'
case 'prm_dcl':
return 'type_param'
case 'fun':
return 'func'
case 'lcl_dcl':
return 'local_var'
}
return t
}
const psr = ModelDeserializer()
const isRawJson = psr.syntaxJsonFromString(inputStr)
// Remind: isRawJson is new format.
//console.log('raw', name, isRawJson)
// TODO how to test validation errors
const shdNttId2Order = {}
for (let rdr of resScenarioJson.entityEvalOrders) {
shdNttId2Order[rdr.id] = rdr.order
}
const shdFuncId2Order = {}
for (let rdr of resScenarioJson.functionEvalOrders) {
shdFuncId2Order[rdr.id] = rdr.order
}
const id1stOf = function(elt) {
let id = elt.id // may be undefined
if (id == undefined) {
if (elt.ids.t) { // new is format
id = elt.ids.s[0]
} else { // old shd format
id = elt.ids[0]
}
}
if (typeof id === 'object') {
return id.id
} else {
return id
}
}
const mdl = Model(isRawJson)
const id2name = function(id) {
return mdl.schemaId() + '.' + id.toUpperCase()
}
for (let shd of resScenarioJson.types) {
const has = mdl.hasType(id2name(shd.id))
ist(has)
if (has) {
const is = mdl.typeById(id2name(shd.id))
// Just compare the id of what is returned.
ist(is.id, shd.id)
// const isStr = stringify(is)
// const shouldStr = stringify(shd)
// ist(isStr, shouldStr)
}
}
for (let shd of resScenarioJson.entities) {
const has = mdl.hasEntity(id2name(shd.id))
ist(has)
if (has) {
const is = mdl.entityById(id2name(shd.id))
// Just compare the id of what is returned.
ist(is.id, shd.id)
// const isStr = stringify(is)
// const shouldStr = stringify(shd)
// ist(isStr, shouldStr)
// if (shd.id == 'NttWoInheritence') {
// const evalOrder = mdl.nttEvalOrder(shd.id)
// // TODO validate that order
// if (evalOrder.elements) {
// console.log(shd.id)
// evalOrder.elements.forEach(function(elt){console.log(elt)})
// } else {
// console.log(evalOrder.message)
// }
// }
const shdOrder = shdNttId2Order[shd.id]
const isOrder = mdl.nttEvalOrder(id2name(shd.id))
if (Array.isArray(shdOrder)) { // test order specified
ist( // TODO Is there no other way to tag the test with the shd.id
`Entity ${shd.id} has order is ${isOrder.result}.`,
`Entity ${shd.id} has order is true.`
)
ist( // TODO Is there no other way to tag the test with the shd.id
`Order length of ${shd.id} is ${isOrder.elements.length}.`,
`Order length of ${shd.id} is ${shdOrder.length}.`
)
if (isOrder.elements.length == shdOrder.length) {
for (let i = 0; i<shdOrder.length; i++) {
const isElt = isOrder.elements[i]
// console.log('')
// console.log(isElt.id, isElt.ids)
// isOrder.dependencies[i].forEach(function(d){console.log(d)})
const isType = atrTypToOldFmt(isElt.t)
const shdElt = shdOrder[i]
const strNttOrderNth = `The ${i}th element of entity ${shd.id}'s order`
ist(
`${strNttOrderNth} has type ${isType}.`,
`${strNttOrderNth} has type ${shdElt.t}.`
)
// console.log('<>')
// console.log(isElt)
// console.log(shdElt)
ist(
`${strNttOrderNth} first id is ${id1stOf(isElt)}.`,
`${strNttOrderNth} first id is ${id1stOf(shdElt)}.`
)
}
}
} else if (typeof shdOrder == 'string') {
// Test failing
ist( // TODO Is there no other way to tag the test with the shd.id
`Entity ${shd.id} has order is ${isOrder.result}.`,
`Entity ${shd.id} has order is false.`
)
ist( // TODO Is there no other way to tag the test with the shd.id
`Entity ${shd.id} has circle in order is ${isOrder.result == false}.`,
`Entity ${shd.id} has circle in order is true.`
)
if (isOrder.message) {
ist( // TODO Is there no other way to tag the test with the shd.id
`Entity ${shd.id} has circle in order with ${shdOrder} is ${isOrder.message.includes(shdOrder)}.`,
`Entity ${shd.id} has circle in order with ${shdOrder} is true.`
)
}
} // else (missing) no test specified
}
}
for (let shd of resScenarioJson.functions) {
const has = mdl.hasFunction(id2name(shd.id))
ist(has)
if (has) {
const is = mdl.functionById(id2name(shd.id))
// Just compare the id of what is returned.
ist(is.id, shd.id)
// const isStr = stringify(is)
// const shouldStr = stringify(shd)
// ist(isStr, shouldStr)
const shdOrder = shdFuncId2Order[shd.id]
const isOrder = mdl.funcEvalOrder(id2name(shd.id))
if (Array.isArray(shdOrder)) { // test order specified
ist( // TODO Is there no other way to tag the test with the shd.id
`Function ${shd.id} has order is ${isOrder.result}.`,
`Function ${shd.id} has order is true.`
)
ist( // TODO Is there no other way to tag the test with the shd.id
`Order length of ${shd.id} is ${isOrder.elements.length}.`,
`Order length of ${shd.id} is ${shdOrder.length}.`
)
if (isOrder.elements.length == shdOrder.length) {
for (let i = 0; i<shdOrder.length; i++) {
const isElt = isOrder.elements[i]
// console.log('')
// console.log(isElt.id, isElt.ids)
// isOrder.dependencies[i].forEach(function(d){console.log(d)})
const isType = atrTypToOldFmt(isElt.t)
const shdElt = shdOrder[i]
const strNttOrderNth = `The ${i}th element of function ${shd.id}'s order`
ist(
`${strNttOrderNth} has type ${isType}.`,
`${strNttOrderNth} has type ${shdElt.t}.`
)
ist(
`${strNttOrderNth} first id is ${id1stOf(isElt)}.`,
`${strNttOrderNth} first id is ${id1stOf(shdElt)}.`
)
}
}
} else if (typeof shdOrder == 'string') {
// Test failing
ist( // TODO Is there no other way to tag the test with the shd.id
`Function ${shd.id} has order is ${isOrder.result}.`,
`Function ${shd.id} has order is false.`
)
ist( // TODO Is there no other way to tag the test with the shd.id
`Function ${shd.id} has circle in order is ${isOrder.result == false}.`,
`Function ${shd.id} has circle in order is true.`
)
if (isOrder.message) {
ist( // TODO Is there no other way to tag the test with the shd.id
`Function ${shd.id} has circle in order with ${shdOrder} is ${isOrder.message.includes(shdOrder)}.`,
`Function ${shd.id} has circle in order with ${shdOrder} is true.`
)
}
} // else (missing) no test specified
}
}
// TODO procs
}
function applyCase(cInfo) {
const xpl = fs.readFileSync(cInfo.xpl, 'utf8')
const jsonStr = fs.readFileSync(cInfo.json, 'utf8')
// console.log(jsonStr)
const json = JSON.parse(jsonStr)
json.types = resolveElement(json.types)
json.entities = resolveElement(json.entities)
json.functions = resolveElement(json.functions)
json.procedures = resolveElement(json.procedures)
// console.log('json', json)
apply(cInfo.name, xpl, json)
}
function testCase(dirName, caseName) {
const ci = genCaseInfo(dirName, caseName)
// The json format must be scenario not single case.
it(`The ${ci.name} model is created correctly.`, () => {
applyCase(ci)
})
}
function testCases(dirName) {
const cases = loadCases(dirName)
for (let i = 0; i<cases.length; i++) {
const ci = cases[i]
// if (ci.name != 'NttWithSimpleAttrs') continue // uncomment for focus testing
it(`The ${ci.name} model is created correctly.`, () => {
applyCase(ci)
})
}
}
describe("Model", () => {
context("The attributes functions are present.", () => {
testCases('mniScenarios')
// testCase('mniScenarios', 'usersAndRelated')
// it(`It is as it is.`, () => {
// ist('TODO', 'TODO')
// })
})
// TODO coverage hints:
// model.js entityIdChainById function
// model.js resolveType function .. if (ref.id in nttId2Ntt)
// model.js resolveType function .. } else { // type.spec.t == 'select'
// model.js functionById, procById und ruleById
// model.js nttSuperChainById function .. while body
// model.js typeSpecChainById function .. while else case throwing
// TODO use typeInheritChains and entityInheritChains to test ...
// TODO use scenario's enitiyCompleteAttrs to test fullAttrListById
// TODO change the format of entityCompleteAttrs for NttDevice can have SELF\NttThing.isGood omitted
// TODO use TODO (containing a select type; with an invalid reference) to test possibleTypesOfRef
// More future todos:
// TODO do WHERE tests of TpIntegerGreaterThanZero and TpHhMmSsMx
})