Attaching a "phase 1" patch that adds two JUnit tests to lang/_Suite.java. The first test, XMLTypeAndOpsTest.java, is meant to be a JUnit equivalent to the current lang/xml_general.sql test. The second test, XMLMissingClassesTest, tests the behavior of the SQL/XML operators when the required JAXP or Xalan classes are not in the classpath.
This patch constitutes my first attempt at writing JUnit tests, so any feedback/advice would be much appreciated. In particular, things I am wondering include:
1. The expectation is that tests in XMLTypeAndOpsTest are run in
the order in which they appear in the .java file. With all of
my testing this seems to be the case--but as a general rule
is this a safe assumption with JUnit tests? If not then I'll
have to spend more time trying to make the different test cases
independent of each other.
2. Tables and data for the tests are created/inserted as they
are needed. I think this is best for this particular test
because the creation of tables and insertion of data is
part of what we're testing--i.e. it's not just "fixture"
code. But that said, I imagine some might prefer that
all of the table creation and data insertion logic go
into a startUp() method of a decorator that then runs
the test. I don't know what the established protocol is
with this. I prefer (at least in XMLTypeAndOpsTest) to
do the creation of tables on the fly (esp. since that's
what the old lang/xml_general.sql test did) but am not
opposed to changing it.
3. At most one of XMLTypeAndOpsTest and XMLMissingClasses will
ever run in a given environment. Given that fact, I didn't
necessarily have to split them out into two different tests--
I could just as easily have added logic to the "suite()"
method to add the appropriate test case(s) depending on
whether or the classpath had the required classes. Is there
a preference one way or the other for this kind of thing?
The patch, d1758_newJUnitTests_v1.patch, also adds a new utility method and some associated state to JDBC.java for checking two things: 1) that the classpath has JAXP and Xalan classes, and 2) if the classpath has Xalan, check that the version of Xalan meets the minimum requirement for use of Derby SQL/XML operators. These methods/flags are then used to determine when to run the new XML JUnit tests. I wasn't sure if they are more appropriate in JDBC.java or BaseJDBCTestCase.java, so I chose the former. But if that was the wrong decision, I can of course change it.
I ran the new test cases against jdk142, ibm142, jdk15, ibm15, and jdk16. In the absence of "endorsed jars" and classpath entries that include Xalan, the results were as follow:
jdk142: Neither XMLTypeAndOpsTest nor XMLMissingClassesTest runs.
This is because jdk142 exposes a version of Xalan that does
not meet the minimum requirements for Derby SQL/XML. Attempts
to run either test would lead to a Xalan-induced error caused
by a Xalan bug when running with security manager. Thus both
tests are skipped.
ibm142: XMLTypeAndOpsTest runs successfully, XMLMissingClassesTest
is skipped (as expected--a version of Xalan 2.6 is exposed in the
jdk15: XMLMissingClassesTest runs successfully, XMLTypeAndOpsTest
is skipped (as expected--jdk15 does not expose Xalan).
ibm15: XMLTypeAndOpsTest runs successfully, XMLMissingClassesTest
is skipped (as expected--a version of Xalan 2.7.1 is exposed
in the ibm15 JVM).
jdk16: XMLMissingClassesTest runs successfully, XMLTypeAndOpsTest
is skipped (as expected--jdk16 does not expose Xalan).
I then re-ran the tests after providing external Xalan and JAXP jars via classpath settings and/or "endorsed jars" to the JVMs. I tried both a 2.5.0 and a 2.7.0 version of Xalan in these tests. In all cases the XMLMissingClassesTest was skipped (as expected) and the XMLTypeAndOpsTest was run. There were two cases where the test failed:
1) ibm15 w/ endorsed 2.5.0: In this case there were lots of
failures caused by Java exceptions saying something to the
effect of "Unable to locate implementation for xxx" where
"xxx" was an internal Xalan class. My guess is that since
ibm15 embeds and exposes a version of Xalan 2.7.1 it has
some dependencies on that particular version. When I
overrode that with an earlier version (2.5.0) the classes
expected by the JVM did not exist, leading to errors. That
seems reasonable to me and is not something I think should
block the patch. As a general rule it seems like a bad idea
to override the JVMs libraries with earlier versions than
what it expects.
Note that when I endorsed Xalan 2.7.0 over the ibm15-embedded
version, everything ran as expected.
2) jdk16 w/ endorsed jars (either 2.5.0 or 2.7.0): there is
a single failure reported in XMLTypeAndOpsTest when running
against the Derby client. The failure occurs because the
test is written to assert the SQLSTATE of a nested exception--
but it turns out that for jdk16 the exception message does not
include the SQLSTATE for the nested exception. Some changes
that I made as part of
DERBY-1976 added logic to assertSQLState()
to search for nested exceptions, but that logic expects the
SQLSTATE to be included in the error message. For whatever
reason that's not the case with jdk16. More specifically,
we see the following error message from the client with
JVMs < 1.6:
org.apache.derby.client.am.SqlException: The exception 'java.sql.SQLException:
XML values are not allowed in top-level result sets; try using XMLSERIALIZE.'
was thrown while evaluating an expression. SQLSTATE: 42Z71: XML values are not
allowed in top-level result sets; try using XMLSERIALIZE.
From this we can search for "SQLSTATE" and the expected "42Z71".
But with jdk16 the error message is:
java.sql.SQLException: The exception 'java.sql.SQLSyntaxErrorException: XML
values are not allowed in top-level result sets; try using XMLSERIALIZE.' was
thrown while evaluating an expression.
The SQLSTATE of the nested exception is not printed. I spent some
time trying to figure out how to retrieve the SQLSTATE of the nested
exception in this case, but was unable to do so. I need to look
at this some more.
But since jdk16 by default does not exposed Xalan jars, the typical
case for running tests on that JVM will be that XMLMissingClassesTest
runs (and passes). Thus I don't think this is a blocker for the patch,
And finally, I ran "suites.All" with jdk142 and ibm142 and all tests passed with this patch.
NOTE: After this patch has been reviewed/updated and finally committed I will post a separate patch to remove the old lang/xml_general.sql test and the corresponding master files. I will then continue addressing the rest of the tasks for this issue (esp. xmlBinding.java) in incremental fashion.