uniba-dsg/betsy

If-InvalidExpressionValue: Clarify definition of invalid expression

vanto opened this issue · 4 comments

Betsy's If-InvalidExpressionValue test tests if a BPEL engine complains about the following snippet:

<if name="TestIfInputIsEven">
    <condition>"I am not a condition"</condition>
    ...

I doubt that this is actually an invalid expression. Here is why:

The BPEL spec clearly states:

Boolean expressions should return valid values of xsd:boolean (8.3, p 57)

And later in the same section, assuming that "WS-BPEL's default binding to XPath 1.0 is used as the expression language":

For WS-BPEL Boolean expressions, XPath's boolean(object) function is used to convert the expression result into a Boolean value if needed.

Now the definition of that boolean(object) function in XPath 1.0 is defined as follows:

Function: boolean boolean(object)

The boolean function converts its argument to a boolean as follows:

  • a number is true if and only if it is neither positive or negative zero nor NaN
  • a node-set is true if and only if it is non-empty
  • a string is true if and only if its length is non-zero
  • an object of a type other than the four basic types is converted to a boolean in a way that is dependent on that type

This leads to the conclusion that the string "I am not a condition" (a literal string) is, when passed to boolean(object) evaluates to false() as its length is not non-zero.

Thus I believe this statement is just fine and should not lead to a bpel:SelectionFailure

That sounds reasonable. Although, if I understand the definition correctly, the string literal "I am not a condition" should evaluate to true(). Only the empty string should evaluate to false(). So the process should just return 1.

Still, we should change the condition to include a value that is invalid in the above sense. Although it's hard for me at the moment to come up with an expression that is invalid, since boolean(object) seems to convert nearly anything to a boolean. Since numbers, strings, and node-sets always can be converted to true or false with the above definition, I would go for the fourth option, something like:

<condition>NoConditionHere</condition>

I'll also try an empty condition, but my intuition tells me that the engines might cope better with the above one. I ran some quick tests with the above example and bpel-g fails it. I'll do more complete tests in a few days and maybe also think of a smarter way for testing for InvalidExpressionValue.

That sounds reasonable. Although, if I understand the definition correctly, the string literal "I am not a condition" should evaluate to true(). Only the empty string should evaluate to false(). So the process should just return 1.

Sure, sorry.


I think

<condition>NoConditionHere</condition>

will be evaluated as path, similar to ./NoConditionHere, which would be an empty node-set and thus be false() -- if it would raise a ´SelectionFailure` it would be impossible to test for the existence of elements. On the other hand, engines may complain that there is no context element to evaluate the condition against. So it would be worth a try.

Another case that comes to my mind would be an undeclared namespace prefix, like x:UnknownNamespace where x is not declared in the process definition. WDYT?

I'll give the undeclard namespace prefix a try and see what the engines do.

As a side note: At least the tests for InvalidExpressionValue work with other BPEL activities that are more restricted. For instance the counter values of a forEach or the wait activity do expected unsigned integers and dates or times and should throw an InvalidExpressionValue for something like a string. The only problem here is that these actities are not as well supported as the if to begin with, so we easily run into dependencies among the tests here. For that reason it would be nice if we could provoke an InvalidExpressionValue in an if.

Finally, I have some data available, but it doesn't look that nice. Basically all of the versions discussed above fail for all engines. Some more details:

  1. For NoConditionHere:
    Two engines throw a subLanguageExecutionFault, one with a custom fault, two simply skip the assign but continue normally, and one doesn't reply anything
  2. For and empty condition:
    Again, twice a subLanguageExecutionFault, two custom faults, one refuses deployment and one replies nothing
  3. For undeclared namespace:
    Two refuse deployment, two ignore the assign, one replies a custom fault and one replies nothing.

I think the sublanguageExecutionFault is valid here, since the spec says in Sec. 8.2:

If the execution of a query or an expression yields an unhandled language fault, the WS-BPEL standard fault bpel:subLanguageExecutionFault MUST be thrown.

I would suggest to do the following:

  1. Convert the first two tests to tests for subLanguageExecutionFault. This has some value, as so far we only test for subLanguageExecutionFault in combination with XSLT, but not with XPath.
  2. Remove the third test, since it doesn't really give us anything. As a consequence, we won't have any more tests for InvalidExpressionValue in combination with a boolean expression. We still have some in combination with dates and times (Wait-For-InvalidExpressionValue) and unsigned ints (ForEach-NegativeStartCounter and more). Since I can't seem to find a nice way to put something in a condition that is valid in terms of XPath but cannot be converted with boolean(), I think this is the way to go.