Skip to content

Commit 2eeb3a8

Browse files
committed
Various cleanups in core TestUtils and FuzzData
Moved TestUtils and FuzzData in core to src/main so FuzzData can be used outside of daffodil proper. Removed unused and trivial methods from TestUtils. Made private all methods possible. We're left with minimum footprint of public methods. Removed dependency on JUnit from TestUtils and FuzzData so they don't have to be in src/test. Tested for and removed a couple of TODOs that are no longer needed. Reducing the number of TODOs and FIXMEs is DAFFODIL-1569. DAFFODIL-2959, DAFFODIL-1569
1 parent 108b2b5 commit 2eeb3a8

28 files changed

+196
-264
lines changed

daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/Conversions.scala

+3-4
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,11 @@ object Conversion {
280280
// case (AnyAtomic, Date) => AnyAtomicToString +: conversionOps(String, tt, context)
281281
// case (AnyAtomic, DateTime) => AnyAtomicToString +: conversionOps(String, tt, context)
282282

283-
// TODO: Is this a valid solution for DFDL-1074 and the like?
284-
// Essentially, all of the 'types' should fall under AnyAtomic and there
285-
// is no need to conver to an AnyAtomic. So anything converted to AnyAtomic
283+
// All of the 'types' should fall under AnyAtomic and there
284+
// is no need to convert to an AnyAtomic. So anything converted to AnyAtomic
286285
// should be itself.
287286
//
288-
case (_, AnyAtomic) => Nil // is this correct?
287+
case (_, AnyAtomic) => Nil
289288

290289
case (_, Exists) => Nil
291290
case (_, other) => {

daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/Expression.scala

+1-5
Original file line numberDiff line numberDiff line change
@@ -2836,14 +2836,10 @@ case class XSConverterExpr(
28362836
override def targetTypeForSubexpression(childExpr: Expression): NodeInfo.Kind =
28372837
resultType // NodeInfo.AnyType
28382838

2839-
// TODO: this should work... why do we need to call an additional converter. The
2840-
// args(0).compiledDPath should already have taken into account converting into
2841-
// their target types which are the same as this conversion's output result type.
2842-
28432839
override lazy val compiledDPath = {
28442840
checkArgCount(1)
28452841
val arg0Recipe = args(0).compiledDPath
2846-
val c = conversions
2842+
val c = conversions // additional final conversions are added
28472843
val res = new CompiledDPath(arg0Recipe.ops.toList ++ c)
28482844
res
28492845
}

daffodil-core/src/test/scala/org/apache/daffodil/core/util/FuzzData.scala daffodil-core/src/main/scala/org/apache/daffodil/core/util/FuzzData.scala

+4-5
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,12 @@ import scala.util.Random
2222
import scala.xml.Elem
2323
import scala.xml.Node
2424

25-
import org.apache.daffodil.core.util.TestUtils.getAMessage
2625
import org.apache.daffodil.lib.exceptions.Assert
26+
import org.apache.daffodil.lib.util.Misc.getAMessage
27+
import org.apache.daffodil.lib.xml.XMLUtils
2728
import org.apache.daffodil.lib.xml.XMLUtils.XMLDifferenceException
2829
import org.apache.daffodil.runtime1.processors.parsers.ParseError
2930

30-
import org.junit.Assert.fail
31-
3231
/**
3332
* Utility base class to support fuzz testing. Given a piece of data,
3433
* it fuzzes it (without modifying the original data) each time next() is
@@ -187,7 +186,7 @@ class FuzzParseTester(
187186
}
188187
if (pr ne null) {
189188
try {
190-
TestUtils.assertEqualsXMLElements(expected, node)
189+
XMLUtils.compareAndReport(expected, node)
191190
} catch {
192191
case e: XMLDifferenceException =>
193192
handleUnexpectedSuccess(node, testData, e)
@@ -230,6 +229,6 @@ class LayerParseTester(
230229
if (okParses.size > 0)
231230
println(s"Parse succeeded on fuzzed data ${okParses.size} times.")
232231
if (shouldFail)
233-
fail("errors were found")
232+
throw new AssertionError("errors were found")
234233
}
235234
}

daffodil-core/src/test/scala/org/apache/daffodil/core/util/TestUtils.scala daffodil-core/src/main/scala/org/apache/daffodil/core/util/TestUtils.scala

+44-140
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,23 @@
1818
package org.apache.daffodil.core.util
1919

2020
import java.io.ByteArrayInputStream
21-
import java.io.File
22-
import java.io.FileNotFoundException
2321
import java.io.InputStream
2422
import java.nio.channels.Channels
2523
import java.nio.channels.ReadableByteChannel
2624
import java.nio.channels.WritableByteChannel
27-
import java.nio.file.Paths
2825
import scala.collection.mutable.ArrayBuffer
2926
import scala.util.Try
3027
import scala.xml._
3128

3229
import org.apache.daffodil.core.compiler.Compiler
30+
import org.apache.daffodil.core.compiler.ProcessorFactory
3331
import org.apache.daffodil.core.dsom._
3432
import org.apache.daffodil.io.InputSourceDataInputStream
3533
import org.apache.daffodil.lib.Implicits._
3634
import org.apache.daffodil.lib.api._
35+
import org.apache.daffodil.lib.exceptions.MultiException
3736
import org.apache.daffodil.lib.externalvars.Binding
3837
import org.apache.daffodil.lib.util._
39-
import org.apache.daffodil.lib.xml.XMLUtils
4038
import org.apache.daffodil.lib.xml._
4139
import org.apache.daffodil.runtime1.api.DFDL
4240
import org.apache.daffodil.runtime1.api.MetadataHandler
@@ -48,9 +46,6 @@ import org.apache.daffodil.runtime1.infoset.ScalaXMLInfosetOutputter
4846
import org.apache.daffodil.runtime1.processors.DataProcessor
4947
import org.apache.daffodil.runtime1.processors.VariableMap
5048

51-
import org.apache.commons.io.output.NullOutputStream
52-
import org.junit.Assert.assertEquals
53-
5449
object INoWarnU2 { ImplicitsSuppressUnusedImportWarning() }
5550

5651
/*
@@ -60,31 +55,8 @@ object INoWarnU2 { ImplicitsSuppressUnusedImportWarning() }
6055
*/
6156
object TestUtils {
6257

63-
/**
64-
* Compares two XML Elements, after having (optionally) stripped off all attributes.
65-
*/
66-
def assertEqualsXMLElements(expected: Node, actual: Node): Unit = {
67-
XMLUtils.compareAndReport(expected, actual)
68-
}
69-
70-
/**
71-
* We want to be able to run tests from Eclipse or from batch builds that
72-
* are rooted in a different directory, so, since Java/JVMs don't have a notion
73-
* of setting the current directory to a specific value for interpreting things,
74-
* we have to do that ourselves manually like this.
75-
*
76-
* When you specify a file for use in a test, you want to specify it
77-
* relative to the root of the sub-project of which it is part. I.e., within core,
78-
* the file you specify should be relative to daffodil/sub-projects/core.
79-
*
80-
* Returns null if the file cannot be found.
81-
*/
82-
def findFile(fn: String): File = findFile(new File(fn))
83-
def findFile(f: File): File = {
84-
if (f.exists()) return f
85-
val cwd = new File("").getAbsolutePath
86-
throw new FileNotFoundException("Couldn't find file " + f + " relative to " + cwd + ".")
87-
}
58+
def assertEquals[T](expected: T, actual: T) =
59+
if (expected != actual) throw new AssertionError("assertEquals failed.")
8860

8961
def testString(testSchema: Node, data: String, areTracing: Boolean = false) = {
9062
runSchemaOnRBC(testSchema, Misc.stringToReadableByteChannel(data), areTracing)
@@ -108,11 +80,7 @@ object TestUtils {
10880
runSchemaOnRBC(testSchema, rbc, areTracing)
10981
}
11082

111-
def testFile(testSchema: Node, fileName: String) = {
112-
runSchemaOnRBC(testSchema, Misc.fileToReadableByteChannel(new java.io.File(fileName)))
113-
}
114-
115-
val useSerializedProcessor = true
83+
private val useSerializedProcessor = true
11684

11785
def testUnparsing(
11886
testSchema: scala.xml.Elem,
@@ -122,25 +90,17 @@ object TestUtils {
12290
): Seq[Diagnostic] = {
12391
val compiler = Compiler().withTunable("allowExternalPathExpressions", "true")
12492
val pf = compiler.compileNode(testSchema)
125-
if (pf.isError) {
126-
val msgs = pf.getDiagnostics.map(_.getMessage()).mkString("\n")
127-
throw new Exception(msgs)
128-
}
93+
if (pf.isError) throwDiagnostics(pf.getDiagnostics)
12994
var u = saveAndReload(pf.onPath("/").asInstanceOf[DataProcessor])
130-
if (u.isError) {
131-
val msgs = u.getDiagnostics.map(_.getMessage()).mkString("\n")
132-
throw new Exception(msgs)
133-
}
95+
if (u.isError) throwDiagnostics(u.getDiagnostics)
13496
val outputStream = new java.io.ByteArrayOutputStream()
13597
val out = java.nio.channels.Channels.newChannel(outputStream)
13698
u = if (areTracing) {
13799
u.withDebugger(builtInTracer).withDebugging(true)
138100
} else u
139101
val inputter = new ScalaXMLInfosetInputter(infosetXML)
140102
val actual = u.unparse(inputter, out)
141-
if (actual.isProcessingError) {
142-
throwDiagnostics(actual.getDiagnostics)
143-
}
103+
if (actual.isProcessingError) throwDiagnostics(actual.getDiagnostics)
144104
val unparsed = outputStream.toString
145105
// System.err.println("parsed: " + infoset)
146106
// System.err.println("unparsed: " + unparsed)
@@ -149,12 +109,8 @@ object TestUtils {
149109
actual.getDiagnostics
150110
}
151111

152-
def throwDiagnostics(ds: Seq[Diagnostic]): Unit = {
153-
if (ds.length == 1) throw (ds(0))
154-
else {
155-
val msgs = ds.map(_.getMessage()).mkString("\n")
156-
throw new Exception(msgs)
157-
}
112+
private def throwDiagnostics(ds: Seq[Diagnostic]): Nothing = {
113+
new MultiException(ds).toss
158114
}
159115

160116
def testUnparsingBinary(
@@ -208,30 +164,21 @@ object TestUtils {
208164
def compileSchema(testSchema: Node) = {
209165
val compiler = Compiler()
210166
val pf = compiler.compileNode(testSchema)
211-
val isError = pf.isError
212-
val msgs = pf.getDiagnostics.map(_.getMessage()).mkString("\n")
213-
214-
if (isError) {
215-
throw new Exception(msgs)
216-
}
167+
if (pf.isError) throwDiagnostics(pf.getDiagnostics)
217168
val p = saveAndReload(pf.onPath("/").asInstanceOf[DataProcessor])
218-
val pIsError = p.isError
219-
if (pIsError) {
220-
val msgs = pf.getDiagnostics.map(_.getMessage()).mkString("\n")
221-
throw new Exception(msgs)
222-
}
169+
if (p.isError) throwDiagnostics(p.getDiagnostics)
223170
p
224171
}
225172

226-
def runSchemaOnRBC(
173+
private def runSchemaOnRBC(
227174
testSchema: Node,
228175
data: ReadableByteChannel,
229176
areTracing: Boolean = false
230177
): (DFDL.ParseResult, Node) = {
231178
runSchemaOnInputStream(testSchema, Channels.newInputStream(data), areTracing)
232179
}
233180

234-
def runSchemaOnInputStream(
181+
private def runSchemaOnInputStream(
235182
testSchema: Node,
236183
is: InputStream,
237184
areTracing: Boolean = false
@@ -255,12 +202,7 @@ object TestUtils {
255202
val outputter = new ScalaXMLInfosetOutputter()
256203
val input = InputSourceDataInputStream(is)
257204
val actual = p.parse(input, outputter)
258-
if (actual.isProcessingError) {
259-
val diags = actual.getDiagnostics
260-
if (diags.length == 1) throw diags(0)
261-
val msgs = diags.map(_.getMessage()).mkString("\n")
262-
throw new Exception(msgs)
263-
}
205+
if (actual.isProcessingError) throwDiagnostics(actual.getDiagnostics)
264206
(actual, outputter.getResult)
265207
}
266208

@@ -292,52 +234,16 @@ object TestUtils {
292234
compiler: Compiler,
293235
schemaSource: URISchemaSource,
294236
output: WritableByteChannel
295-
) = {
237+
): Try[(ProcessorFactory, DFDL.DataProcessor)] = {
296238
Try {
297239
val pf = compiler.compileSource(schemaSource)
298-
if (!pf.isError) {
299-
val dp = pf.onPath("/")
300-
dp.save(output)
301-
if (!dp.isError) {
302-
(pf, dp)
303-
} else {
304-
throw new Exception(
305-
(dp.getDiagnostics ++ pf.getDiagnostics).map { _.getMessage() }.mkString("\n")
306-
)
307-
}
308-
} else
309-
throw new Exception(pf.getDiagnostics.map { _.getMessage() }.mkString("\n"))
240+
if (pf.isError) throwDiagnostics(pf.getDiagnostics)
241+
val dp = pf.onPath("/")
242+
dp.save(output)
243+
if (dp.isError) throwDiagnostics(dp.getDiagnostics ++ pf.getDiagnostics)
244+
(pf, dp)
310245
}
311246
}
312-
313-
def testCompileTime(resourcePathString: String): Unit = {
314-
val nos = NullOutputStream.INSTANCE
315-
val nullChannel = java.nio.channels.Channels.newChannel(nos)
316-
val compiler = Compiler()
317-
val uri = Misc.getRequiredResource(resourcePathString)
318-
val schemaSource = URISchemaSource(Paths.get(resourcePathString).toFile, uri)
319-
val theTry = Timer.getResult(compileAndSave(compiler, schemaSource, nullChannel))
320-
theTry.get
321-
}
322-
323-
/**
324-
* Gets some sort of a message from a throwable. Includes messages from all
325-
* classes in the cause chain. If there is no message, just uses the class name.
326-
* @param cause
327-
* @return
328-
*/
329-
def getAMessage(cause: Throwable): String = {
330-
val n1 = Misc.getNameFromClass(cause)
331-
val m = cause.getMessage
332-
val c = cause.getCause
333-
val s = (m, c) match {
334-
case (null, null) => Misc.getNameFromClass(cause)
335-
case (null, c) => getAMessage(c)
336-
case (m, null) => m
337-
case (m, c) => m + " " + getAMessage(c)
338-
}
339-
n1 + s"($s)"
340-
}
341247
}
342248

343249
/**
@@ -397,7 +303,7 @@ class Fakes private () {
397303
lazy val fakeSequenceGroupRef = fs3.asInstanceOf[SequenceGroupRef]
398304
lazy val fakeGroupRefFactory = GroupRefFactory(fs1.xml, fs1, 1, false)
399305

400-
class FakeDataProcessor extends DFDL.DataProcessor {
306+
private class FakeDataProcessor extends DFDL.DataProcessor {
401307
override def save(output: DFDL.Output): Unit = {}
402308
override def parse(
403309
input: InputSourceDataInputStream,
@@ -428,18 +334,15 @@ class Fakes private () {
428334
): DFDL.DaffodilUnparseContentHandler = null
429335

430336
}
431-
lazy val fakeDP = new FakeDataProcessor
337+
lazy val fakeDP: DFDL.DataProcessor = new FakeDataProcessor
432338

433339
}
434340

435341
/**
436342
* Testing class for streaming message parse behavior
437343
*/
438344
object StreamParser {
439-
case class CompileFailure(diags: Seq[Diagnostic])
440-
extends Exception("DFDL Schema Compile Failure") {
441-
override def getMessage() = diags.map { _.toString }.mkString(",\n")
442-
}
345+
case class CompileFailure(diags: Seq[Diagnostic]) extends MultiException(diags)
443346

444347
/**
445348
* Result object for parse calls. Just a tuple.
@@ -473,37 +376,38 @@ object StreamParser {
473376
}
474377
}
475378

476-
def doStreamTest(schema: Node, data: String): Seq[Result] = {
379+
def doStreamTest(schema: Node, data: String): Stream[Result] = {
477380
val mp = new StreamParser(schema)
478381
val is: InputStream = new ByteArrayInputStream(data.getBytes("ascii"))
479382
mp.setInputStream(is)
480383
var r: StreamParser.Result = null
481384
val results = new ArrayBuffer[Result]
482385
val resStream = Stream.continually(mp.parse).takeWhile(r => !r.isProcessingError)
483-
resStream.toSeq
386+
resStream
484387
}
485388
}
486389

487-
class StreamParser(val schema: Node) {
390+
class StreamParser private (val schema: Node) {
391+
392+
private lazy val outputter = new ScalaXMLInfosetOutputter()
393+
private var dis: InputSourceDataInputStream = _
488394

489-
val outputter = new ScalaXMLInfosetOutputter()
490-
var dis: InputSourceDataInputStream = _
491-
var dp: DFDL.DataProcessor = _
492395
//
493396
// First compile the DFDL Schema
494-
val c = Compiler()
495-
val pf = c.compileNode(schema)
496-
val pfDiags = pf.getDiagnostics
497-
if (pf.isError) throw new StreamParser.CompileFailure(pfDiags)
498-
dp = pf
499-
.onPath("/")
500-
.withValidationMode(ValidationMode.Full)
501-
// .withDebuggerRunner(new TraceDebuggerRunner()) // DAFFODIL-2624 - cannot trace in streaming SAPI
502-
// .withDebugging(true)
503-
val dpDiags = dp.getDiagnostics
504-
if (dp.isError) throw new StreamParser.CompileFailure(dpDiags)
505-
val compilationWarnings =
506-
if (!pfDiags.isEmpty) pfDiags else dpDiags // dpDiags might be empty. That's ok.
397+
private lazy val c = Compiler()
398+
private lazy val pf = c.compileNode(schema)
399+
private val dp = {
400+
if (pf.isError) throw new StreamParser.CompileFailure(pf.getDiagnostics)
401+
val dataproc = pf
402+
.onPath("/")
403+
.withValidationMode(ValidationMode.Full)
404+
// .withDebuggerRunner(new TraceDebuggerRunner()) // DAFFODIL-2624 - cannot trace in streaming SAPI
405+
// .withDebugging(true)
406+
if (dataproc.isError) throw new StreamParser.CompileFailure(dataproc.getDiagnostics)
407+
dataproc
408+
}
409+
410+
lazy val compilationWarnings: Seq[Diagnostic] = pf.getDiagnostics ++ dp.getDiagnostics
507411

508412
def setInputStream(inputStream: InputStream): Unit = {
509413
dis = InputSourceDataInputStream(inputStream)

0 commit comments

Comments
 (0)