import AbstractProvenanceProvider from '@cafetextual/util/dist/src/module/AbstractProvenanceProvider'; import GSuiteContext from "./GSuiteContext"; import GTestContext from "./GTestContext"; import IGrammarProvider from "./IGrammarProvider"; import GrammarTestsuiteRunner from "./GrammarTestsuiteRunner"; import { ITypeManifest, SimpleTextContent, IIterator, ArrayIterator, ArchiveDeserializer } from '@cafetextual/util'; import Assert from '@cafetextual/util/dist/src/assert/Assert'; import GrammarTestSuite from '../testsuite/GrammarTestSuite'; import GrammarTest from '../testsuite/GrammarTest'; import ParseResult from '../testsuite/ParseResult'; import GRule, { GImport } from '../parser/grammar/GRule'; import IncrementalParseHelper from '../parser/temp/IncrementalParseHelper'; import MetaGrammarManifest from '../serialize/MetaGrammarManifest'; import STest from '../../../../../testdata/TestHelpers'; import GrammarTestSrc from '../testsuite/GrammarTestSrc'; import SeepGrammar from '../parser/SeepGrammar'; export type ResourceData = {rtype:string, suri:string, data:any} /** * Create a GSuiteContext, while handling all the serializaion, metagrammar parsing, initialization etc * required to set up a suites of grammar tests. * * (Run the tests using GrammarTestsuiteRunner) * * note: - stateless, should just make all mehods static * */ export default class GrammarTestsuiteMgr extends AbstractProvenanceProvider { context:GSuiteContext; parseGrammarLocally:boolean jsonResourcesByURI:{[suri:string]:any} constructor( resources:Array, rawResouces:Array, manifest:ITypeManifest, parseGrammarLocally:boolean = true) { super(); this.parseGrammarLocally = parseGrammarLocally; this.init(resources, rawResouces, manifest, parseGrammarLocally); } rawResourceByDocURI(docURI:string):any { return this.jsonResourcesByURI[docURI]; } getAllTestsuiteRawResoure():Array { var out:Array = [] var r:ResourceData for (var suri in this.jsonResourcesByURI) { r = this.jsonResourcesByURI[suri] if (r.rtype == 'grammar-test') { out.push(r) } } return out } // ----- iniialization private init(resources:Array, rawResouces:Array, manifest:ITypeManifest, parseGrammarLocally:boolean):void { var suiteContext:GSuiteContext = new GSuiteContext(manifest) var resource:any //ResourceDesc var g:SeepGrammar; var testsuites:Array = [] // of GrammarTestSuite this.jsonResourcesByURI = {} for (resource of rawResouces) { this.jsonResourcesByURI[resource.suri] = resource } for (resource of resources) { var type:string = resource.rtype; var suri:string = resource.suri; var data:any = resource.data; if (type == "grammar") { // ambient grammars (ie referenced by uri) g = data as SeepGrammar; g.provUri = suri; var ok:boolean = this.initializeGrammar(g, suiteContext) Assert.assert(ok) suiteContext.registerGrammar(g); console.log(' go grammar ' + suri); } else if (type == "grammar-test") { ts = data as GrammarTestSuite; ts.provUri = suri; testsuites.push(ts) } } var testContexts:Array = []; var ts:GrammarTestSuite for (ts of testsuites) { var testContext:GTestContext = this.initTestSuite(ts, suiteContext, parseGrammarLocally /*parse grammar locally */) } this.context = suiteContext; } addTestsuiteFromSrc(uri:string, src:string):void { var ts:GTestContext = this.parseTestSuite(uri, src, this.context); this.addTestSuite(ts, this.context, this.parseGrammarLocally); } // /** * Resolve and initialze grammar as per test * * * @param parseGrammarLocally - do this when we need * * */ initTestGrammar(gtest:GrammarTest, testContext:GTestContext, parseGrammarLocally:boolean):ParseResult { var g:SeepGrammar var gid:string = gtest.grammarID; var suri:string = gtest.grammarSURI; var parseResult:ParseResult if (gtest.grammarSrc && parseGrammarLocally) { var metaGrammar:SeepGrammar = testContext.getGrammar("grammars/metagrammar/metagrammar.seas"); var r:GRule = metaGrammar.getDefaultRule(); // var parseResult:ParseResult = IncrementalParseHelper.parseContent(r, new SimpleTextContent( gtest.grammarSrc.join('\n') ), testContext ) gtest.grammarParseResult = parseResult; if (!parseResult.ok) { // todo - result error ? return parseResult } } // TODO - possibility to compare AST diffs here parseResult = gtest.grammarParseResult; // <-- recalling this may have ben serialized if (parseResult) { var deserializedGrammar:SeepGrammar = this.deserializeGrammar(parseResult.data, testContext); // --- register by id or suri if (gid) { testContext.registerGrammarById(deserializedGrammar, gid); } else if (suri) { testContext.registerGrammarByUri(deserializedGrammar, suri) } else { Assert.fail(" no grammar regisration mechanism"); } g = deserializedGrammar } else if (suri) { // --- grammar referenced by @[suri] g = testContext.getGrammar(suri); } else if (gid) { // --- referenced by @id g = testContext.grammarById(gid) } else { Assert.fail(" no grammar ") } Assert.assert(g != null); testContext.registerGrammarForTest(g, gtest); return parseResult } // initTestGrammar initTestSuite(ts:GrammarTestSuite, suiteContext:GSuiteContext, parseGrammarLocally:boolean):GTestContext { var testContext:GTestContext = new GTestContext(ts, suiteContext) return this.addTestSuite(testContext, suiteContext, parseGrammarLocally); } // initTestSuite addTestSuite(testContext:GTestContext, suiteContext:GSuiteContext, parseGrammarLocally:boolean):GTestContext { var gtest:GrammarTest for (gtest of testContext.testSuite.tests) { this.initTestGrammar(gtest, testContext, parseGrammarLocally) } suiteContext.addTests(testContext) return testContext; } srcIt(ts:GrammarTestSuite):IIterator { return new ArrayIterator(ts.tests) } private resolveImportGrammar(importDef:GImport, context:IGrammarProvider):SeepGrammar { Assert.assert(importDef.suri != null) var g:SeepGrammar = context.getGrammar(importDef.suri); Assert.assert(g != null); return g; } // resolveImportGrammar private deserializeGrammar(data:any, context:IGrammarProvider):SeepGrammar { var deserializer:ArchiveDeserializer = new ArchiveDeserializer(new MetaGrammarManifest()) STest.stripPs(data, {"__uid":true}); var g:SeepGrammar = (data instanceof SeepGrammar) ? data as SeepGrammar : deserializer.deserialize(data); this.initializeGrammar(g, context); Assert.assert(g.isValid()) return g; } private initializeGrammar(g:SeepGrammar, context:IGrammarProvider):boolean { var imports:Array = g.imports; var allImportedGrammarsInitialized:boolean = true if (imports) { var importDef:GImport // resolve grammars for imports for (importDef of imports) { var requiredGrammarURI:string = importDef.suri var grammarToImport:SeepGrammar = this.resolveImportGrammar(importDef, context) if (!grammarToImport) { Assert.fail(" failed to import grammar @" + requiredGrammarURI ); // + " into gramamr @ return false } importDef.grammar = grammarToImport; if (!grammarToImport.isInit) { allImportedGrammarsInitialized = false; } } } if (!allImportedGrammarsInitialized) { Assert.fail(' dependancies on grammar not quite right'); return false } g.parentManifest = context.getManifest() g.init(); if (!g.isValid()) { Assert.fail(' grammar failed to initialize'); return false } return true; } // parseTestSuite(uri:string, src:string, suiteContext:GSuiteContext):GTestContext { var g:SeepGrammar = this.context.getGrammar("grammars/metagrammar/metagrammar-testsuite.grammar") var rule:GRule = g.getDefaultRule(); var testContext:GTestContext = new GTestContext(null, suiteContext); var result:ParseResult = IncrementalParseHelper.parseContent(rule, new SimpleTextContent(src), testContext ); console.log(' result ' + uri + " : " + result.ok); if (result.ok) { var deserializer:ArchiveDeserializer = new ArchiveDeserializer(new MetaGrammarManifest) var ts:GrammarTestSuite = deserializer.deserialize(result.data); ts.provUri = uri; testContext.testSuite = ts; } else { Assert.fail(); // handle parse/deserialization issues here } return testContext; } // parseTestSuite /** * serializes a list of test suites */ serializeTestsuites():string { var it:IIterator = this.context.it(); var tss:Array = [] while (it.hasNext()) { var ctx:GTestContext = it.next(); var ts:GrammarTestSuite = ctx.testSuite tss.push(ts); } var json:string = JSON.stringify({testsuites:tss},null, " ") console.log(' ---- \n' + json ); return json; } // serializeTestsuites runAllTestSuites(asReference:boolean):void { GrammarTestsuiteRunner.runAllTestSuites(this.context, true); } runTest(ctx:GTestContext, gtest:GrammarTest, src:GrammarTestSrc):ParseResult { var grammar:SeepGrammar = ctx.grammarByTest(gtest) var result = GrammarTestsuiteRunner.runTest(src, grammar, ctx) return result } // runTest parseGrammarToAst(ctx:GTestContext, src:Array ):ParseResult { // retreive metagrammar (recall that it isn't parsed locally) var g:SeepGrammar = this.context.getGrammar('grammars/metagrammar/metagrammar.seas') var r:GRule = g.getRule('grammar') var content:SimpleTextContent= new SimpleTextContent(src.join('\n') ); var out:ParseResult = IncrementalParseHelper.parseContent(r, content) return out; } updateGrammarSrc(ts:GrammarTestSuite, gctx:GTestContext, gtest:GrammarTest, newSrc:Array):ParseResult { gtest.grammarSrc = newSrc var invalidateFutureTests = this.grammarHasfutureDependencis(gctx, gtest) var parseResult = this.initTestGrammar(gtest, gctx, true ) invalidateFutureTests = invalidateFutureTests || this.grammarHasfutureDependencis(gctx, gtest) if (invalidateFutureTests) { Assert.fail(" not implemented") } return parseResult } grammarHasfutureDependencis(gctx:GTestContext, gtest:GrammarTest):boolean { return false } } // class