You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mb...@apache.org on 2005/05/22 20:40:21 UTC

svn commit: r171355 [29/31] - in /incubator/jdo/trunk/fostore20: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/fostore/ test/ test/conf/ test/fsuid2/ test/fsuid2/org/ test/fsuid2/org/apache/ test/fsuid2/org/apache/jdo/ test/fsuid2/org/apache/jdo/pc/ test/java/ test/java/org/ test/java/org/apache/ test/java/org/apache/jdo/ test/java/org/apache/jdo/impl/ test/java/org/apache/jdo/impl/fostore/ test/java/org/apache/jdo/pc/ test/java/org/apache/jdo/pc/appid/ test/java/org/apache/jdo/pc/empdept/ test/java/org/apache/jdo/pc/serializable/ test/java/org/apache/jdo/pc/xempdept/ test/java/org/apache/jdo/test/ test/java/org/apache/jdo/test/query/ test/java/org/apache/jdo/test/util/ test/jdo/ test/jdo/org/ test/jdo/org/apache/ test/jdo/org/apache/jdo/ test/jdo/org/apache/jdo/pc/ test/jdo/org/apache/jdo/pc/appid/ test/jdo/org/apache/jdo/pc/empdept/ test/jdo/org/apache/jdo/pc/serializable/ test/jdo/org/apache/jdo/pc/xempdept/

Added: incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/query/TreeTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/query/TreeTest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/query/TreeTest.java (added)
+++ incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/query/TreeTest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,613 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.
+ */
+
+/*
+ * TreeTest.java
+ *
+ * Created on April 10, 2000
+ */
+
+package org.apache.jdo.test.query;
+
+import java.util.*;
+import java.io.*;
+import java.io.PrintStream;
+
+import javax.jdo.*;
+
+import org.apache.jdo.impl.jdoql.tree.FilterExpressionDumper;
+import org.apache.jdo.jdoql.tree.Expression;
+import org.apache.jdo.jdoql.tree.Node;
+import org.apache.jdo.jdoql.tree.QueryTree;
+import org.apache.jdo.jdoql.tree.TreeWalker;
+import org.apache.jdo.pc.xempdept.Department;
+import org.apache.jdo.pc.xempdept.Employee;
+import org.apache.jdo.pc.xempdept.Project;
+
+/**
+ *
+ * @author  Michael Bouschen
+ */
+public class TreeTest
+    extends PositiveTest
+{
+    private final TreeWalker walker = new TreeWalker();
+    private final FilterExpressionDumper dumper = new FilterExpressionDumper();
+    private void dumpTree(Node qt)
+    {   walker.walk( qt, dumper );
+    }
+
+    public TreeTest(PersistenceManagerFactory pmf, PrintStream log)
+    {
+        super(pmf, log);
+    }
+
+    protected boolean isTestMethodName(String methodName)
+    {
+       return methodName.startsWith("tree");
+    }
+
+    // ==========================================================================
+    // Test methods
+    // ==========================================================================
+
+    /**
+     * Testcase: relational operation
+     * field == literal
+     */
+    public void tree001()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.setCandidateClass(Employee.class);
+        Expression field = qt.newIdentifier("firstname");
+        Expression constant = qt.newConstant("firstEngOne");
+        Expression equals = qt.newEquals(field, constant);
+        qt.setFilter(equals);
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setEmployeeCandidates(query);
+        Object result = query.execute();
+        List oids = getResultOids(result);
+        Collections.sort(oids);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Employee.Oid key = new Employee.Oid();
+        key.empid = 1;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 11;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: using parameters
+     */
+    public void tree002()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.declareParameter(String.class, "name");
+        qt.setCandidateClass(Employee.class);
+        Expression field = qt.newIdentifier("lastname");
+        Expression param = qt.newIdentifier("name");
+        Expression equals = qt.newEquals(field, param);
+        qt.setFilter(equals);
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setEmployeeCandidates(query);
+        Object result = query.execute("lastEngTwo");
+        List oids = getResultOids(result);
+        Collections.sort(oids);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Employee.Oid key = new Employee.Oid();
+        key.empid = 2;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 12;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: compiled query
+     */
+    public void tree003()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.setCandidateClass(Department.class);
+        Expression field = qt.newIdentifier("deptid");
+        Expression constant = qt.newConstant(new Integer(1));
+        Expression equals = qt.newEquals(field, constant);
+        qt.setFilter(equals);
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+
+        // serialize query object
+        ByteArrayOutputStream bout = new ByteArrayOutputStream ();
+        ObjectOutputStream oout = new ObjectOutputStream (bout);
+        oout.writeObject(query);
+        oout.flush ();
+        byte[] bytes = bout.toByteArray();
+        oout.close ();
+
+        // deserialize query object
+        ByteArrayInputStream bin = new ByteArrayInputStream (bytes);
+        ObjectInputStream oin = new ObjectInputStream (bin);
+        query = (Query)oin.readObject ();
+        oin.close ();
+
+        // init and execute query
+        query = pm.newQuery(query);
+        setDepartmentCandidates(query);
+        Object result = query.execute();
+        List oids = getResultOids(result);
+        Collections.sort(oids);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Department.Oid key = new Department.Oid();
+        key.deptid = 1;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: compiled query
+     * simple query filter: Department.deptid == 1
+     */
+    public void tree004()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.setCandidateClass( Department.class );
+        Expression equals = qt.newEquals( qt.newIdentifier("deptid"), qt.newConstant(1) );
+        qt.setFilter( equals );
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setDepartmentCandidates(query);
+        Object result = query.execute();
+        List oids = getResultOids(result);
+        Collections.sort(oids);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Department.Oid key = new Department.Oid();
+        key.deptid = 1;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: compiled query
+     * bound variable access on Project
+     */
+    public void tree005()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.setCandidateClass( Employee.class );
+        qt.declareVariable( Project.class, "project" );
+        Expression contains = qt.newMethodCall( qt.newIdentifier("projects"), "contains", new Expression[] {qt.newIdentifier("project")} );
+        Expression projectName = qt.newFieldAccess( qt.newIdentifier("project"), "name" );
+        Expression equals = qt.newEquals( projectName, qt.newConstant("Sales Project") );
+        Expression and = qt.newConditionalAnd( contains, equals );
+        qt.setFilter( and );
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setEmployeeCandidates(query);
+        Object result = query.execute();
+        List oids = getResultOids(result);
+        Collections.sort(oids);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Employee.Oid key = new Employee.Oid();
+        key.empid = 1;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 4;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 5;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 6;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: compiled query
+     * bound variable access on Employee
+     */
+    public void tree006()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.setCandidateClass( Project.class );
+        qt.declareVariable( Employee.class, "employee" );
+        Expression contains = qt.newMethodCall( qt.newIdentifier("employees"), "contains", new Expression[] {qt.newIdentifier("employee")} );
+        Expression firstName = qt.newFieldAccess( qt.newIdentifier("employee"), "firstname" );
+        Expression equals = qt.newEquals( firstName, qt.newConstant("firstEngOne") );
+        Expression and = qt.newAnd( contains, equals );
+        qt.setFilter( and );
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setProjectCandidates(query);
+        Object result = query.execute();
+        List oids = getResultOids(result);
+        Collections.sort(oids);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Project.Oid key = new Project.Oid();
+        key.projid = 1;
+        expected.add(key);
+        key = new Project.Oid();
+        key.projid = 2;
+        expected.add(key);
+        key = new Project.Oid();
+        key.projid = 3;
+        expected.add(key);
+        key = new Project.Oid();
+        key.projid = 11;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: compiled query
+     * nested bound variable access on Employee and Project
+     */
+    public void tree007()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.setCandidateClass( Employee.class );
+        qt.declareVariable( Project.class, "project" );
+        qt.declareVariable( Employee.class, "employee" );
+        Expression contains1 = qt.newMethodCall( qt.newIdentifier("projects"), "contains", new Expression[] {qt.newIdentifier("project")} );
+        Expression contains2 = qt.newMethodCall( qt.newFieldAccess(qt.newIdentifier("project"), "employees"), "contains", new Expression[] {qt.newIdentifier("employee")} );
+        Expression firstName = qt.newFieldAccess( qt.newIdentifier("employee"), "firstname" );
+        Expression equals = qt.newEquals( firstName, qt.newConstant("firstEngOne") );
+        Expression and2 = qt.newAnd( contains2, equals );
+        Expression and1 = qt.newConditionalAnd( contains1, and2 );
+        qt.setFilter( and1 );
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setEmployeeCandidates(query);
+        Object result = query.execute();
+        List oids = getResultOids(result);
+        Collections.sort(oids);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Employee.Oid key = new Employee.Oid();
+        key.empid = 1;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 2;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 3;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 4;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 5;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 6;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 7;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 11;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 12;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: compiled query
+     * method call
+     */
+    public void tree008()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.setCandidateClass( Employee.class );
+        Expression firstName = qt.newIdentifier( "firstname" );
+        Expression methodCall = qt.newMethodCall( firstName, "endsWith", new Expression[]{qt.newConstant("One")} );
+        qt.setFilter( methodCall );
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setEmployeeCandidates(query);
+        Object result = query.execute();
+        List oids = getResultOids(result);
+        Collections.sort(oids);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Employee.Oid key = new Employee.Oid();
+        key.empid = 1;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 11;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: compiled query
+     * ascending
+     */
+    public void tree009()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.setCandidateClass( Employee.class );
+        Expression empid = qt.newIdentifier( "empid" );
+        Expression birthdate = qt.newIdentifier( "birthdate" );
+        qt.addAscendingOrdering( empid );
+        Expression firstName = qt.newIdentifier( "firstname" );
+        Expression equals = qt.newEquals( firstName, qt.newConstant("firstEngOne") );
+        qt.setFilter( equals );
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setEmployeeCandidates(query);
+        Object result = query.execute();
+        List oids = getResultOids(result);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Employee.Oid key = new Employee.Oid();
+        key.empid = 1;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 11;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: compiled query
+     * decending
+     */
+    public void tree010()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.setCandidateClass( Employee.class );
+        Expression empid = qt.newIdentifier( "empid" );
+        Expression birthdate = qt.newIdentifier( "birthdate" );
+        qt.addDescendingOrdering( empid );
+        Expression firstName = qt.newIdentifier( "firstname" );
+        Expression equals = qt.newEquals( firstName, qt.newConstant("firstEngOne") );
+        qt.setFilter( equals );
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setEmployeeCandidates(query);
+        Object result = query.execute();
+        List oids = getResultOids(result);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Employee.Oid key = new Employee.Oid();
+        key.empid = 11;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 1;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: compiled query
+     * ascending/decending
+     */
+    public void tree011()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.setCandidateClass( Employee.class );
+        Expression firstName = qt.newIdentifier( "firstname" );
+        Expression empid = qt.newIdentifier( "empid" );
+        qt.addAscendingOrdering( firstName );
+        qt.addDescendingOrdering( empid );
+        Expression name = qt.newIdentifier( "firstname" );
+        Expression equals = qt.newEquals( name, qt.newConstant("firstEngOne") );
+        qt.setFilter( equals );
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setEmployeeCandidates(query);
+        Object result = query.execute();
+        List oids = getResultOids(result);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Employee.Oid key = new Employee.Oid();
+        key.empid = 11;
+        expected.add(key);
+        key = new Employee.Oid();
+        key.empid = 1;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+    /**
+     * Testcase: compiled query
+     * decending
+     */
+    public void tree012()
+        throws Exception
+    {
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+
+        // create query tree
+
+        QueryTree qt = newQueryTree();
+        qt.declareParameter( Collection.class, "collection" );
+        qt.setCandidateClass( Employee.class );
+        Expression equals = qt.newEquals( qt.newIdentifier("empid"), qt.newConstant(1) );
+        Expression contains = qt.newMethodCall( qt.newIdentifier("collection"), "contains", new Expression[]{qt.newConstant((short)1)} );
+        Expression and = qt.newAnd( contains, equals );
+        qt.setFilter( and );
+
+        // create query
+
+        Query query = pm.newQuery(qt);
+        setEmployeeCandidates(query);
+        Collection collection = new HashSet();
+        collection.add( new Short((short)1) );
+        Object result = query.execute( collection );
+        List oids = getResultOids(result);
+        Collections.sort(oids);
+
+        // check query result
+
+        Collection expected = new ArrayList();
+        Employee.Oid key = new Employee.Oid();
+        key.empid = 1;
+        expected.add(key);
+        checkQueryResult(oids, expected);
+
+        tx.commit();
+    }
+
+}
+

