blob: ce58b7d18b2a5a656bee4563f48ca8d462ed895d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.daffodil.oolag
import org.junit.Assert._
import org.apache.daffodil.oolag.OOLAG._
import org.junit.Test
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.exceptions.Abort
import org.apache.daffodil.Implicits._
import org.apache.daffodil.api.Diagnostic
import org.apache.daffodil.util.Maybe
import org.apache.daffodil.util.Maybe._
class MyException(msg: String)
extends Diagnostic(Nope, Nope, Nope, Maybe(msg)) {
override def isError = true
override def modeName = "Parse"
}
abstract class MyBase(parentArg: MyBase)
extends OOLAGHostImpl(parentArg) {
def a1 = a1_.value
lazy val a1_ = LV('a1) {
// println("evaluating a1")
"a1 value"
}
def a2 = a2_.value
lazy val a2_ = LV('a2) {
// println("evaluating a2")
val msg = "a2 failed with an exception"
// println(msg)
val e = new MyException(msg)
// e.printStackTrace()
throw e
// "a2 value"
}
}
class MySubHost(name: String, parent: MyBase)
extends MyBase(parent) {
requiredEvaluationsAlways(a1)
}
class MyHost extends MyBase(null) {
requiredEvaluationsIfActivated(a1)
// LoggingDefaults.setLoggingLevel(LogLevel.Debug)
lazy val subHostCreator = {
val subHost1 = new MySubHost("subHost1", this)
val subHost2 = new MySubHost("subHost2", this)
(subHost1, subHost2)
}
def a3 = a3_.value
lazy val a3_ = LV('a3) {
// println("My LV name is " + LV.name)
"a3 value"
}
def a4 = a4_.value
lazy val a4_ = LV('a4) {
// println("My LV name is " + LV.name)
a3
}
def circ1: Int = circ1_.value
private lazy val circ1_ = LV('circ1) {
circ2
}
def circ2: Int = circ2_.value
private lazy val circ2_ = LV('circ2) {
circ1
}
def abortInside = abortInside_.value
private lazy val abortInside_ = LV('abortInside) {
abend
}
def abend = abend_.value
private lazy val abend_ = LV('err) {
Assert.abort("supposed to abort here")
}
var x = 0
def divZero = divZero_.value
lazy val divZero_ = LV('divZero) {
5 / x
}
def warnTest = warnTest_.value
lazy val warnTest_ = LV('warnTest) {
if (x < 1) {
val diag = new MyException("warnTest")
warn(diag)
}
x
}
}
class TestOOLAG {
@Test def testPrettyName(): Unit = {
val h = new MyHost
h.setRequiredEvaluationsActive()
assertEquals("MyHost", h.diagnosticDebugName)
}
@Test def testSuccessLazyVal(): Unit = {
val h = new MyHost
h.setRequiredEvaluationsActive()
// println("get the LV")
val a1lv = h.a1_
assertFalse(a1lv.hasError)
OOLAG.keepGoing({}) {
val a1v = h.a1
// println("value of a1_ is: " + a1lv)
assertEquals("a1 value", a1v)
}
// println(h.errorLVs)
assertFalse(a1lv.hasError)
assertFalse(h.isError)
}
@Test def testFailLazyVal(): Unit = {
val h = new MyHost
h.setRequiredEvaluationsActive()
OOLAG.keepGoing({}) {
// println("ask host for the LV")
h.a2
// catch {
// case e : Throwable => println("got exception " + e)
// }
// println("now test if it is an error")
}
val isErrorA2 = h.isError
assertTrue(isErrorA2)
}
// Note: Below commented out, as this reflection/stack-trace stuff
// was deemed too fragile, and troublesome in a lazy-evaluation world
// So the name must now, annoyingly, be passed to LVs.
// /**
// * Test mechanism by which LVs figure out their own method names
// *
// * That is, when you write lazy val foo = LV{...} the code can
// * get the name foo.
// *
// * This depends on some reflection stuff underneath which might change if
// * scala compilation model evolves. So if these tests break, then search
// * OOLAG.scala for "magic number" and see what is going on there.
// */
// @Test def testLVName() {
// val h = new MyHost
// h.setRequiredEvaluationsActive()
// // println("ask for the value")
// val a3: String = h.a3.value
// val a3Name = h.a3.name
// assertEquals("a3 value", a3)
// assertEquals("a3", a3Name)
// }
/**
* Make sure one LV calling another doesn't confuse things.
*/
@Test def testLVName2(): Unit = {
val h = new MyHost
h.setRequiredEvaluationsActive()
var res: String = null
OOLAG.keepGoing({}) {
// println("ask for the value")
res = h.a4 + h.a3
}
assertEquals("a3 valuea3 value", res)
}
@Test def testCircularDefinitionDetected(): Unit = {
val h = new MyHost
h.setRequiredEvaluationsActive()
var e: Exception = null
OOLAG.keepGoing({}) {
e = intercept[CircularDefinition] {
h.circ1
fail()
}
}
val msg = e.getMessage()
assertTrue(msg.toLowerCase().contains("circ1"))
}
@Test def testAlreadyTried(): Unit = {
val h = new MyHost
h.setRequiredEvaluationsActive()
assertTrue(h.a2_.isError)
val e = intercept[AlreadyTried] {
h.a2_.value
}
e match {
case at: AlreadyTried => {
val m = e.getMessage()
assertTrue(m.contains("a2"))
}
case _ => fail()
}
}
@Test def testThrowToTopLevel(): Unit = {
val h = new MyHost
h.setRequiredEvaluationsActive()
intercept[Abort] {
OOLAG.keepGoing({}) {
h.abortInside // should print useful lazy val nest messages to log
}
}
}
@Test def testDivZeroInside(): Unit = {
// LoggingDefaults.setLoggingLevel(LogLevel.OOLAGDebug)
val h = new MyHost
h.setRequiredEvaluationsActive()
// println("done constructing MyHost")
h.a1
h.subHostCreator
intercept[Exception] {
OOLAG.keepGoing({}) {
h.divZero
}
}
// println("Message: " + e.getMessage())
// assertTrue(h.isError)
assertTrue(h.divZero_.isError)
val d = h.diagnostics
d.foreach { System.err.println(_) }
// Division by zero is not caught by oolag anymore, so there will be
// no diagnostic message.
// assertTrue(d.length == 1)
}
@Test def testAutoTreeCreate(): Unit = {
val h = new MyHost
h.setRequiredEvaluationsActive()
OOLAG.keepGoing({}) {
h.subHostCreator
h.a2
}
assertTrue(h.isError)
val errs = h.diagnostics
println(errs)
}
}