mbeckerle commented on a change in pull request #129: Cross Testing Capability with IBM DFDL URL: https://github.com/apache/incubator-daffodil/pull/129#discussion_r234380239
########## File path: daffodil-tdml/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala ########## @@ -437,69 +449,121 @@ abstract class TestCase(testCaseXML: NodeSeq, val parent: DFDLTestSuite) lazy val defaultRoundTrip: RoundTrip = parent.defaultRoundTrip lazy val defaultValidation: String = parent.defaultValidation - /** - * This doesn't fetch a serialized processor, it runs whatever the processor is - * through a serialize then unserialize path to get a processor as if - * it were being fetched from a file. - */ - private def generateProcessor(pf: DFDL.ProcessorFactory, useSerializedProcessor: Boolean): DFDLTestSuite.CompileResult = { - val p = pf.onPath("/") - val diags = p.getDiagnostics - if (p.isError) Left(diags) - else { - val dp = - if (useSerializedProcessor) { - val os = new java.io.ByteArrayOutputStream() - val output = Channels.newChannel(os) - p.save(output) + private lazy val defaultImplementations: Seq[String] = parent.defaultImplementations + private lazy val tcImplementations = (testCaseXML \ "@implementations").text + private lazy val implementationStrings = + if (tcImplementations == "") defaultImplementations + else tcImplementations.split("""\s+""").toSeq - val is = new java.io.ByteArrayInputStream(os.toByteArray) - val input = Channels.newChannel(is) - val compiler_ = Compiler() - compiler_.reload(input) - } else p - - Right((diags, dp)) + lazy val implementations: Seq[TDMLDFDLProcessorFactory] = { + // + // just by way of eating our own dogfood, we're always going to dynaload the + // processor, even for the built-in Daffodil one. + // + lazy val dafpfs = dynamicLoadTDMLProcessorFactory(Runner.daffodilTDMLDFDLProcessorFactoryName) + val allImpls = { + if (parent.optDebugger.isDefined) + dafpfs // when debugging or tracing, we only run daffodil, ignore other implementations + else { + implementationStrings.flatMap { s => + s.toLowerCase match { + // + // When adding another processor implementation to a test case + // you can also use daffodil by just specifying implementations="daffodil otherOne.full.class.name" + // That is, you don't have to use a class name for daffodil. + case "daffodil" => dafpfs + case _ => dynamicLoadTDMLProcessorFactory(s) + } + } + } } + allImpls.foreach { + _.setValidateDFDLSchemas(parent.validateDFDLSchemas) + } + if (allImpls.isEmpty) throw new TDMLException("No TDML DFDL implementations found for '%s'".format(implementationStrings.mkString(", "))) + allImpls } - private def compileProcessor(schemaSource: DaffodilSchemaSource, useSerializedProcessor: Boolean): DFDLTestSuite.CompileResult = { - val pf = compiler.compileSource(schemaSource) - val diags = pf.getDiagnostics - if (pf.isError) { - Left(diags) // throw new TDMLException(diags) - } else { - val res = this.generateProcessor(pf, useSerializedProcessor) - res - } + private lazy val tdmlDFDLProcessorFactoryTraitName = { + import scala.language.reflectiveCalls + // Doing this so that if we decide to rename the verbose class name here + // it will handle this code too. + // Also we can rename the packages, etc. + val clazzTag = scala.reflect.classTag[TDMLDFDLProcessorFactory] + val cname = clazzTag.toString() + cname } - final protected def getProcessor(schemaSource: DaffodilSchemaSource, useSerializedProcessor: Boolean): DFDLTestSuite.CompileResult = { - val res: DFDLTestSuite.CompileResult = schemaSource match { - case uss: URISchemaSource => - SchemaDataProcessorCache.compileAndCache(uss, useSerializedProcessor, - parent.checkAllTopLevel, - root, - null) { - compileProcessor(uss, useSerializedProcessor) - } - case _ => { - compileProcessor(schemaSource, useSerializedProcessor) + def dynamicLoadTDMLProcessorFactory(className: String): Seq[TDMLDFDLProcessorFactory] = { + import scala.language.reflectiveCalls + import scala.language.existentials + + val res = + try { + Seq(Class.forName(className).newInstance().asInstanceOf[TDMLDFDLProcessorFactory]) + } catch { + case cnf: ClassNotFoundException => + System.err.println("TDML Runner did not find implementation '%s'. No tests will be run against it.".format(className)) + Seq() + case ie: InstantiationException => { + // + // In this case, we found it, but we couldn't create an instance of it, so it's somehow broken, + // but there's no point in trying to use it. + // + System.err.println("TDML Runner found implementation '%s'. But was unable to create an instance. No tests will be run against it.".format(className)) + Seq() + } + case cce: ClassCastException => { + // + // In this case, we found it, created an instance, but it's not the right type. + // So there's no point in trying to use it. + // + System.err.println("TDML Runner found implementation '%s'. But it was not an instance of %s. No tests will be run against it.".format( + className, tdmlDFDLProcessorFactoryTraitName + )) + Seq() + } Review comment: This is reimplemented now along the lines of your original comment. No change to scala vs. scala-debug though. This patch set is already super huge. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services