Index: test/java/org/apache/jdo/tck/query/delete/DeleteCallback.java =================================================================== --- test/java/org/apache/jdo/tck/query/delete/DeleteCallback.java (Revision 0) +++ test/java/org/apache/jdo/tck/query/delete/DeleteCallback.java (Revision 0) @@ -0,0 +1,395 @@ +/* + * 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.tck.query.delete; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; + +import javax.jdo.JDOHelper; +import javax.jdo.PersistenceManager; +import javax.jdo.Query; +import javax.jdo.Transaction; +import javax.jdo.listener.DeleteLifecycleListener; +import javax.jdo.listener.InstanceLifecycleEvent; +import javax.jdo.listener.StoreLifecycleListener; + +import org.apache.jdo.tck.JDO_Test; +import org.apache.jdo.tck.pc.company.CompanyModelReader; +import org.apache.jdo.tck.pc.company.Person; +import org.apache.jdo.tck.pc.mylib.MylibReader; +import org.apache.jdo.tck.pc.mylib.PrimitiveTypes; +import org.apache.jdo.tck.query.QueryElementHolder; +import org.apache.jdo.tck.query.QueryTest; +import org.apache.jdo.tck.util.BatchTestRunner; +import org.apache.jdo.tck.util.ConversionHelper; + +/** + *Title: Delete Persistent All. + *
+ *Keywords: query + *
+ *Assertion ID: A14.8-4 + *
+ *Assertion Description: + * Dirty instances of affected classes are first flushed to the datastore. + * Instances already in the cache when deleted via these methods + * or brought into the cache as a result of these methods + * undergo the life cycle transitions as if deletePersistent + * had been called on them. + * That is, if an affected class implements the DeleteCallback interface, + * the instances to be deleted are instantiated in memory and + * the jdoPreDelete method is called prior + * to deleting the instance in the datastore. + * If any LifecycleListener instances are registered with affected classes, + * these listeners are called for each deleted instance. + * Before returning control to the application, + * instances of affected classes in the cache are refreshed + * by the implementation so their status in the cache reflects + * whether they were deleted from the datastore. + */ +public class DeleteCallback extends QueryTest { + + /** */ + private static final String ASSERTION_FAILED = + "Assertion A14.8-4 (DeleteCallback) failed: "; + + /** + * The array of valid queries which may be executed as + * single string queries and as API queries. + */ + private static final QueryElementHolder[] VALID_QUERIES = { + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ null, + /*INTO*/ null, + /*FROM*/ Person.class, + /*EXCLUDE*/ null, + /*WHERE*/ null, + /*VARIABLES*/ null, + /*PARAMETERS*/ null, + /*IMPORTS*/ null, + /*GROUP BY*/ null, + /*ORDER BY*/ null, + /*FROM*/ null, + /*TO*/ null), + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ null, + /*INTO*/ null, + /*FROM*/ PrimitiveTypes.class, + /*EXCLUDE*/ null, + /*WHERE*/ null, + /*VARIABLES*/ null, + /*PARAMETERS*/ null, + /*IMPORTS*/ null, + /*GROUP BY*/ null, + /*ORDER BY*/ null, + /*FROM*/ null, + /*TO*/ null) + }; + + /** + * The expected results of valid queries. + */ + private List[] expectedResult = { + getCompanyModelInstancesAsList(new String[]{ + "emp1", "emp2", "emp3", "emp4", "emp5"}), + getMylibInstancesAsList(new String[]{ + "primitiveTypesPositive", + "primitiveTypesNegative", + "primitiveTypesCharacterStringLiterals"}) + }; + + /** + * The main is called when the class + * is directly executed from the command line. + * @param args The arguments passed to the program. + */ + public static void main(String[] args) { + BatchTestRunner.run(DeleteCallback.class); + } + + /** */ + public void testRelationshipsAPI() { + queryUpdateDeleteVerify(0, "middlename", false); + } + + /** */ + public void testRelationshipsSingleString() { + queryUpdateDeleteVerify(0, "middlename", true); + } + + /** */ + public void testNoRelationshipsAPI() { + queryUpdateDeleteVerify(1, "stringNull", false); + } + + /** */ + public void testNoRelationshipsSingleString() { + queryUpdateDeleteVerify(1, "stringNull", true); + } + + /** + * @see JDO_Test#localSetUp() + */ + protected void localSetUp() { + loadCompanyModel(getPM(), COMPANY_TESTDATA); + addTearDownClass(CompanyModelReader.getTearDownClasses()); + loadMylib(getPM(), MYLIB_TESTDATA); + addTearDownClass(MylibReader.getTearDownClasses()); + } + + /** + * Adds a lifecycle listener to the persistence manager. + * Converts the query element holder instance refered to by argument + * index to a JDO query instance based on argument + * asSingleString. + * Executes the query instance and makes dirty all queried pc instances + * calling {@link JDOHelper#makeDirty(java.lang.Object, java.lang.String)}. + * Passes argument fieldName to that call. + * Afterwards, calls {@link Query#deletePersistentAll()}, and + * verifies the lifecycle callbacks and the lifecycle states. + * @param index the index of the query element hoplder instance + * @param fieldName the field name passed as argument to + * {@link JDOHelper#makeDirty(java.lang.Object, java.lang.String) + * @param asSingleString determines if the query is executed as + * single string query or as API query. + */ + private void queryUpdateDeleteVerify(int index, + String fieldName, boolean asSingleString) { + PersistenceManager pm = getPM(); + Transaction transaction = pm.currentTransaction(); + transaction.begin(); + try + { + LifecycleVerifyer lifecycleVerifyer; + + // query, check result, update + Query query = asSingleString ? + VALID_QUERIES[index].getSingleStringQuery(pm) : + VALID_QUERIES[index].getAPIQuery(pm); + if (logger.isDebugEnabled()) { + if (asSingleString) { + logger.debug("Executing single string query: " + + VALID_QUERIES[index]); + } else { + logger.debug("Executing API query: " + + VALID_QUERIES[index]); + } + } + Collection result = (Collection) query.execute(); + try { + if (logger.isDebugEnabled()) { + logger.debug("Query result: " + ConversionHelper. + convertObjectArrayElements(result)); + } + checkQueryResultWithoutOrder(ASSERTION_FAILED, result, expectedResult[index]); + + // add lifecycle listener + lifecycleVerifyer = new LifecycleVerifyer(result); + pm.addInstanceLifecycleListener(lifecycleVerifyer, + new Class[]{VALID_QUERIES[index].getCandidateClass()}); + + // update + for (Iterator i = result.iterator(); i.hasNext(); ) { + Object pc = i.next(); + if (logger.isDebugEnabled()) { + logger.debug("Calling JDOHelper.makeDirty(" + + pc + ", \"" + fieldName + "\")"); + } + JDOHelper.makeDirty(pc, fieldName); + } + } finally + { + query.close(result); + } + + // delete + if (logger.isDebugEnabled()) { + if (asSingleString) { + logger.debug("Deleting persistent by single string query: " + + VALID_QUERIES[index]); + } else { + logger.debug("Deleting persistent by API query: " + + VALID_QUERIES[index]); + } + } + long nr = query.deletePersistentAll(); + if (logger.isDebugEnabled()) { + logger.debug(nr + " objects deleted."); + } + + // verify + if (logger.isDebugEnabled()) { + logger.debug("Verifying callbacks and states."); + } + lifecycleVerifyer.verifyCallbacksAndStates(); + } finally { + if (transaction.isActive()) { + transaction.rollback(); + } + } + } + + /** + * A lifecycle listener which may be added to persistence managers. + * Gathers delete events and store events and keeps those + * in a list. + * Method {@link LifecycleVerifyer#verifyCallbacksAndStates()} + * may be called to check if the right events have been called + * on all expected instances. + * The expected instances are passed through + * {@link LifecycleVerifyer#LifecycleVerifyer(Collection). + */ + private class LifecycleVerifyer + implements DeleteLifecycleListener, StoreLifecycleListener { + + /** The oids of expected pc instances. */ + private Collection expectedOids = new HashSet(); + + /** The list of events. */ + private List events = new ArrayList(); + + /** + * Argument expectedPCInstances holds pc instances + * which are expected to be sources of events. + * @param expectedPCInstances the pc instances + * which are expected to be sources of events. + */ + public LifecycleVerifyer(Collection expectedPCInstances) { + for (Iterator i = expectedPCInstances.iterator(); i.hasNext(); ) { + this.expectedOids.add(JDOHelper.getObjectId(i.next())); + } + } + + /** + * Verifies if the right events have been called for all + * expected pc instances. + * All store events must have been fired before the + * first delete event has been fired. + * Furthermore, checks if pc instances kept in + * delete events have state persistent-deleted. + * The test case fails if one of these conditions + * is violated. + */ + public void verifyCallbacksAndStates() { + // The two collections are filled iterating through the list of + // events. Finally, they are compared against field expectedOids. + // Note: Set implementations are used instead of list + // implementations two eliminate duplicates. Duplicates may occur + // if multiple updates or deletions are executed for the same + // pc instances. + Collection oidsOfDeletedInstances = new HashSet(); + Collection oidsOfUpdateInstances = new HashSet(); + + boolean hasDeleteEventBeenPassed = false; + int size = events.size(); + for (int i = 0; i < size; i++) { + InstanceLifecycleEvent event = + (InstanceLifecycleEvent) this.events.get(i); + Object source = event.getSource(); + int eventType = event.getEventType(); + if (eventType == InstanceLifecycleEvent.DELETE) { + if (logger.isDebugEnabled()) { + logger.debug("Verifying delete event on " + + JDOHelper.getObjectId(source)); + } + hasDeleteEventBeenPassed = true; + if (!JDOHelper.isDeleted(source)) { + fail(ASSERTION_FAILED, + "PC instance must have persistent deleted " + + "state: " + source); + } + oidsOfDeletedInstances.add(JDOHelper.getObjectId(source)); + } else if (eventType == InstanceLifecycleEvent.STORE) { + if (logger.isDebugEnabled()) { + logger.debug("Verifying store event on " + + JDOHelper.getObjectId(source)); + } + + if (hasDeleteEventBeenPassed) { + fail(ASSERTION_FAILED, + "PC instances must not be flushed " + + "after delete has been executed."); + } + oidsOfUpdateInstances.add(JDOHelper.getObjectId(source)); + } + } + + if (!equalsCollection(oidsOfDeletedInstances, + this.expectedOids)) { + String lf = System.getProperty("line.separator"); + fail(ASSERTION_FAILED, "Got delete events on " + + oidsOfDeletedInstances + lf + + "Expected deleted events on " + + this.expectedOids); + } else if (!equalsCollection(oidsOfUpdateInstances, + this.expectedOids)) { + String lf = System.getProperty("line.separator"); + fail(ASSERTION_FAILED, "Got store events on " + + oidsOfUpdateInstances + lf + + "Expected store events on " + + this.expectedOids); + } + } + + /** + * @see DeleteLifecycleListener#preDelete(javax.jdo.listener.InstanceLifecycleEvent) + */ + public void preDelete(InstanceLifecycleEvent event) { + if (logger.isDebugEnabled()) { + logger.debug("preDelete event: " + + JDOHelper.getObjectId(event.getSource())); + } + } + + /** + * @see DeleteLifecycleListener#postDelete(javax.jdo.listener.InstanceLifecycleEvent) + */ + public void postDelete(InstanceLifecycleEvent event) { + this.events.add(event); + if (logger.isDebugEnabled()) { + logger.debug("postDelete event: " + + JDOHelper.getObjectId(event.getSource())); + } + } + + /** + * @see StoreLifecycleListener#preStore(javax.jdo.listener.InstanceLifecycleEvent) + */ + public void preStore(InstanceLifecycleEvent event) { + if (logger.isDebugEnabled()) { + logger.debug("preStore event: " + + JDOHelper.getObjectId(event.getSource())); + } + } + + /** + * @see StoreLifecycleListener#postStore(javax.jdo.listener.InstanceLifecycleEvent) + */ + public void postStore(InstanceLifecycleEvent event) { + this.events.add(event); + if (logger.isDebugEnabled()) { + logger.debug("postStore event: " + + JDOHelper.getObjectId(event.getSource())); + } + } + } +} Index: test/java/org/apache/jdo/tck/query/delete/DeleteQueryElements.java =================================================================== --- test/java/org/apache/jdo/tck/query/delete/DeleteQueryElements.java (Revision 0) +++ test/java/org/apache/jdo/tck/query/delete/DeleteQueryElements.java (Revision 0) @@ -0,0 +1,230 @@ +/* + * 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.tck.query.delete; + +import java.math.BigDecimal; + +import org.apache.jdo.tck.JDO_Test; +import org.apache.jdo.tck.pc.company.CompanyModelReader; +import org.apache.jdo.tck.pc.company.FullTimeEmployee; +import org.apache.jdo.tck.pc.company.Person; +import org.apache.jdo.tck.query.QueryElementHolder; +import org.apache.jdo.tck.query.QueryTest; +import org.apache.jdo.tck.query.result.classes.FullName; +import org.apache.jdo.tck.util.BatchTestRunner; + +/** + *Title: Delete Query Elements. + *
+ *Keywords: query + *
+ *Assertion ID: A14.8-3 + *
+ *Assertion Description: + * Query elements filter, parameters, imports, variables, + * and unique are valid in queries used for delete. + * Elements result, result class, range, grouping, and ordering are invalid. + * If any of these elements is set to its non-default value + * when one of the deletePersistentAll methods is called, + * a JDOUserException is thrown and no instances are deleted. + */ +public class DeleteQueryElements extends QueryTest { + + /** */ + private static final String ASSERTION_FAILED = + "Assertion A14.8-1 (DeleteQueryElements) failed: "; + + /** + * The array of valid queries which may be executed as + * single string queries and as API queries. + */ + private static final QueryElementHolder[] VALID_QUERIES = { + new QueryElementHolder( + /*UNIQUE*/ Boolean.TRUE, + /*RESULT*/ null, + /*INTO*/ null, + /*FROM*/ FullTimeEmployee.class, + /*EXCLUDE*/ null, + /*WHERE*/ "salary > 1000 & projects.contains(project) & " + + "project.budget > limit", + /*VARIABLES*/ "Project project", + /*PARAMETERS*/ "BigDecimal limit", + /*IMPORTS*/ "import org.apache.jdo.tck.pc.company.Project; " + + "import java.math.BigDecimal;", + /*GROUP BY*/ null, + /*ORDER BY*/ null, + /*FROM*/ null, + /*TO*/ null) + }; + + /** + * The array of invalid queries which may be executed as + * single string queries and as API queries. + */ + private static final QueryElementHolder[] INVALID_QUERIES = { + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ "firstname, lastname", + /*INTO*/ null, + /*FROM*/ Person.class, + /*EXCLUDE*/ null, + /*WHERE*/ null, + /*VARIABLES*/ null, + /*PARAMETERS*/ null, + /*IMPORTS*/ null, + /*GROUP BY*/ null, + /*ORDER BY*/ null, + /*FROM*/ null, + /*TO*/ null), + // The query may fail because there is a result class, or + // because there is a result class w/o result + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ null, + /*INTO*/ FullName.class, + /*FROM*/ Person.class, + /*EXCLUDE*/ null, + /*WHERE*/ null, + /*VARIABLES*/ null, + /*PARAMETERS*/ null, + /*IMPORTS*/ null, + /*GROUP BY*/ null, + /*ORDER BY*/ null, + /*FROM*/ null, + /*TO*/ null), + // The query may fail because there is a result, or + // because there is a result class + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ "firstname, lastname", + /*INTO*/ FullName.class, + /*FROM*/ Person.class, + /*EXCLUDE*/ null, + /*WHERE*/ null, + /*VARIABLES*/ null, + /*PARAMETERS*/ null, + /*IMPORTS*/ null, + /*GROUP BY*/ null, + /*ORDER BY*/ null, + /*FROM*/ null, + /*TO*/ null), + // The query may fail because there is a grouping clause, or + // because there is a grouping clause w/o result + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ null, + /*INTO*/ null, + /*FROM*/ Person.class, + /*EXCLUDE*/ null, + /*WHERE*/ null, + /*VARIABLES*/ null, + /*PARAMETERS*/ null, + /*IMPORTS*/ null, + /*GROUP BY*/ "lastname", + /*ORDER BY*/ null, + /*FROM*/ null, + /*TO*/ null), + // The query may fail because there is a result, or + // because there is a grouping clause + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ "lastname", + /*INTO*/ null, + /*FROM*/ Person.class, + /*EXCLUDE*/ null, + /*WHERE*/ null, + /*VARIABLES*/ null, + /*PARAMETERS*/ null, + /*IMPORTS*/ null, + /*GROUP BY*/ "lastname", + /*ORDER BY*/ null, + /*FROM*/ null, + /*TO*/ null), + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ null, + /*INTO*/ null, + /*FROM*/ Person.class, + /*EXCLUDE*/ null, + /*WHERE*/ null, + /*VARIABLES*/ null, + /*PARAMETERS*/ null, + /*IMPORTS*/ null, + /*GROUP BY*/ null, + /*ORDER BY*/ "lastname", + /*FROM*/ null, + /*TO*/ null), + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ null, + /*INTO*/ null, + /*FROM*/ Person.class, + /*EXCLUDE*/ null, + /*WHERE*/ null, + /*VARIABLES*/ null, + /*PARAMETERS*/ null, + /*IMPORTS*/ null, + /*GROUP BY*/ null, + /*ORDER BY*/ null, + /*FROM*/ "0", + /*TO*/ "5") + }; + + /** Parameters of valid queries. */ + private static Object[][] parameters = { + {new BigDecimal("1000")} + }; + + /** + * The main is called when the class + * is directly executed from the command line. + * @param args The arguments passed to the program. + */ + public static void main(String[] args) { + BatchTestRunner.run(DeleteQueryElements.class); + } + + /** */ + public void testAPI() { + int index = 0; + deletePersistentAllByAPIQuery(ASSERTION_FAILED, + VALID_QUERIES[index], parameters[index], 3); + } + + /** */ + public void testSingleString() { + int index = 0; + deletePersistentAllBySingleStringQuery(ASSERTION_FAILED, + VALID_QUERIES[index], parameters[index], 3); + } + + /** */ + public void testNegative() { + for (int i = 0; i < INVALID_QUERIES.length; i++) { + deletePersistentAllByAPIQuery(ASSERTION_FAILED, + INVALID_QUERIES[i], null, -1); + } + } + + /** + * @see JDO_Test#localSetUp() + */ + protected void localSetUp() { + loadCompanyModel(getPM(), COMPANY_TESTDATA); + addTearDownClass(CompanyModelReader.getTearDownClasses()); + } +} Index: test/java/org/apache/jdo/tck/query/delete/DeletePersistentAll.java =================================================================== --- test/java/org/apache/jdo/tck/query/delete/DeletePersistentAll.java (Revision 0) +++ test/java/org/apache/jdo/tck/query/delete/DeletePersistentAll.java (Revision 0) @@ -0,0 +1,145 @@ +/* + * 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.tck.query.delete; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.jdo.tck.JDO_Test; +import org.apache.jdo.tck.pc.company.CompanyModelReader; +import org.apache.jdo.tck.pc.company.Person; +import org.apache.jdo.tck.query.QueryElementHolder; +import org.apache.jdo.tck.query.QueryTest; +import org.apache.jdo.tck.util.BatchTestRunner; + +/** + *Title: Delete Persistent All. + *
+ *Keywords: query + *
+ *Assertion ID: A14.8-1, A14.8-2 + *
+ *Assertion Description: + * These methods delete the instances of affected classes + * that pass the filter, and all dependent instances. + * Affected classes are the candidate class and + * its persistence-capable subclasses. + * + * The number of instances of affected classes that were deleted is returned. + * Embedded instances and dependent instances are not counted + * in the return value. + */ +public class DeletePersistentAll extends QueryTest { + + /** */ + private static final String ASSERTION_FAILED = + "Assertion A14.8-1 (DeletePersistentAll) failed: "; + + /** + * The array of valid queries which may be executed as + * single string queries and as API queries. + */ + private static final QueryElementHolder[] VALID_QUERIES = { + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ null, + /*INTO*/ null, + /*FROM*/ Person.class, + /*EXCLUDE*/ null, + /*WHERE*/ null, + /*VARIABLES*/ null, + /*PARAMETERS*/ null, + /*IMPORTS*/ null, + /*GROUP BY*/ null, + /*ORDER BY*/ null, + /*FROM*/ null, + /*TO*/ null), + new QueryElementHolder( + /*UNIQUE*/ null, + /*RESULT*/ null, + /*INTO*/ null, + /*FROM*/ Person.class, + /*EXCLUDE*/ null, + /*WHERE*/ "firstname == param", + /*VARIABLES*/ null, + /*PARAMETERS*/ "String param", + /*IMPORTS*/ null, + /*GROUP BY*/ null, + /*ORDER BY*/ null, + /*FROM*/ null, + /*TO*/ null) + }; + + /** + * The main is called when the class + * is directly executed from the command line. + * @param args The arguments passed to the program. + */ + public static void main(String[] args) { + BatchTestRunner.run(DeletePersistentAll.class); + } + + /** */ + public void testNoParametersAPI() { + deletePersistentAllByAPIQuery(ASSERTION_FAILED, + VALID_QUERIES[0], null, 5); + } + + /** */ + public void testNoParametersSingleString() { + deletePersistentAllBySingleStringQuery(ASSERTION_FAILED, + VALID_QUERIES[0], null, 5); + } + + /** */ + public void testObjectArrayParametersAPI() { + Object[] parameters = new Object[] {"emp1First"}; + deletePersistentAllByAPIQuery(ASSERTION_FAILED, + VALID_QUERIES[1], parameters, 1); + } + + /** */ + public void testObjectArrayParametersSingleString() { + Object[] parameters = new Object[] {"emp1First"}; + deletePersistentAllBySingleStringQuery(ASSERTION_FAILED, + VALID_QUERIES[1], parameters, 1); + } + + /** */ + public void testMapParametersAPI() { + Map parameters = new HashMap(); + parameters.put("param", "emp1First"); + deletePersistentAllByAPIQuery(ASSERTION_FAILED, + VALID_QUERIES[1], parameters, 1); + } + + /** */ + public void testMapParametersSingleString() { + Map parameters = new HashMap(); + parameters.put("param", "emp1First"); + deletePersistentAllBySingleStringQuery(ASSERTION_FAILED, + VALID_QUERIES[1], parameters, 1); + } + + /** + * @see JDO_Test#localSetUp() + */ + protected void localSetUp() { + loadCompanyModel(getPM(), COMPANY_TESTDATA); + addTearDownClass(CompanyModelReader.getTearDownClasses()); + } +} Index: test/java/org/apache/jdo/tck/query/QueryTest.java =================================================================== --- test/java/org/apache/jdo/tck/query/QueryTest.java (Revision 348686) +++ test/java/org/apache/jdo/tck/query/QueryTest.java (Arbeitskopie) @@ -442,7 +442,7 @@ * @param o2 the second object * @return true if o1 and o2 equal. */ - private boolean equals(Object o1, Object o2) { + protected boolean equals(Object o1, Object o2) { boolean result; if (o1 == o2) { result = true; @@ -488,7 +488,7 @@ * @param o2 the second object array * @return true if o1 and o2 equal. */ - private boolean equalsObjectArray(Object[] o1, Object[] o2) { + protected boolean equalsObjectArray(Object[] o1, Object[] o2) { boolean result = true; if (o1 != o2) { if (o1.length != o2.length) { @@ -520,7 +520,7 @@ * @param o2 the second list * @return true if o1 and o2 equal. */ - private boolean equalsList(List o1, List o2) { + protected boolean equalsList(List o1, List o2) { boolean result = true; if (o1 != o2) { if (o1.size() != o2.size()) { @@ -553,7 +553,7 @@ * @param o2 the second collection * @return true if o1 and o2 equal. */ - private boolean equalsCollection(Collection o1, Collection o2) { + protected boolean equalsCollection(Collection o1, Collection o2) { boolean result = true; if (o1 != o2) { if (o1.size() != o2.size()) { @@ -583,7 +583,7 @@ * @param o2 the second map * @return true if o1 and o2 equal. */ - private boolean equalsMap(Map o1, Map o2) { + protected boolean equalsMap(Map o1, Map o2) { boolean result = true; if (o1 != o2) { if (o1.size() != o2.size()) { @@ -826,13 +826,13 @@ try { query.compile(); if (!positive) { - fail(assertion + + fail(assertion, "Query compilation must throw JDOUserException: " + queryText); } } catch (JDOUserException e) { if (positive) { - fail(assertion + "Query '" + queryText + + fail(assertion, "Query '" + queryText + "' must be compilable. The exception message is: " + e.getMessage()); } @@ -1009,7 +1009,7 @@ */ private Object execute(String assertion, QueryElementHolder queryElementHolder, boolean asSingleString, - Object[] parameters, Object expectedResult) { + Object parameters, Object expectedResult) { Query query = asSingleString ? queryElementHolder.getSingleStringQuery(pm) : queryElementHolder.getAPIQuery(pm); @@ -1120,15 +1120,24 @@ */ private Object execute(String assertion, Query query, String singleStringQuery, boolean hasOrdering, - Object[] parameters, Object expectedResult, boolean positive) { + Object parameters, Object expectedResult, boolean positive) { Object result = null; PersistenceManager pm = getPM(); Transaction tx = pm.currentTransaction(); tx.begin(); try { try { - result = parameters != null ? - query.executeWithArray(parameters) : query.execute(); + if (parameters == null) { + result = query.execute(); + } else if (parameters instanceof Object[]) { + result = query.executeWithArray((Object[])parameters); + } else if (parameters instanceof Map) { + result = query.executeWithMap((Map)parameters); + } else { + throw new IllegalArgumentException("Argument parameters " + + "must be instance of Object[], Map, or null."); + } + if (logger.isDebugEnabled()) { logger.debug("Query result: " + ConversionHelper. convertObjectArrayElements(result)); @@ -1143,7 +1152,7 @@ expectedResult); } } else { - fail(assertion + "Query must throw JDOUserException: " + + fail(assertion, "Query must throw JDOUserException: " + singleStringQuery); } } finally { @@ -1160,4 +1169,153 @@ } return result; } + + /** + * Converts the given query element holder instance to a + * JDO query instance. + * Calls {@link Query#deletePersistentAll()}, or + * {@link Query#deletePersistentAll(java.util.Map), or + * {@link Query#deletePersistentAll(java.lang.Object[]) + * depending on the type of argument parameters. + * If the number of deleted objects does not + * match expectedNrOfDeletedObjects, + * then the test case fails prompting argument assertion. + * @param assertion the assertion to prompt if the test case fails. + * @param queryElementHolder the query to execute. + * @param parameters the parmaters of the query. + * @param expectedNrOfDeletedObjects the expected number of deleted objects. + */ + protected void deletePersistentAllByAPIQuery(String assertion, + QueryElementHolder queryElementHolder, + Object parameters, long expectedNrOfDeletedObjects) { + if (logger.isDebugEnabled()) { + logger.debug("Deleting persistent by API query: " + + queryElementHolder); + } + delete(assertion, queryElementHolder, false, + parameters, expectedNrOfDeletedObjects); + } + + /** + * Converts the given query element holder instance to a + * JDO query instance. + * Calls {@link Query#deletePersistentAll()}, or + * {@link Query#deletePersistentAll(java.util.Map), or + * {@link Query#deletePersistentAll(java.lang.Object[]) + * depending on the type of argument parameters. + * If the number of deleted objects does not + * match expectedNrOfDeletedObjects, + * then the test case fails prompting argument assertion. + * @param assertion the assertion to prompt if the test case fails. + * @param queryElementHolder the query to execute. + * @param parameters the parmaters of the query. + * @param expectedNrOfDeletedObjects the expected number of deleted objects. + */ + protected void deletePersistentAllBySingleStringQuery(String assertion, + QueryElementHolder queryElementHolder, + Object parameters, long expectedNrOfDeletedObjects) { + if (logger.isDebugEnabled()) { + logger.debug("Deleting persistent by single string query: " + + queryElementHolder); + } + delete(assertion, queryElementHolder, true, + parameters, expectedNrOfDeletedObjects); + } + + /** + * Converts the given query element holder instance to a + * JDO query based on argument asSingleString. + * Calls {@link Query#deletePersistentAll()}, or + * {@link Query#deletePersistentAll(java.util.Map), or + * {@link Query#deletePersistentAll(java.lang.Object[]) + * depending on the type of argument parameters. + * If the number of deleted objects does not + * match expectedNrOfDeletedObjects, + * then the test case fails prompting argument assertion. + * @param assertion the assertion to prompt if the test case fails. + * @param queryElementHolder the query to execute. + * @param asSingleString determines if the query is executed as + * single string query or as API query. + * @param parameters the parmaters of the query. + * @param expectedNrOfDeletedObjects the expected number of deleted objects. + */ + private void delete(String assertion, + QueryElementHolder queryElementHolder, boolean asSingleString, + Object parameters, long expectedNrOfDeletedObjects) { + Query query = asSingleString ? + queryElementHolder.getSingleStringQuery(pm) : + queryElementHolder.getAPIQuery(pm); + delete(assertion, query, queryElementHolder.toString(), + parameters, expectedNrOfDeletedObjects); + boolean positive = expectedNrOfDeletedObjects >= 0; + if (positive) { + execute(assertion, queryElementHolder, asSingleString, parameters, + queryElementHolder.isUnique() ? null : new ArrayList()); + } + } + + /** + * Calls {@link Query#deletePersistentAll()}, or + * {@link Query#deletePersistentAll(java.util.Map), or + * {@link Query#deletePersistentAll(java.lang.Object[]) + * depending on the type of argument parameters. + * If the number of deleted objects does not + * match expectedNrOfDeletedObjects, + * then the test case fails prompting argument assertion. + * Argument singleStringQuery is only used as part + * of the failure message. + * @param assertion the assertion to prompt if the test case fails. + * @param query the query to execute. + * @param singleStringQuery the single string representation of the query. + * @param parameters the parmaters of the query. + * @param expectedNrOfDeletedObjects the expected number of deleted objects. + */ + private void delete(String assertion, Query query, + String singleStringQuery, Object parameters, + long expectedNrOfDeletedObjects) { + boolean positive = expectedNrOfDeletedObjects >= 0; + PersistenceManager pm = getPM(); + Transaction tx = pm.currentTransaction(); + tx.begin(); + try { + try { + long nr; + if (parameters == null) { + nr = query.deletePersistentAll(); + } else if (parameters instanceof Object[]) { + nr = query.deletePersistentAll((Object[])parameters); + } else if (parameters instanceof Map) { + nr = query.deletePersistentAll((Map)parameters); + } else { + throw new IllegalArgumentException("Argument parameters " + + "must be instance of Object[], Map, or null."); + } + if (logger.isDebugEnabled()) { + logger.debug(nr + " objects deleted."); + } + + if (positive) { + if (nr != expectedNrOfDeletedObjects) { + fail(assertion, "deletePersistentAll returned " + nr + + ", expected is " + expectedNrOfDeletedObjects + + ". Query: " +singleStringQuery); + } + } else { + fail(assertion, "deletePersistentAll must throw JDOUserException: " + + singleStringQuery); + } + } finally { + query.closeAll(); + } + tx.commit(); + } catch (JDOUserException e) { + if (positive) { + throw e; + } + } finally { + if (tx.isActive()) { + tx.rollback(); + } + } + } } Index: test/java/org/apache/jdo/tck/query/QueryElementHolder.java =================================================================== --- test/java/org/apache/jdo/tck/query/QueryElementHolder.java (Revision 348686) +++ test/java/org/apache/jdo/tck/query/QueryElementHolder.java (Arbeitskopie) @@ -230,7 +230,7 @@ * Returns the unique JDOQL query element. * @return the unique JDOQL query element. */ - protected boolean isUnique() { + public boolean isUnique() { return this.unique != null && this.unique.booleanValue(); } @@ -238,9 +238,17 @@ * Returns the unique JDOQL query element. * @return the unique JDOQL query element. */ - protected boolean hasOrdering() { + public boolean hasOrdering() { return this.ordering != null; } + + /** + * Returns the candtidate class JDOQL query element. + * @return the candtidate class JDOQL query element. + */ + public Class getCandidateClass() { + return this.candidateClass; + } /** * Delegates to {@link QueryElementHolder#toString(String, String) Index: test/conf/alltests.conf =================================================================== --- test/conf/alltests.conf (Revision 348686) +++ test/conf/alltests.conf (Arbeitskopie) @@ -296,6 +296,9 @@ org.apache.jdo.tck.query.api.SetterReplacePreviousValues \ org.apache.jdo.tck.query.api.SingleStringQuery \ org.apache.jdo.tck.query.api.UnmodifiableQuery \ +org.apache.jdo.tck.query.delete.DeleteCallback \ +org.apache.jdo.tck.query.delete.DeletePersistentAll \ +org.apache.jdo.tck.query.delete.DeleteQueryElements \ org.apache.jdo.tck.query.jdoql.AssignmentPrePostIncrementDecrementNotSupported \ org.apache.jdo.tck.query.jdoql.Cast \ org.apache.jdo.tck.query.jdoql.CharacterAndStringLiterals \