Added: incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/query/UnsupportedTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/query/UnsupportedTest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/query/UnsupportedTest.java (added)
+++ incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/query/UnsupportedTest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.
+ */
+
+/*
+ * UnsupportedTest.java
+ *
+ * Created on April 6, 2000
+ */
+
+package org.apache.jdo.test.query;
+
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.Map;
+import java.io.PrintStream;
+
+import javax.jdo.*;
+
+import org.apache.jdo.pc.xempdept.Department;
+import org.apache.jdo.pc.xempdept.Employee;
+import org.apache.jdo.pc.xempdept.Project;
+
+/** 
+ *
+ * @author  Michael Bouschen
+ */
+public class UnsupportedTest
+  extends NegativeTest
+{
+    public UnsupportedTest(PersistenceManagerFactory pmf, PrintStream log)
+    {
+        super(pmf, log);
+    }
+
+    protected boolean isTestMethodName(String methodName)
+    {
+       return methodName.startsWith("unsupported");
+    }
+    
+    // ==========================================================================
+    // Test methods
+    // ==========================================================================
+    /**
+     * Testcase: unconstraint variable
+     */
+    public void unsupported001()
+        throws Exception
+    {
+        String expectedMsg = msg.msg("EXC_UnconstraintVariable", "e"); //NOI18N
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+        
+        try
+        {
+            Query query = pm.newQuery(Department.class);
+            query.declareImports("import org.apache.jdo.pc.xempdept.Employee");
+            query.declareVariables("Employee e");
+            query.setFilter("deptid == 1");
+            query.compile();
+            query.execute();
+            checkMissingException(JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        catch (JDOException ex)
+        {
+            checkJDOException(ex, JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        
+        tx.rollback();
+    }
+
+    /**
+     * Testcase: unconstriant variable
+     */
+    public void unsupported002()
+        throws Exception
+    {
+        String expectedMsg = msg.msg("EXC_UnconstraintVariable", "d");
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+        
+        try
+        {
+            Query query = pm.newQuery();
+            query.setClass(Project.class);
+            query.declareVariables("org.apache.jdo.pc.xempdept.Employee e; org.apache.jdo.pc.xempdept.Department d");
+            query.setFilter("d.employees.contains(e) & e.department == d");
+            query.compile();
+            checkMissingException(JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        catch (JDOException ex)
+        {
+            checkJDOException(ex, JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        
+        tx.rollback();
+    }
+
+    /**
+     * Testcase: variable constraint, but not used
+     */
+    public void unsupported003()
+        throws Exception
+    {
+        String expectedMsg = msg.msg("EXC_UnusedVariable", "e"); //NOI18N
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+        
+        try
+        {
+            Query query = pm.newQuery(Department.class);
+            query.declareImports("import org.apache.jdo.pc.xempdept.Employee");
+            query.declareVariables("Employee e");
+            query.setFilter("employees.contains(e)");
+            query.compile();
+            query.execute();
+            checkMissingException(JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        catch (JDOException ex)
+        {
+            checkJDOException(ex, JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        
+        tx.rollback();
+    }
+
+    /**
+     * Testcase: variable constraint, but not used
+     */
+    public void unsupported004()
+        throws Exception
+    {
+        String expectedMsg = msg.msg("EXC_UnusedVariable", "e"); //NOI18N
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+        
+        try
+        {
+            Query query = pm.newQuery(Department.class);
+            query.declareImports("import org.apache.jdo.pc.xempdept.Employee");
+            query.declareVariables("Employee e");
+            query.setFilter("employees.contains(e) | (deptid == 1)");
+            query.execute();
+            checkMissingException(JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        catch (JDOException ex)
+        {
+            checkJDOException(ex, JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        
+        tx.rollback();
+    }
+
+    /**
+     * Testcase: cyclic variable constraint in one expression
+     */
+    public void unsupported005()
+        throws Exception
+    {
+        String expectedMsg = 
+            msg.msg("EXC_UnsupportedCyclicConstaint", "e"); //NOI18N
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+        
+        try
+        {
+            Query query = pm.newQuery(Employee.class);
+            query.declareVariables("Employee e");
+            query.setFilter("e.team.contains(e)");
+            query.setCandidates(pm.getExtent(Employee.class, false));
+            query.execute();
+            checkMissingException(JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        catch (JDOException ex)
+        {
+            checkJDOException(ex, JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        
+        tx.rollback();
+    }
+
+    /**
+     * Testcase: cyclic variable constraint using two expressions
+     */
+    public void unsupported006()
+        throws Exception
+    {
+        String expectedMsg = 
+            msg.msg("EXC_UnsupportedCyclicConstaint", "p"); //NOI18N
+        Transaction tx = pm.currentTransaction();
+        tx.begin();
+        
+        try
+        {
+            Query query = pm.newQuery(Project.class);
+            query.declareVariables("org.apache.jdo.pc.xempdept.Employee e; org.apache.jdo.pc.xempdept.Project p");
+            query.setFilter("p.employees.contains(e) & e.projects.contains(p)");
+            query.execute();
+            checkMissingException(JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        catch (JDOException ex)
+        {
+            checkJDOException(ex, JDOUnsupportedOptionException.class, expectedMsg);
+        }
+        
+        tx.rollback();
+    }
+}

Added: incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/AbstractTest.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/AbstractTest.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/AbstractTest.java (added)
+++ incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/AbstractTest.java Sun May 22 11:40:13 2005
@@ -0,0 +1,778 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.jdo.test.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.PrintStream;
+
+import java.net.URL;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.TreeSet;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import javax.jdo.JDOHelper;
+import javax.jdo.Extent;
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+import javax.jdo.Transaction;
+import javax.jdo.JDOException;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.impl.fostore.FOStoreConnectionFactory;
+import org.apache.jdo.impl.fostore.FOStorePMF;
+import org.apache.jdo.impl.fostore.FOStoreRemoteConnection;
+
+/**
+* Tests that we can activate a class.  Actually goes farther than that,
+* storing the value of an instance of a class, since that's the only way we can
+* cause a class to be activated.
+*
+* @author Dave Bristor
+*/
+public abstract class AbstractTest 
+    extends TestCase
+{
+    protected static PrintStream out = System.out;
+
+    protected PersistenceManagerFactory pmf;
+
+    // Default values as given in ant build scripts
+    private static final String DEFAULT = "--default--";
+
+    // Put oid's of inserted objects here for later retrieval.
+    protected List oids = new ArrayList();
+
+    // Name of host on which server runs (remote case only)
+    protected final String dbHost;
+
+    // Port on host on which server runs (remote case only)
+    protected final String dbPort;
+
+    // Directory of the database
+    protected final String dbDir;
+
+    // Root name of the database
+    protected String dbName;
+
+    // If neither null nor empty String, access the PMF via the name given
+    // with JNDI.  This takes precedence over dbName.  If dbDir is given, then
+    // the JNDI InitialContext is rooted there, otherwise in the current
+    // directory.
+    protected String pmfLoadName = null;
+
+    // If neither null nor empty String, loads the named file's Properties
+    // object and uses it to configure a FOStoreConnectionFactory, which is
+    // then set on the PMF.
+    protected String cfPropsFile = null;
+
+    // If neither null nor empty String, save the PMF under the given name
+    // before exiting.
+    protected String pmfSaveName = null;
+
+    // Number of objects to insert.
+    // Not final, so that subclasses can override (e.g. Test_ParallelPMs).
+    protected int numInsert;
+
+    /** Logger */
+    protected Log logger =
+        LogFactory.getFactory().getInstance("org.apache.jdo.test");
+
+    /** true if debug logging in enabled. */
+    protected boolean debug = logger.isDebugEnabled();
+
+    // Maximum number of messages to print in various phases of processing
+    protected final int maxMessages;
+    
+    // Becomes true once we've announced maxMessages
+    protected boolean messagesPrinted = false;
+
+    // If true, class reading instances should invoke verify() on each one.
+    // verify() is defined in this file.
+    protected int verify;
+
+    // If true, use existing database (and fail if it's not there), otherwise
+    // create a new one (which is the default).  Unlike other properties, this
+    // one is not final; it can be changed by a subclass to enforce that an
+    // existing database is to be used or that a new one is to be created.
+    protected boolean existing;
+
+    // Factory object by which PersistenceCapable instances are created.  Not
+    // final, so that subclasses can provide their own factory.
+    protected Factory factory;
+
+    // Number of objects inserted.  See announce().
+    protected int insertedCount = 0;
+
+    protected Properties properties = null;
+
+    // Flag indicating successful test run
+    protected boolean testSucceeded;
+
+    /**
+    * Construct and initialize from properties.
+    */
+    protected AbstractTest() {
+        super(null);
+
+        //
+        // Get property values
+        //
+
+        try {
+            numInsert = Integer.parseInt(System.getProperty("insert"));
+        } catch (Exception ex) {
+            numInsert = getDefaultInsert(); // use default
+        }
+        
+        int max = 10;
+        try {
+            max = Integer.parseInt(System.getProperty("max"));
+        } catch (Exception ex) {
+            // use default
+        }
+        maxMessages = max;
+
+        try {
+            verify = Integer.parseInt(System.getProperty("verify"));
+        } catch (Exception ex) {
+            verify = getDefaultVerify(); // use default
+        }
+
+        existing = Boolean.getBoolean("existing");
+
+        String host = System.getProperty ("host", "");
+        if (host.equals("")) {
+            host = null;
+        } else {
+            host = "//" + host;
+        }
+
+        String port = System.getProperty ("port", "");
+        if (port.equals("")) {
+            port = null;
+        } else {
+            port = ":" + port;
+        }
+
+        if (null == host & null != port) {
+            host = "//localhost";
+        }
+
+        if (null != host && null == port) {
+            port =":" + new Integer(FOStoreRemoteConnection.DEFAULT_PORT);
+        }
+
+        dbHost = host;
+        dbPort = port;
+
+        String dir = System.getProperty("dir");
+        if (null == dir || dir.equals(DEFAULT)) {
+            dir = System.getProperty("user.dir");
+        }
+        dbDir = dir;
+
+        String name = System.getProperty("name");
+        if (null == name || name.equals(DEFAULT)) {
+            name = "FOStoreTestDB";
+        }
+        dbName = name;
+
+        pmfLoadName = System.getProperty("pmfLoadName");
+        if (null != pmfLoadName && pmfLoadName.length() == 0) {
+            pmfLoadName = null;
+        }
+
+        cfPropsFile = System.getProperty("cfPropsFile");
+        if (null != cfPropsFile && cfPropsFile.length() == 0) {
+            cfPropsFile = null;
+        }
+
+        pmfSaveName = System.getProperty("pmfSaveName");
+        if (null != pmfSaveName && pmfSaveName.length() == 0) {
+            pmfSaveName = null;
+        }
+
+        factory = getFactory(verify);
+    }
+    
+    /** */
+    protected int getDefaultInsert()
+    {
+        return 1;
+    }
+ 
+    /** */
+    protected int getDefaultVerify()
+    {
+        return 0;
+    }   
+
+    /**
+     * Sets up the PMF for the test.
+     */
+    protected void setUp() throws Exception {
+        setupPMF();
+        if (null != pmfSaveName) {
+            savePMF();
+        }
+    }
+
+    /**
+     * Runs the bare test sequence.
+     * @exception Throwable if any exception is thrown
+     */
+    public void runBare() throws Throwable {
+        setUp();
+        try {
+            testSucceeded = false;
+            runTest();
+            testSucceeded = true;
+        }
+        finally {
+            tearDown();
+        }
+    }
+
+    /**
+     */
+    protected void tearDown() {
+        try {
+            insertedCount = 0;
+            messagesPrinted = false;
+            oids.clear();
+            closePMF();
+        }
+        catch (Throwable ex) {
+            if (debug) ex.printStackTrace();
+            if (testSucceeded) {
+                // runTest succeeded, but closePMF throws exception =>
+                // failure
+                fail("Exception during tearDown: " + ex);
+            }
+            else {
+                // runTest failed and closePMF throws exception =>
+                // just print the closePMF exception, otherwise the
+                // closePMF exception would swallow the test case failure
+                logger.debug("Exception during tearDown: " + ex);
+            }
+        }
+    }
+
+    /**
+     *
+     */
+    protected void closePMF() {
+        JDOException failure = null;
+        while (pmf != null) {
+            if (debug) logger.debug("closePMF");
+            try {
+                // Execute pmf.close in a privileged block, otherwise the test
+                // class caller needs permission close a PMF.
+                AccessController.doPrivileged(new PrivilegedAction () {
+                        public Object run () {
+                            pmf.close();
+                            return null;
+                        }});
+                pmf = null;
+            }
+            catch (JDOException ex) {
+                // store failure of first call pmf.close
+                if (failure == null)
+                    failure = ex;
+                PersistenceManager[] pms = getFailedPersistenceManagers(ex);
+                for (int i = 0; i < pms.length; i++) {
+                    closePM(pms[i]);
+                }
+            }
+        }
+
+        // rethrow JDOException thrown by pmf.close
+        if (failure != null)
+            throw failure;
+    }
+
+    /** 
+     * This method cleans up the specified 
+     * <code>PersistenceManager</code>. If the pm still has an open
+     * transaction, it will be rolled back, before closing the pm.
+     */
+    protected void closePM(PersistenceManager pm) 
+    {
+        if ((pm != null) && !pm.isClosed()) {
+            if (pm.currentTransaction().isActive()) {
+                pm.currentTransaction().rollback();
+            }
+            pm.close();
+        }
+    }
+
+    /** */
+    protected PersistenceManager[] getFailedPersistenceManagers(
+        JDOException ex) {
+        Throwable[] nesteds = ex.getNestedExceptions();
+        int numberOfExceptions = nesteds==null ? 0 : nesteds.length;
+        PersistenceManager[] result = new PersistenceManager[numberOfExceptions];
+        for (int i = 0; i < numberOfExceptions; ++i) {
+            JDOException exc = (JDOException)nesteds[i];
+            Object failedObject = exc.getFailedObject();
+            if (exc.getFailedObject() instanceof PersistenceManager) {
+                result[i] = (PersistenceManager)failedObject;
+            } else {
+                fail("Unexpected failed object of type: " +
+                     failedObject.getClass().getName());
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Sets up the PMF used by this test as per defaults and system properties.
+     */
+    protected void setupPMF() throws Exception {
+        if (null == pmfLoadName) {
+            if( null == pmfSaveName &&
+                null == cfPropsFile ) {
+                pmf = createPMF();
+            }
+            else {
+                pmf = new FOStorePMF();
+                if (null != cfPropsFile) {
+                    configCF();
+                } else {
+                    configPMF();
+                }
+            }
+        } else {
+            loadPMF();
+        }
+    }
+
+    /**
+     * Initializes JDO startup properties with default values.
+     * Sub classes can overwrite this method in order to change those default
+     * values.
+     */
+    protected void initProperties() {
+        properties = new Properties();
+        properties.setProperty("javax.jdo.option.ConnectionUserName", "fred");
+        properties.setProperty("javax.jdo.option.ConnectionPassword", "wombat");
+        properties.setProperty("javax.jdo.option.ConnectionURL", createURL());
+    }
+
+    /**
+     * Returns a PMF instance using a properties file.
+     * @return the PMF instance
+     */
+    protected PersistenceManagerFactory createPMF() throws IOException {
+        initProperties();
+        // Execute getResourceAsStream in a privileged block, otherwise the
+        // test class caller needs permission to read the properties file. 
+        InputStream input = (InputStream)AccessController.doPrivileged(
+            new PrivilegedAction () {
+                public Object run () {
+                    return AbstractTest.class.getClassLoader().
+                        getResourceAsStream("PMF.properties");
+                }
+            });
+        properties.load( input );
+        if( !properties.containsKey("javax.jdo.option.ConnectionURL") )
+            properties.setProperty("javax.jdo.option.ConnectionURL",
+                                   createURL());
+        PersistenceManagerFactory pmf = 
+            JDOHelper.getPersistenceManagerFactory(properties);
+        if( pmf instanceof FOStorePMF )
+            ((FOStorePMF)pmf).setConnectionCreate(!existing);
+        return pmf;
+    }
+
+    /**
+     * Configures a PMF with some basic properties, and creates the
+     * corresponding database.
+     */
+    protected void configPMF() throws Exception {
+        if( pmf instanceof FOStorePMF )
+            ((FOStorePMF)pmf).setConnectionCreate(!existing);
+
+        pmf.setConnectionUserName(System.getProperty("user", "fred"));
+        pmf.setConnectionPassword(System.getProperty("password", "wombat"));
+
+        String url = createURL();
+        pmf.setConnectionURL(url);
+    }
+
+        /** Create url in string form from dbHost, dbPort, dbDir, and path.
+         *@return String URL.
+         */
+    protected String createURL() {
+        String path = "";
+
+        if (null != dbHost) {
+            path += dbHost;
+        }
+
+        if (null != dbPort) {
+            path += dbPort + "/";
+        }
+
+        if (null == dbHost && null == dbPort) {
+            path += dbDir + File.separator;
+        }
+        path += dbName;
+
+        path = "fostore:" + path;
+
+        if (debug) {
+            logger.debug("ConnectionURL is " + path);
+        }
+        return path;
+    }
+
+    /**
+     * Loads a previously configured PMF via JNDI.
+     */
+    protected void loadPMF() throws Exception {
+        if (debug) logger.debug("Loading PMF via JNDI from " + pmfLoadName);
+        Context c = new InitialContext();
+        pmf = (FOStorePMF)c.lookup(pmfLoadName);
+        c.close();
+    }
+
+    /**
+     * Saves the PMF via JNDI.
+     */
+    protected void savePMF() throws Exception{
+        if (debug) logger.debug("Saving PMF via JNDI as " + pmfSaveName);
+        Context c = new InitialContext();
+        c.rebind(pmfSaveName, pmf);
+        c.close();
+    }
+
+    /**
+     * Configures a ConnectionFactory from properties in a file.
+     */
+    protected void configCF() throws Exception {
+        if (debug)
+            logger.debug("Setting PMF's ConnectionFactory from " + cfPropsFile);
+        Properties p = new Properties();
+        p.load(new FileInputStream(new File(cfPropsFile)));
+        FOStoreConnectionFactory cf = new FOStoreConnectionFactory();
+        cf.setFromProperties(p);
+        // oid file handling need dbName to be initialized => set
+        // dbName to the file portion of the connections factory's url
+        URL url = new URL(cf.getURL());
+        dbName = url.getFile();
+        if (debug) {
+            logger.debug("CF: " + cf.toString());
+            logger.debug("dbName: " + dbName);
+        }
+        pmf.setConnectionFactory(cf);
+        if (debug) {
+            logger.debug("PMF: " + pmf.toString());
+        }
+    }
+
+    /**
+     * Inserts some number of objects of some kind in the database.  The
+     * number and kind are determined by defaults and system properties.
+     */
+    protected void insertObjects() throws Exception {
+        PersistenceManager pm = pmf.getPersistenceManager();
+        Transaction tx = pm.currentTransaction();
+
+        try {
+            tx.begin();
+            Object inserted[] = new Object[numInsert];
+            for (int i = 0; i < numInsert; i++) {
+                Object pc = factory.create(i);
+                pm.makePersistent(pc);
+                inserted[i] = pc;
+            }
+            
+            tx.commit();
+            
+            for (int i = 0; i < numInsert; i++) {
+                announce("inserted ", inserted[i]);
+            }
+        }
+        finally {
+            if (tx != null && tx.isActive())
+                tx.rollback();
+            if (pm != null && !pm.isClosed())
+                pm.close();
+        }
+    }
+
+    /**
+     * Inserts some number of objects of some kind in the database.  The
+     * number and kind are determined by defaults and system properties.
+     */
+    protected void readObjects() throws Exception {
+        PersistenceManager pm = pmf.getPersistenceManager();
+        try {
+            int count = 0;
+            for (Iterator i = oids.listIterator(); i.hasNext();) {
+                Object oid = i.next();
+                Object pc = pm.getObjectById(oid, true);
+                if (debug)
+                    logger.debug("readObjects oid: " + oid + " pc: " + pc);
+                verify(count++, pc); 
+            }
+        }
+        finally {
+            if (pm != null && !pm.isClosed())
+                pm.close();
+        }
+    }
+
+    /**
+     * Helper method checking whether the extent of the specified pc class
+     * has the expected number of instances.
+     */
+    protected void checkExtent(Class pcClass, int expected) {
+        PersistenceManager pm = pmf.getPersistenceManager();
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            Extent extent = pm.getExtent(pcClass, false);
+            int nrOfObjects = 0;
+            for (Iterator i = extent.iterator(); i.hasNext();) {
+                i.next();
+                nrOfObjects++;
+            }
+            if (debug)
+                logger.debug("checkExtent: "+ pcClass.getName() + 
+                             " extent has " + nrOfObjects + " instances.");
+            assertEquals("Wrong number of instances in " + pcClass.getName() + 
+                         " extent", expected, nrOfObjects);
+            tx.commit();
+        }
+        finally {
+            if (tx != null && tx.isActive())
+                tx.rollback();
+            if (pm != null && !pm.isClosed())
+                pm.close();
+        }
+    }
+    
+    /** 
+     * Helper method creating an input stream for reading objects.
+     **/
+    protected ObjectInputStream getObjectInputStream(final String filename)
+        throws IOException
+    {
+        try {
+            return (ObjectInputStream)AccessController.doPrivileged(
+                new PrivilegedExceptionAction () {
+                    public Object run () throws IOException {
+                        return new ObjectInputStream(
+                            new FileInputStream(filename));
+                    }
+                });
+        }
+        catch (PrivilegedActionException ex) {
+            // unwrap IOException
+            throw (IOException)ex.getException();
+        } 
+    }
+
+    /** 
+     * Helper method creating an output stream for writing oids into a file.
+     **/
+    protected ObjectOutputStream getObjectOutputStream(final String filename)
+        throws IOException
+    {
+        try {
+            return (ObjectOutputStream)AccessController.doPrivileged(
+                new PrivilegedExceptionAction () {
+                    public Object run () throws IOException {
+                        return new ObjectOutputStream(
+                            new FileOutputStream(filename));
+                    }
+                });
+        }
+        catch (PrivilegedActionException ex) {
+            // unwrap IOException
+            throw (IOException)ex.getException();
+        } 
+    }
+    
+
+    /** 
+     * Helper method creating an input stream for reading oids from a file.
+     **/
+    protected ObjectInputStream getOIDFileInputStream() throws IOException
+    {
+        final String name = dbDir + File.separator + dbName + ".oid";
+        final File f = new File(name);
+        try {
+            return (ObjectInputStream)AccessController.doPrivileged(
+                new PrivilegedExceptionAction () {
+                    public Object run () throws IOException {
+                        assertTrue("OID file " + name + " does not exist",
+                                   f.exists());
+                        return new ObjectInputStream(new FileInputStream(f));
+                    }
+                });
+        }
+        catch (PrivilegedActionException ex) {
+            // unwrap IOException
+            throw (IOException)ex.getException();
+        } 
+    }
+    
+    /** 
+     * Helper method creating an output steam for writing oids into a file.
+     */
+    protected ObjectOutputStream getOIDFileOutputStream() throws IOException
+    {
+        final File f = new File(dbDir + File.separator + dbName + ".oid");
+        try {
+            return (ObjectOutputStream)AccessController.doPrivileged(
+                new PrivilegedExceptionAction () {
+                    public Object run () throws IOException {
+                        if (f.exists()) {
+                            f.delete();
+                        }
+                        return new ObjectOutputStream(new FileOutputStream(f));
+                    }
+                });
+        }
+        catch (PrivilegedActionException ex) {
+            // unwrap IOException
+            throw (IOException)ex.getException();
+        } 
+    }
+
+    /**
+     * Writes the OID values to a file, for later reading by tests that want
+     * to fetch objects by OID.
+     */
+    protected void writeOIDs() throws Exception {
+        ObjectOutputStream out = getOIDFileOutputStream();
+        int count = 0;
+        boolean messagePrinted = false;
+        TreeSet sorted = new TreeSet(new OIDComparator());
+        sorted.addAll(oids);
+        for (Iterator i = sorted.iterator(); i.hasNext();) {
+            count++;
+            Object oid = i.next();
+            if (debug && count < maxMessages) {
+                logger.debug("writing: " + oid);
+            } else {
+                if (debug && !messagePrinted) {
+                    logger.debug("skip remaining messages");
+                    messagePrinted = true;
+                }
+            }
+            out.writeObject(oid);
+        }
+
+        if (debug) {
+            logger.debug("wrote " + count + " OID's");
+        }
+        out.close();
+    }
+
+    protected synchronized void announce(String msg, Object pc) {
+        insertedCount++;
+        Object oid = JDOHelper.getObjectId(pc);
+        //MBOobjects.put(oid, pc.getClass());
+        oids.add(oid);
+        if (debug) {
+            if (insertedCount < maxMessages) {
+                logger.debug(msg + Util.getClassName(pc) +
+                             ": " + oid + ", " + pc);
+            } else if ( ! messagesPrinted) {
+                logger.debug("skip remaining messages");
+                messagesPrinted = true;
+            }
+        }
+    }
+
+    /**
+     * Determines the kind of objects that are inserted.  
+     */
+    protected Factory getFactory(int verify)
+    {
+        return null;
+    }
+
+    /**
+     *
+     */
+    protected Factory getFactoryByClassProperty(int verify,
+                                                String defaultClassName)
+    {
+        Factory factory = null;
+        String className = System.getProperty("class");
+        if (className == null) {
+            className = defaultClassName;
+        }
+        try {
+            String name = className;
+            int pos = name.indexOf("PC");
+            if (pos > 0) {
+                name = name.substring(0, pos) + name.substring(pos + 2);
+            }
+            Class factoryClass = Class.forName(name + "Factory");
+            factory = (Factory)factoryClass.newInstance();
+            factory.setVerify(verify);
+        } catch (ClassNotFoundException ex) {
+            fail("Could not load factory for " + className+ ": " + ex);
+        } catch (InstantiationException ex) {
+            fail("Could not instantiate instance of class " + className + ": " + ex);
+        } catch (IllegalAccessException ex) {
+            fail("Cannot access class " + className + " or its constructor: " + ex);
+        }
+        factory.setVerify(verify);
+        return factory;
+    }
+
+    /**
+     * Verifies that an objects is as it is supposed to be.  Leaves the
+     * decision as to whether or not the object is OK up to the factory which
+     * created it.
+     */
+    protected void verify(int i, Object pc) {
+        if (verify > 0) {
+            if (debug) logger.debug("verify (i = " + i + ") " + pc); 
+            assertTrue("Verify pc instance", factory.verify(i, pc));
+        }
+    }
+}

Added: incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/BatchResultPrinter.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/BatchResultPrinter.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/BatchResultPrinter.java (added)
+++ incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/BatchResultPrinter.java Sun May 22 11:40:13 2005
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.jdo.test.util;
+
+import java.io.PrintStream;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.textui.ResultPrinter;
+
+/**
+ * Default result printer implementation for running tests in batch mode.
+ * 
+ * @author Michael Bouschen
+ */
+public class BatchResultPrinter
+    extends ResultPrinter
+{
+    /** */
+    public BatchResultPrinter(PrintStream writer) {
+        super(writer);
+    }
+        
+    /** Called in case of a test error. */
+    public void addError(Test test, Throwable t) {
+        getWriter().print("   ERROR");
+    }
+        
+    /** Called in case of a test failure. */ 
+    public void addFailure(Test test, AssertionFailedError t) {
+        getWriter().print("   FAILURE");
+    }
+        
+    /** Called when a test case is finished. */
+    public void endTest(Test test) {
+        getWriter().println();
+    }
+        
+    /** Called when a test case is started. */
+    public void startTest(Test test) {
+        String testName;
+        if (test instanceof TestCase) {
+            testName = getClassBaseName(test) + "." + ((TestCase)test).getName();
+        }
+        else {
+            testName = test.toString();
+        }
+        getWriter().print("RUN " + testName);
+    }
+        
+    /** */
+    protected void printHeader(long runTime) {
+        getWriter().println("Time: "+elapsedTimeAsString(runTime));
+    }
+        
+    /** */
+    protected void printFooter(TestResult result) {
+        if (result.wasSuccessful()) {
+            getWriter().print("OK");
+            getWriter().println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")");
+                
+        } else {
+            getWriter().println("FAILURES!!!");
+            getWriter().println("Tests run: "+result.runCount()+ 
+                                ",  Failures: "+result.failureCount()+
+                                ",  Errors: "+result.errorCount());
+        }
+    }
+        
+    // helper method
+        
+    /** 
+     * @return Name of the class of the given object without package prefix
+     */
+    private String getClassBaseName(Object obj) {
+        if (obj == null) return null;
+        String className = obj.getClass().getName();
+        int index = className.lastIndexOf('.');
+        if (index != -1) {
+            className = className.substring(index + 1);
+        }
+        return className;
+    }
+        
+}
+
+

Added: incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/Container.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/Container.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/Container.java (added)
+++ incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/Container.java Sun May 22 11:40:13 2005
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.jdo.test.util;
+
+import java.util.*;
+
+import javax.jdo.*;
+
+import javax.transaction.*;
+import javax.transaction.xa.*;
+
+import org.apache.jdo.ejb.EJBHelper;
+import org.apache.jdo.ejb.EJBImplHelper;
+import org.apache.jdo.impl.fostore.FOStorePMF;
+import org.apache.jdo.impl.pm.PersistenceManagerWrapper;
+import org.apache.jdo.pm.PersistenceManagerFactoryInternal;
+import org.apache.jdo.pm.PersistenceManagerInternal;
+import org.apache.jdo.store.Connector;
+
+/**
+ * Helper container to simulate test in a managed environment
+ * @author Marina Vatkina
+ */
+
+public class Container implements EJBHelper {
+    
+    Vector pmfs = new Vector();
+    PersistenceManagerFactory pmf0 = null;
+    PersistenceManagerInternal pm = null;
+    GlobalTx globaltx = null;
+    UserTx usertx = null;
+    final boolean verbose;
+    
+    /** Register this container with EJBImplHelper
+     */
+    public Container(boolean verbose) {
+        this.verbose = verbose;
+        EJBImplHelper.registerEJBHelper (this);
+    }
+    
+    /** Get new PersistenceManagerFactory
+     */
+    public PersistenceManagerFactory getPMF(String url)
+    {
+        // RESOLVE:
+        FOStorePMF pmf = new FOStorePMF();
+        pmf.setConnectionURL (url);
+        ((FOStorePMF)pmf).setConnectionCreate ("true");
+        pmf.setConnectionUserName("");
+        pmf.setConnectionPassword("");
+        pmf.setOptimistic(false);
+        
+        return pmf;
+    }
+
+    /** Start CMT transaction
+     */
+    public void startCMT() {
+        globaltx = new GlobalTx();
+    }
+
+    /** Start BMT transaction
+     */
+    public void startBMT() {
+        if (usertx == null) {
+            usertx = new UserTx();
+        }
+    }
+
+    /** Finish BMT transaction
+     */
+    public void finishBMT() {
+        usertx = null;
+    }
+
+    /** Commit CMT transaction. Rollback transaction if commit fails.
+     */
+    public void finishCMT(boolean commit) {
+        try {
+            if (commit) globaltx.commit();
+            else throw new Exception("FORCING ROLLBACK");
+        } catch (Exception e) {
+            if (verbose) System.err.println ("finishCMT IN COMMIT: " + e.getMessage());
+            try {
+                globaltx.setRollbackOnly();
+                globaltx.rollback();
+            } catch (Exception e1) {
+                if (verbose) System.err.println ("finishCMT IN ROLLBACK: " + e1);
+                e1.printStackTrace();
+            }
+        }
+        globaltx = null;
+    }
+
+    //
+    // --- Implementation of EJBHelper interface ----
+    //
+
+    public javax.transaction.Transaction getTransaction(){
+        return globaltx;
+    }
+
+    public UserTransaction getUserTransaction() {
+        return usertx;
+    }
+
+    public int translateStatus(int st) {
+        return st;
+    }
+
+    public PersistenceManagerFactory replacePersistenceManagerFactory(
+        PersistenceManagerFactory pmf) {
+        try {
+            Iterator it = pmfs.iterator();
+            while (it.hasNext()) {
+                Object o = it.next();
+                if (o.equals(pmf)) {
+                    pmf0 = (PersistenceManagerFactory) o;
+                    return pmf0;
+                }
+            }
+            pmfs.add(pmf); // not found
+            pmf0 = pmf;
+            return pmf;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new JDOFatalInternalException("", e);  //NOI18N
+        }
+    }
+
+    public Object enlistBeforeCompletion(Object component) {
+        return null;
+    }
+
+    public void delistBeforeCompletion(Object im) {
+    }
+
+    //
+    // --- End implementation of EJBHelper interface ----
+    //
+
+    protected Connector getConnector() {
+        PersistenceManager pm = pmf0.getPersistenceManager();
+        return ((PersistenceManagerFactoryInternal)pmf0).
+            getStoreManager(pm).getConnector();
+    }
+
+    /**
+     * Unregisters this EJBHelper and returns the delegate PMF.
+     */
+    public PersistenceManagerFactory close()
+    {
+        EJBImplHelper.registerEJBHelper(null);
+        return pmf0;
+    }
+
+    /**
+     * Class that simulates JTA Transaction
+     */
+    class GlobalTx implements javax.transaction.Transaction {
+    
+        Synchronization sync = null;
+        int st = Status.STATUS_ACTIVE;
+        Connector conn = null;
+
+        public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+            java.lang.SecurityException, SystemException {
+            try {
+                sync.beforeCompletion();
+                st = Status.STATUS_PREPARED;
+    
+                conn = getConnector();
+                conn.commit();
+                conn = null;
+                pm = null;
+    
+                st = Status.STATUS_COMMITTED;
+                sync.afterCompletion(st);
+    
+            } catch (Exception e) {
+                e.printStackTrace();
+                st = Status.STATUS_MARKED_ROLLBACK;
+                this.rollback();
+                throw new SystemException(e.toString());
+            }
+        }
+    
+        public boolean delistResource(XAResource xaRes, int flag)
+            throws java.lang.IllegalStateException, SystemException{
+            return false;
+        }
+    
+        public boolean enlistResource(XAResource xaRes)
+            throws RollbackException, java.lang.IllegalStateException, SystemException {
+            return false; 
+        }
+    
+        public int getStatus() throws SystemException {
+            return st;
+        }
+    
+        public void registerSynchronization(Synchronization sync)
+            throws RollbackException, java.lang.IllegalStateException, SystemException {
+            this.sync = sync;
+        }
+    
+        public void rollback() throws java.lang.IllegalStateException, SystemException {
+            if (st == Status.STATUS_ACTIVE) {
+                st = Status.STATUS_ROLLING_BACK;
+            }
+            try {
+                if (conn == null) {
+                    conn = getConnector();
+                }
+                conn.rollback();
+                conn = null;
+                pm = null;
+    
+                st = Status.STATUS_ROLLEDBACK;
+                sync.afterCompletion(st);
+    
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new SystemException(e.toString());
+            }
+        }
+    
+        public void setRollbackOnly() throws java.lang.IllegalStateException, SystemException {
+            st = Status.STATUS_MARKED_ROLLBACK;
+        }
+
+    }
+   
+    /**
+     * Class that simulates JTA UserTransaction
+     */
+    class UserTx implements UserTransaction {
+
+        public void begin() throws NotSupportedException, SystemException {
+            if (globaltx == null) {
+                globaltx = new GlobalTx();
+            }
+        }
+
+        public void commit() throws RollbackException, HeuristicMixedException,
+            HeuristicRollbackException, java.lang.SecurityException,
+            java.lang.IllegalStateException, SystemException {
+
+            globaltx.commit();
+            globaltx = null;
+        }
+
+        public void rollback() throws java.lang.IllegalStateException,
+            java.lang.SecurityException, SystemException {
+            globaltx.rollback(); 
+            globaltx = null;
+        }
+    
+        public void setRollbackOnly() throws java.lang.IllegalStateException, SystemException {
+            globaltx.setRollbackOnly();
+        }
+    
+        public int getStatus() throws SystemException {
+            return globaltx.getStatus();
+        }
+    
+        public void setTransactionTimeout(int seconds) throws SystemException { }
+    }
+   
+}

Added: incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/DumpExtent.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/DumpExtent.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/DumpExtent.java (added)
+++ incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/DumpExtent.java Sun May 22 11:40:13 2005
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.jdo.test.util;
+
+import java.util.*;
+
+import javax.jdo.*;
+
+import org.apache.jdo.test.util.AbstractTest;
+import org.apache.jdo.test.util.JDORITestRunner;
+
+/**
+* This test retrieves an extent-full of instances.
+*
+* @author Dave Bristor
+*/
+public class DumpExtent extends AbstractTest {
+
+    /** If true, get subclass instances too. */
+    private final boolean subclasses;
+
+    /** class names */
+    private final String classNames;
+    
+    /** */
+    public static void main(String args[]) {
+        new DumpExtent().start();
+    }
+
+    /** */
+    public DumpExtent() {
+        super();
+        this.subclasses = Boolean.getBoolean("subclasses");
+        this.classNames = System.getProperty("class", "org.apache.jdp.pc.PCPoint");
+        this.existing = true;
+    }
+
+    /** */
+    public void start() {
+        PersistenceManager pm = null;
+        try {
+            setUp();
+            pm = pmf.getPersistenceManager();
+            dumpExtents(pm, getClassList());
+        }
+        catch (Exception ex) {
+            logger.debug("caught " + ex);
+        }
+        finally {
+            if (pm != null && !pm.isClosed())
+                pm.close();
+            tearDown();
+        }
+    }
+
+    /** */
+    protected List getClassList() {
+        List classes = new ArrayList();
+        StringTokenizer st = new StringTokenizer(classNames, ",");
+        while (st.hasMoreElements()) {
+            String className = (String)st.nextElement();
+            try {
+                classes.add(Class.forName(className));
+            } catch (ClassNotFoundException ex) {
+                logger.debug("Could not load specified class " + className);
+            }
+        }
+        return classes;
+    }
+
+    /** */
+    protected void dumpExtents(PersistenceManager pm, List classes) {
+        for (Iterator i = classes.iterator(); i.hasNext();) {
+            dumpExtent(pm, (Class)i.next());
+        }
+    }
+    
+    /** */
+    protected void dumpExtent(PersistenceManager pm, Class clazz) {
+        logger.debug("\nEXTENT of " + clazz.getName());
+        Extent e = pm.getExtent(clazz, subclasses);
+        int objCount = 0;
+        TreeSet elements = new TreeSet();
+        for (Iterator i = e.iterator(); i.hasNext();) {
+            Object pc = i.next();
+            elements.add(pc.toString());
+            objCount++;
+        }
+        for (Iterator k = elements.iterator(); k.hasNext();) {
+            logger.debug((String)k.next());
+        }
+        logger.debug("extent of " + clazz.getName() + " has " +
+                     objCount + " objects");
+    }
+}

Added: incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/Factory.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/Factory.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/Factory.java (added)
+++ incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/Factory.java Sun May 22 11:40:13 2005
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.jdo.test.util;
+
+/**
+* Provides a means to create objects that are inserted into a database, and
+* for verifying that they've been retrieved OK.
+*
+* @author Dave Bristor
+*/
+public interface Factory {
+    /**
+    * Returns the class instance of the pc class of this factory.
+    */
+    public Class getPCClass();
+
+    /**
+    * Returns a new PC.  The index is for the implementation's own use.
+    */
+    public Object create(int index);
+
+    /**
+    * Provides a factory with a value which can be used to create instances.
+    */
+    public void setVerify(int size);
+    
+    /**
+    * Returns true if the PC instances is OK.
+    */
+    public boolean verify(int i, Object pc);
+}

Added: incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/JDORITestRunner.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/JDORITestRunner.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/JDORITestRunner.java (added)
+++ incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/JDORITestRunner.java Sun May 22 11:40:13 2005
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.jdo.test.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.io.PrintStream;
+import java.util.Arrays;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+import junit.textui.ResultPrinter;
+import junit.textui.TestRunner;
+
+/**
+ * TestRunner class for running a single test or a test suite in batch
+ * mode. The format of the test output is specified by the result printer
+ * class. The main method sets an exit code according to the test result:
+ * <ul>
+ * <li><code>0</code>: success
+ * <li><code>1</code>: failure, the test shows an unexpected behavior
+ * <li><code>2</code>: exception, the test throws an unhandled excption 
+ * </ul>
+ * 
+ * @author Michael Bouschen
+ */
+public class JDORITestRunner
+    extends TestRunner
+{
+    /** Name of the system property to specify the result printer class. */
+    public static final String RESULTPRINTER_PROPERTY = "ResultPrinterClass"; 
+    
+    /** Default of the system property ResultPrinterClass. */
+    public static final String RESULTPRINTER_DEFAULT = BatchResultPrinter.class.getName();
+    
+    /** 
+     * Constructor. 
+     * It creates a result printer instance based on the system property
+     * and delegates to the constructor taking a result printer argument. 
+     */
+    public JDORITestRunner() {
+        super();
+        setPrinter(getResultPrinter());
+    }
+    
+    /**  
+     * Constructor. Uses the specified resultPrinter to format the test result.
+     */
+    public JDORITestRunner(ResultPrinter resultPrinter) {
+        super(resultPrinter);
+    }
+
+    /** Runs all test methods from the specified class. */
+    public static void run(Class clazz) {
+        run(new TestSuite(clazz));
+    }
+    
+    /** Runs the specified test. */
+    public static TestResult run(Test test) {
+        return new JDORITestRunner().doRun(test);
+    }
+
+    /** Runs the specified test and waits until the user types RETURN. */
+    public static void runAndWait(Test suite) {
+        new JDORITestRunner().doRun(suite, true);
+    }
+
+    /** 
+     * Runs in batch mode and sets an exit code. If the specified String
+     * array includes a single fully qualified class name, this test class
+     * is executed. If it is empty it runs the TestListSuite.
+     */
+    public static void main(String args[]) {
+        try {
+            TestResult r = new JDORITestRunner().start(args);
+            if (!r.wasSuccessful()) 
+                System.exit(FAILURE_EXIT);
+            System.exit(SUCCESS_EXIT);
+        } catch(Exception e) {
+            System.err.println(e.getMessage());
+            System.exit(EXCEPTION_EXIT);
+        }
+    }
+
+    /** */
+    public TestResult start(String[] args) {
+        Test suite = null;
+        if ((args == null) || args.length == 0) {
+            suite = getTest(TestListSuite.class.getName());
+        }
+        else if (args.length == 1) {
+            suite = getTest(args[0]);
+        }
+        else {
+            suite = new TestListSuite("JDO TCK", Arrays.asList(args));
+        }
+        return doRun(suite);
+    }
+
+    /** 
+     * Returns a result printer instance. The system property
+     * ResultPrinterClass specifies the class of the returned instanec. The
+     * class must extend junit.textui.ResultPrinter.
+     */
+    protected ResultPrinter getResultPrinter() {
+        String className =  System.getProperty(RESULTPRINTER_PROPERTY);
+        if (className != null) {
+            className = className.trim();
+            if (className.length() != 0) {
+                String msg = null;
+                try {
+                    // get class instance
+                    Class clazz = Class.forName(className);
+                    // constructor taking PrintStream arg
+                    Constructor ctor = clazz.getConstructor(
+                        new Class[] { PrintStream.class } );
+                    // create instance
+                    return (ResultPrinter)ctor.newInstance(
+                        new Object[] { System.out });
+                }
+                catch (ClassNotFoundException ex) {
+                    // specified ResultPrinter class not 
+                    msg = "Cannot find specified result printer class " + 
+                        className + ".";
+                }
+                catch (NoSuchMethodException ex) {
+                    msg = "Class " + className + 
+                        " does not provide constructor taking a PrintStream.";
+                }
+                catch (InstantiationException ex) {
+                    msg = "Class " + className + " is abstract.";
+                }
+                catch (IllegalAccessException ex) {
+                    msg = "Constructor taking a PrintStream of class " + 
+                        className + " is not accessible.";
+                }
+                catch (InvocationTargetException ex) {
+                    msg = "Constructor call results in exception " + ex + ".";
+                }
+
+                // ResultPrinter class specified, but not avaiable
+                System.out.println(msg);
+                ResultPrinter printer = getDefaultResultPrinter();
+                System.out.println("Using default result printer of class " + 
+                                   printer.getClass().getName());
+            }
+        }
+        
+        // ResultPrinter class not specified => use default
+        return getDefaultResultPrinter();
+    }
+
+    /** 
+     * Returns an instance of the default result printer class
+     * BatchResultPrinter.
+     */
+    protected ResultPrinter getDefaultResultPrinter() {
+        return new BatchResultPrinter(System.out);
+    }
+}

Added: incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/OIDComparator.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/OIDComparator.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/OIDComparator.java (added)
+++ incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/OIDComparator.java Sun May 22 11:40:13 2005
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.jdo.test.util;
+
+import java.util.Comparator;
+
+import org.apache.jdo.impl.fostore.OID;
+
+public class OIDComparator implements Comparator {
+    public int compare(Object o1, Object o2) {
+        // Please note, 
+        //   return (int)(((OID)o1).oid - ((OID)o2).oid);
+        // does not work, because the difference might exceed the int range
+        // and then the cast to an int returns unwanted results.
+        long oid1 = ((OID)o1).oid;
+        long oid2 = ((OID)o2).oid;
+        if (oid1 == oid2) return 0;
+        else if (oid1 > oid2) return 1;
+        else return -1;
+    }
+
+    public boolean equals(Object obj) {
+        return obj.equals(this);
+    }
+}

Added: incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/SwingTestRunner.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/SwingTestRunner.java?rev=171355&view=auto
==============================================================================
--- incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/SwingTestRunner.java (added)
+++ incubator/jdo/trunk/fostore20/test/java/org/apache/jdo/test/util/SwingTestRunner.java Sun May 22 11:40:13 2005
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.jdo.test.util;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.swing.JCheckBox;
+import javax.swing.JOptionPane;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import junit.swingui.TestRunner;
+
+/**
+ * TestRunner class for running a single test or a test suite in GUI mode
+ * using swing.
+ *
+ * @author Michael Bouschen
+ */
+public class SwingTestRunner
+    extends TestRunner
+{
+    /** */
+    private static final String TESTCOLLECTOR_KEY= "TestCollectorClass";
+    
+    /** */
+    private static final String USER_DEFINED = "User defined test list";
+    
+    /** */
+    private Test suite = null;
+
+    /** */
+    public SwingTestRunner() {
+        super();
+        setPreference(TESTCOLLECTOR_KEY, TestListSuite.class.getName());
+        // Disable feature: reloading of test classes every run.
+        setPreference("loading", "false");
+    }
+
+    /** */
+    public static void main(String[] args) {
+        new SwingTestRunner().start(args);
+    }
+    
+    /** */
+    public static void run(Class test) {
+        main(new String[] { test.getName() });
+    }
+
+    /** */
+    public void start(String[] args) {
+        String suiteName = "JDO TCK";
+        fFrame = createUI(suiteName);
+        fFrame.pack();
+        fFrame.setVisible(true);
+        if ((args == null) || args.length == 0) {
+            suite = getTest(TestListSuite.class.getName());
+        }
+        else if (args.length == 1) {
+            suiteName = args[0];
+            suite = getTest(args[0]);
+        }
+        else {
+            suite = new TestListSuite(suiteName, Arrays.asList(args));
+        }
+        setSuite(suiteName);
+        runTest(suite);
+    }
+
+    /** Disable feature: reloading of test classes every run. */
+    protected JCheckBox createUseLoaderCheckBox() {
+        JCheckBox box = super.createUseLoaderCheckBox();
+        box.setVisible(false);
+        return box;
+    }
+    
+    /** */
+    public void browseTestClasses() {
+        TestSelector selector= new TestSelector(fFrame, new TestListSuite("JDO TCK test selection"));
+        if (selector.isEmpty()) {
+            JOptionPane.showMessageDialog(fFrame, "No Test Cases found.\nCheck that the configured \'TestCollector\' is supported on this platform.");
+            return;
+        }
+        selector.show();
+        List classNames = selector.getSelectedItems();
+        if ((classNames != null) && (!classNames.isEmpty())) {
+            if (classNames.size() == 1) {
+                setSuite((String)classNames.get(0));
+            }
+            else {
+                setSuite(USER_DEFINED);
+                suite = new TestListSuite("Selected JDORI tests", classNames);
+            } 
+        }
+    }
+    
+    /** */
+    public Test getTest(String suiteClassName) {
+        if ((suiteClassName != null ) && suiteClassName.equals(USER_DEFINED)) {
+            if (suite == null) {
+                // user selected 'User defines test list' from history, 
+                // but there is no user selection => use all tests   
+                suite = new TestListSuite("JDORI tests");
+            }
+            return suite;
+        }
+        return super.getTest(suiteClassName);
+    }
+        
+    /**
+     * Terminates the TestRunner
+     */
+    public void terminate() {
+        fFrame.dispose();
+        System.exit(0);
+    }
+}