blob: 5bf881caacc241df5855c89567360d9708bbeadd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://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.api.converter;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import javax.jdo.JDOHelper;
import javax.jdo.Query;
import javax.jdo.Transaction;
import org.apache.jdo.tck.JDO_Test;
import org.apache.jdo.tck.pc.converter.IPCRect;
import org.apache.jdo.tck.pc.converter.PCRect;
import org.apache.jdo.tck.pc.converter.PCRectAnnotated;
import org.apache.jdo.tck.pc.mylib.Point;
import org.apache.jdo.tck.util.BatchTestRunner;
import org.apache.jdo.tck.util.PointToStringConverter;
/**
* <B>Title:</B>PointAttributeConverterTest <br>
* <B>Keywords:</B> mapping <br>
* <B>Assertion ID:</B> [not identified] <br>
* <B>Assertion Description: </B> A IPCRect instance refers two Point instances, that are stored as
* strings in the datastore. A Point instance is converted using an AttributeConverter.
*/
public class PointAttributeConverterTest extends JDO_Test {
private static final int UL_X = 1;
private static final int UL_Y = 10;
private static final int LR_X = 10;
private static final int LR_Y = 1;
/**
* The <code>main</code> 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(PointAttributeConverterTest.class);
}
/**
* @see org.apache.jdo.tck.JDO_Test#localSetUp()
*/
@Override
protected void localSetUp() {
addTearDownClass(PCRect.class);
addTearDownClass(PCRectAnnotated.class);
}
/** Test method creating and storing a PCRectString instance. */
public void testStorePCRectStringInstance() {
runStoreIPCRectInstance(PCRect.class);
}
/** Test method reading a PCRectString instance from the datastore. */
public void testReadPCRectStringInstance() {
runReadIPCRectInstance(PCRect.class);
}
/** Test method modifying a PCRectString instance and storing in the datastore. */
public void testModifyPCRectStringInstance() {
runModifyIPCRectInstance(PCRect.class);
}
/** Test method running a PCRectString query with a query parameter of type Point. */
public void testPCRectStringQueryWithPointParam() {
runQueryWithPointParameter(PCRect.class);
}
/** Test method running a PCRectString query with a query parameter of type String. */
public void testPCRectStringQueryWithStringParam() throws Exception {
runQueryWithStringParameter(PCRect.class);
}
/** Test method creating and storing a PCRectStringAnnotated instance. */
public void testStorePCRectStringAnnotatedInstance() {
runStoreIPCRectInstance(PCRectAnnotated.class);
}
/** Test method reading a PCRectStringAnnotated instance from the datastore. */
public void testReadPCRectStringAnnotatedInstance() {
runReadIPCRectInstance(PCRectAnnotated.class);
}
/** Test method modifying a PCRectStringAnnotated instance and storing in the datastore. */
public void testModifyPCRectStringAnnotatedInstance() {
runModifyIPCRectInstance(PCRectAnnotated.class);
}
/** Test method running a PCRectStringAnnotated query with a query parameter of type String. */
public void testPCRectStringAnnotatedQueryWithPointParam() {
runQueryWithPointParameter(PCRectAnnotated.class);
}
/** Test method running a PCRectStringAnnotated query with a query parameter of type Point. */
public void testPCRectStringAnnotatedQueryWithStringParam() throws Exception {
runQueryWithStringParameter(PCRectAnnotated.class);
}
// Helper methods
/**
* Helper method creating a IPCRect instance. It should call AttributeConverter method
* convertToDatastore.
*/
private <T extends IPCRect> void runStoreIPCRectInstance(Class<T> pcrectClass) {
int nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
int nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
// Create a persistent IPCRect instance and store its oid
// AttributeConverter method convertToDatastore is called when persisting instance
createIPCRectInstances(pcrectClass, 1);
// convertToDatastore should be called twice
assertEquals(2, PointToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
// convertToAttribute should not be called
assertEquals(0, PointToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);
}
/**
* Helper method reading a IPCRect instance from the datastore. It should call AttributeConverter
* method convertToAttribute.
*/
private <T extends IPCRect> void runReadIPCRectInstance(Class<T> pcrectClass) {
IPCRect rect;
Object oid;
int nrOfDbCalls;
int nrOfAttrCalls;
// Create a persistent IPCRect instance and store its oid
oid = createIPCRectInstances(pcrectClass, 1);
// Cleanup the 2nd-level cache and close the pm to make sure PCRect instances are not cached
pm.getPersistenceManagerFactory().getDataStoreCache().evictAll(false, pcrectClass);
pm.close();
pm = null;
nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
pm = getPM();
pm.currentTransaction().begin();
// Read the IPCRect instance from the datastore, this should call convertToAttribute
rect = (IPCRect) pm.getObjectById(oid);
Point ul = rect.getUpperLeft();
Point lr = rect.getLowerRight();
pm.currentTransaction().commit();
// convertToDatastore should not be called
assertEquals(0, PointToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
// convertToAttribute should be called twice
assertEquals(2, PointToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);
// Check the values of the associated Point instances
assertEquals(UL_X, ul.getX());
assertEquals(UL_Y, ul.getY() == null ? 0 : ul.getY().intValue());
assertEquals(LR_X, lr.getX());
assertEquals(LR_Y, lr.getY() == null ? 0 : lr.getY().intValue());
}
/**
* Helper method modifying a IPCRect instance. It should call AttributeConverter method
* convertToDatastore.
*/
private <T extends IPCRect> void runModifyIPCRectInstance(Class<T> pcrectClass) {
Transaction tx;
IPCRect rect;
Object oid;
int nrOfDbCalls;
int nrOfAttrCalls;
// Create a persistent IPCRect instance and store its oid
oid = createIPCRectInstances(pcrectClass, 1);
// Cleanup the 2nd-level cache and close the pm to make sure PCRect instances are not cached
pm.getPersistenceManagerFactory().getDataStoreCache().evictAll(false, pcrectClass);
pm.close();
pm = null;
nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
pm = getPM();
tx = pm.currentTransaction();
tx.begin();
rect = (IPCRect) pm.getObjectById(oid);
// should trigger convertToAttribute
rect.getLowerRight();
rect.getUpperLeft();
// Update IPCRect instance, this should call convertToDatastore
rect.setUpperLeft(new Point(UL_X + 1, UL_Y + 1));
rect.setLowerRight(new Point(LR_X + 1, LR_Y + 1));
// IPCRect instance should be dirty
assertTrue(JDOHelper.isDirty(rect));
tx.commit();
// convertToDatastore should be called twice
assertEquals(2, PointToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
// convertToAttribute should be called twice
assertEquals(2, PointToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);
}
/**
* Helper method running a query with a Point parameter. The parameter value is converted using
* the AttributeConverter.
*
* @throws Exception
*/
private <T extends IPCRect> void runQueryWithPointParameter(Class<T> pcrectClass) {
int nrOfDbCalls;
int nrOfAttrCalls;
nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
createIPCRectInstances(pcrectClass, 5);
// convertToDatastore should be called twice per instance = 10 times
assertEquals(10, PointToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
// convertToAttribute should not be called
assertEquals(0, PointToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);
// Cleanup the 2nd-level cache and close the pm to make sure PCRect instances are not cached
pm.getPersistenceManagerFactory().getDataStoreCache().evictAll(false, pcrectClass);
pm.close();
pm = null;
nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
pm = getPM();
pm.currentTransaction().begin();
try (Query<T> q = pm.newQuery(pcrectClass, "this.upperLeft == :point")) {
q.setParameters(new Point(UL_X + 1, UL_Y + 1));
// AttributeConverter method convertToAttribute is called when loading instance from the
// datastore
List<T> res = q.executeList();
assertEquals(1, res.size());
IPCRect rect = res.get(0);
Point ul = rect.getUpperLeft();
Point lr = rect.getLowerRight();
// Check the coordinates of the associated Point instances
assertEquals(UL_X + 1, ul.getX());
assertEquals(UL_Y + 1, ul.getY() == null ? 0 : ul.getY().intValue());
assertEquals(LR_X + 1, lr.getX());
assertEquals(LR_Y + 1, lr.getY() == null ? 0 : lr.getY().intValue());
} catch (Exception e) {
fail(e.getMessage());
} finally {
pm.currentTransaction().commit();
}
// convertToDatastore should be called to handle the query parameter
assertTrue(PointToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls >= 1);
// convertToAttribute should be called at least twice
assertTrue(PointToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls >= 2);
}
/**
* Helper method running a query with a Point parameter. The string parameter is compared to the
* converted Point field.
*
* @throws Exception
*/
private <T extends IPCRect> void runQueryWithStringParameter(Class<T> pcrectClass)
throws Exception {
int nrOfDbCalls;
int nrOfAttrCalls;
nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
createIPCRectInstances(pcrectClass, 5);
// convertToDatastore should be called twice per instance = 10 times
assertEquals(10, PointToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
// convertToAttribute should not be called
assertEquals(0, PointToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);
// Cleanup the 2nd-level cache and close the pm to make sure PCRect instances are not cached
pm.getPersistenceManagerFactory().getDataStoreCache().evictAll(false, pcrectClass);
pm.close();
pm = null;
nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
pm = getPM();
pm.currentTransaction().begin();
try (Query<T> q = pm.newQuery(pcrectClass, "this.upperLeft == str")) {
q.declareParameters("String str");
q.setParameters("3:12");
// AttributeConverter method convertToAttribute is called when loading instance from the
// datastore
List<T> res = q.executeList();
assertEquals(1, res.size());
IPCRect rect = res.get(0);
Point ul = rect.getUpperLeft();
Point lr = rect.getLowerRight();
// Check the coordinates of the associated Point instances
assertEquals(UL_X + 2, ul.getX());
assertEquals(UL_Y + 2, ul.getY() == null ? 0 : ul.getY().intValue());
assertEquals(LR_X + 2, lr.getX());
assertEquals(LR_Y + 2, lr.getY() == null ? 0 : lr.getY().intValue());
} finally {
pm.currentTransaction().commit();
}
// convertToDatastore should not be called
assertTrue(PointToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls == 0);
// convertToAttribute should be called at least twice
assertTrue(PointToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls >= 2);
}
/**
* Helper method to create IPCRect instances.
*
* @param pcrectClass class instance of the IPCRect implementation class to be created
* @param nrOfObjects number of IPCRect instances to be created
* @return ObjectId of the first IPCRect instance
*/
private <T extends IPCRect> Object createIPCRectInstances(Class<T> pcrectClass, int nrOfObjects) {
IPCRect rect;
Object oid = null;
if (nrOfObjects < 1) {
return null;
}
pm = getPM();
try {
pm.currentTransaction().begin();
rect = pcrectClass.getConstructor().newInstance();
rect.setUpperLeft(new Point(UL_X, UL_Y));
rect.setLowerRight(new Point(LR_X, LR_Y));
pm.makePersistent(rect);
oid = pm.getObjectId(rect);
for (int i = 1; i < nrOfObjects; i++) {
rect = pcrectClass.getConstructor().newInstance();
rect.setUpperLeft(new Point(UL_X + i, UL_Y + i));
rect.setLowerRight(new Point(LR_X + i, LR_Y + i));
pm.makePersistent(rect);
}
pm.currentTransaction().commit();
} catch (NoSuchMethodException
| SecurityException
| InstantiationException
| IllegalAccessException
| IllegalArgumentException
| InvocationTargetException ex) {
fail("Error creating IPCRect instance: " + ex.getMessage());
} finally {
if (pm.currentTransaction().isActive()) {
pm.currentTransaction().rollback();
}
}
return oid;
}
}