cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject [28/48] Installing Maven Failsafe Plugin
Date Sun, 02 Nov 2014 07:10:16 GMT
http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheEmpiricTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheEmpiricTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheEmpiricTest.java
deleted file mode 100644
index af9a6db..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheEmpiricTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*****************************************************************
- *   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
- *
- *    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.cayenne.access;
-
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.cayenne.DataRow;
-import org.apache.cayenne.configuration.ObjectStoreFactory;
-import org.apache.cayenne.configuration.server.ServerRuntime;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.event.DefaultEventManager;
-import org.apache.cayenne.query.SelectQuery;
-import org.apache.cayenne.test.jdbc.DBHelper;
-import org.apache.cayenne.test.jdbc.TableHelper;
-import org.apache.cayenne.test.parallel.ParallelTestContainer;
-import org.apache.cayenne.testdo.testmap.Artist;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-
-@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
-public class DataContextSharedCacheEmpiricTest extends ServerCase {
-
-    private static final String NEW_NAME = "versionX";
-
-    @Inject
-    private ServerRuntime runtime;
-    
-    @Inject
-    private ObjectStoreFactory objectStoreFactory;
-
-    @Inject
-    private DBHelper dbHelper;
-
-    private DataContext c1;
-    private DataContext c2;
-
-    @Override
-    protected void setUpAfterInjection() throws Exception {
-        dbHelper.deleteAll("PAINTING_INFO");
-        dbHelper.deleteAll("PAINTING");
-        dbHelper.deleteAll("ARTIST_EXHIBIT");
-        dbHelper.deleteAll("ARTIST_GROUP");
-        dbHelper.deleteAll("ARTIST");
-
-        DataRowStore cache = new DataRowStore(
-                "cacheTest",
-                Collections.EMPTY_MAP,
-                new DefaultEventManager());
-
-        c1 = new DataContext(runtime.getDataDomain(), 
-                objectStoreFactory.createObjectStore(cache));
-        c2 = new DataContext(runtime.getDataDomain(), 
-                objectStoreFactory.createObjectStore(cache));
-
-        // prepare a single artist record
-        TableHelper tArtist = new TableHelper(dbHelper, "ARTIST");
-        tArtist.setColumns("ARTIST_ID", "ARTIST_NAME");
-        tArtist.insert(1, "version1");
-    }
-
-    public void testSelectSelectCommitRefresh() throws Exception {
-
-        SelectQuery query = new SelectQuery(Artist.class);
-
-        // select both, a2 should go second...
-        List<?> artists = c1.performQuery(query);
-        Artist a1 = (Artist) artists.get(0);
-
-        List<?> altArtists = c2.performQuery(query);
-        final Artist a2 = (Artist) altArtists.get(0);
-        assertNotNull(a2);
-        assertFalse(a2 == a1);
-
-        // Update Artist
-        a1.setArtistName(NEW_NAME);
-        c1.commitChanges();
-
-        assertOnCommit(a2);
-    }
-
-    public void testSelectSelectCommitRefreshReverse() throws Exception {
-
-        SelectQuery query = new SelectQuery(Artist.class);
-
-        List<?> altArtists = c2.performQuery(query);
-        final Artist a2 = (Artist) altArtists.get(0);
-
-        List<?> artists = c1.performQuery(query);
-        Artist a1 = (Artist) artists.get(0);
-
-        assertFalse(a2 == a1);
-
-        // Update Artist
-        a1.setArtistName(NEW_NAME);
-        c1.commitChanges();
-
-        assertOnCommit(a2);
-    }
-
-    public void testSelectUpdateSelectCommitRefresh() throws Exception {
-
-        SelectQuery query = new SelectQuery(Artist.class);
-
-        List<?> artists = c1.performQuery(query);
-        Artist a1 = (Artist) artists.get(0);
-
-        // Update Artist
-        a1.setArtistName(NEW_NAME);
-
-        List<?> altArtists = c2.performQuery(query);
-        final Artist a2 = (Artist) altArtists.get(0);
-        assertNotNull(a2);
-        assertFalse(a2 == a1);
-
-        c1.commitChanges();
-        assertOnCommit(a2);
-    }
-
-    private void assertOnCommit(final Artist a2) throws Exception {
-        // check underlying cache
-        final DataRow freshSnapshot = c2
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(a2.getObjectId());
-        assertNotNull("No snapshot for artist", freshSnapshot);
-        assertEquals(NEW_NAME, freshSnapshot.get("ARTIST_NAME"));
-
-        // check peer artist
-        ParallelTestContainer helper = new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                assertEquals(
-                        "Snapshot change is not propagated: " + freshSnapshot,
-                        NEW_NAME,
-                        a2.getArtistName());
-            }
-        };
-        helper.runTest(3000);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheIT.java
new file mode 100644
index 0000000..6428086
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheIT.java
@@ -0,0 +1,725 @@
+/*****************************************************************
+ *   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
+ *
+ *    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.cayenne.access;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.DataRow;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.PersistenceState;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.query.SQLTemplate;
+import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.test.parallel.ParallelTestContainer;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.apache.cayenne.unit.util.SQLTemplateCustomizer;
+
+/**
+ * Test suite for testing behavior of multiple DataContexts that share the same underlying
+ * DataDomain.
+ */
+@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
+public class DataContextSharedCacheIT extends ServerCase {
+
+    @Inject
+    private DataContext context;
+
+    @Inject
+    protected DBHelper dbHelper;
+
+    @Inject
+    private DataContext context1;
+
+    @Inject
+    private SQLTemplateCustomizer sqlTemplateCustomizer;
+
+    private Artist artist;
+
+    @Override
+    protected void setUpAfterInjection() throws Exception {
+
+        dbHelper.deleteAll("PAINTING_INFO");
+        dbHelper.deleteAll("PAINTING");
+        dbHelper.deleteAll("ARTIST_EXHIBIT");
+        dbHelper.deleteAll("ARTIST_GROUP");
+        dbHelper.deleteAll("ARTIST");
+        dbHelper.deleteAll("EXHIBIT");
+        dbHelper.deleteAll("GALLERY");
+
+        // prepare a single artist record
+        artist = (Artist) context.newObject("Artist");
+        artist.setArtistName("version1");
+        artist.setDateOfBirth(new Date());
+        context.commitChanges();
+    }
+
+    /**
+     * Test case to prove that refreshing snapshots as a result of the database fetch will
+     * be propagated across DataContexts.
+     */
+    public void testSnapshotChangePropagationOnSelect() throws Exception {
+        String originalName = artist.getArtistName();
+        final String newName = "version2";
+
+        // update artist using raw SQL
+        SQLTemplate query = sqlTemplateCustomizer.createSQLTemplate(
+                Artist.class,
+                "UPDATE ARTIST SET ARTIST_NAME = #bind($newName) "
+                        + "WHERE ARTIST_NAME = #bind($oldName)");
+
+        Map map = new HashMap(3);
+        map.put("newName", newName);
+        map.put("oldName", originalName);
+        query.setParameters(map);
+        context.performNonSelectingQuery(query);
+
+        // fetch updated artist into the new context, and see if the original
+        // one gets updated
+        Expression qual = ExpressionFactory.matchExp("artistName", newName);
+        List artists = context1.performQuery(new SelectQuery(Artist.class, qual));
+        assertEquals(1, artists.size());
+        Artist altArtist = (Artist) artists.get(0);
+
+        // check underlying cache
+        DataRow freshSnapshot = context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(altArtist.getObjectId());
+        assertNotNull(freshSnapshot);
+        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
+
+        // check both artists
+        assertEquals(newName, altArtist.getArtistName());
+
+        ParallelTestContainer helper = new ParallelTestContainer() {
+
+            @Override
+            protected void assertResult() throws Exception {
+                assertEquals(
+                        "Peer object state wasn't refreshed on fetch",
+                        newName,
+                        artist.getArtistName());
+            }
+        };
+        helper.runTest(3000);
+    }
+
+    /**
+     * Test case to prove that changes made to an object in one ObjectStore and committed
+     * to the database will be reflected in the peer ObjectStore using the same
+     * DataRowCache.
+     */
+    public void testSnapshotChangePropagation() throws Exception {
+        String originalName = artist.getArtistName();
+        final String newName = "version2";
+
+        // make sure we have a fully resolved copy of an artist object
+        // in the second context
+        final Artist altArtist = context1.localObject(artist);
+        assertFalse(altArtist == artist);
+        assertEquals(originalName, altArtist.getArtistName());
+        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
+
+        // Update Artist
+        artist.setArtistName(newName);
+
+        // no changes propagated till commit...
+        assertEquals(originalName, altArtist.getArtistName());
+        context.commitChanges();
+
+        // check underlying cache
+        DataRow freshSnapshot = context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(altArtist.getObjectId());
+        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
+
+        // check peer artist
+        ParallelTestContainer helper = new ParallelTestContainer() {
+
+            @Override
+            protected void assertResult() throws Exception {
+                assertEquals(newName, altArtist.getArtistName());
+            }
+        };
+        helper.runTest(3000);
+    }
+
+    /**
+     * Test case to prove that changes made to an object in one ObjectStore and committed
+     * to the database will be correctly merged in the peer ObjectStore using the same
+     * DataRowCache. E.g. modified objects will be merged so that no new changes are lost.
+     * 
+     * @throws Exception
+     */
+    public void testSnapshotChangePropagationToModifiedObjects() throws Exception {
+        String originalName = artist.getArtistName();
+        Date originalDate = artist.getDateOfBirth();
+        String newName = "version2";
+        final Date newDate = new Date(originalDate.getTime() - 10000);
+        final String newAltName = "version3";
+
+        // make sure we have a fully resolved copy of an artist object
+        // in the second context
+        final Artist altArtist = context1.localObject(artist);
+        assertNotNull(altArtist);
+        assertFalse(altArtist == artist);
+        assertEquals(originalName, altArtist.getArtistName());
+        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
+
+        // Update Artist peers independently
+        artist.setArtistName(newName);
+        artist.setDateOfBirth(newDate);
+        altArtist.setArtistName(newAltName);
+
+        context.commitChanges();
+
+        // check underlying cache
+        DataRow freshSnapshot = context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(altArtist.getObjectId());
+        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
+        assertEquals(newDate, freshSnapshot.get("DATE_OF_BIRTH"));
+
+        // check peer artist
+        ParallelTestContainer helper = new ParallelTestContainer() {
+
+            @Override
+            protected void assertResult() throws Exception {
+                assertEquals(newAltName, altArtist.getArtistName());
+                assertEquals(newDate, altArtist.getDateOfBirth());
+                assertEquals(PersistenceState.MODIFIED, altArtist.getPersistenceState());
+            }
+        };
+        helper.runTest(3000);
+
+    }
+
+    /**
+     * Test case to prove that deleting an object in one ObjectStore and committing to the
+     * database will be reflected in the peer ObjectStore using the same DataRowCache. By
+     * default COMMITTED objects will be changed to TRANSIENT.
+     */
+    public void testSnapshotDeletePropagationToCommitted() throws Exception {
+
+        // make sure we have a fully resolved copy of an artist object
+        // in the second context
+        final Artist altArtist = context1.localObject(artist);
+        assertNotNull(altArtist);
+        assertFalse(altArtist == artist);
+        assertEquals(artist.getArtistName(), altArtist.getArtistName());
+        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
+
+        // Update Artist
+        context.deleteObjects(artist);
+        context.commitChanges();
+
+        // check underlying cache
+        assertNull(context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(altArtist.getObjectId()));
+
+        // check peer artist
+        ParallelTestContainer helper = new ParallelTestContainer() {
+
+            @Override
+            protected void assertResult() throws Exception {
+                assertEquals(PersistenceState.TRANSIENT, altArtist.getPersistenceState());
+                assertNull(altArtist.getObjectContext());
+            }
+        };
+        helper.runTest(3000);
+    }
+
+    /**
+     * Test case to prove that deleting an object in one ObjectStore and committed to the
+     * database will be reflected in the peer ObjectStore using the same DataRowCache. By
+     * default HOLLOW objects will be changed to TRANSIENT.
+     * 
+     * @throws Exception
+     */
+    public void testSnapshotDeletePropagationToHollow() throws Exception {
+
+        final Artist altArtist = context1.localObject(artist);
+
+        assertNotNull(altArtist);
+        assertFalse(altArtist == artist);
+        assertEquals(PersistenceState.HOLLOW, altArtist.getPersistenceState());
+
+        // Update Artist
+        context.deleteObjects(artist);
+        context.commitChanges();
+
+        // check underlying cache
+        assertNull(context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(altArtist.getObjectId()));
+
+        // check peer artist
+        ParallelTestContainer helper = new ParallelTestContainer() {
+
+            @Override
+            protected void assertResult() throws Exception {
+                assertEquals(PersistenceState.TRANSIENT, altArtist.getPersistenceState());
+                assertNull(altArtist.getObjectContext());
+            }
+        };
+        helper.runTest(3000);
+    }
+
+    /**
+     * Test case to prove that deleting an object in one ObjectStore and committed to the
+     * database will be reflected in the peer ObjectStore using the same DataRowCache. By
+     * default MODIFIED objects will be changed to NEW.
+     */
+    public void testSnapshotDeletePropagationToModified() throws Exception {
+
+        // make sure we have a fully resolved copy of an artist object
+        // in the second context
+        final Artist altArtist = context1.localObject(artist);
+        altArtist.getArtistName();
+        assertNotNull(altArtist);
+        assertFalse(altArtist == artist);
+
+        // modify peer
+        altArtist.setArtistName("version2");
+        assertEquals(PersistenceState.MODIFIED, altArtist.getPersistenceState());
+
+        // Update Artist
+        context.deleteObjects(artist);
+        context.commitChanges();
+
+        // check underlying cache
+        assertNull(context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(altArtist.getObjectId()));
+
+        // check peer artist
+        ParallelTestContainer helper = new ParallelTestContainer() {
+
+            @Override
+            protected void assertResult() throws Exception {
+                assertEquals(PersistenceState.NEW, altArtist.getPersistenceState());
+            }
+        };
+        helper.runTest(3000);
+
+        // check if now we can save this object again, and with the original
+        // ObjectId
+        ObjectId id = altArtist.getObjectId();
+        assertNotNull(id);
+        assertNotNull(id.getIdSnapshot().get(Artist.ARTIST_ID_PK_COLUMN));
+        assertFalse(id.isTemporary());
+
+        context1.commitChanges();
+
+        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
+    }
+
+    /**
+     * Test case to prove that deleting an object in one ObjectStore and committing to the
+     * database will be reflected in the peer ObjectStore using the same DataRowCache. By
+     * default DELETED objects will be changed to TRANSIENT.
+     * 
+     * @throws Exception
+     */
+    public void testSnapshotDeletePropagationToDeleted() throws Exception {
+
+        // make sure we have a fully resolved copy of an artist object
+        // in the second context
+        final Artist altArtist = context1.localObject(artist);
+        altArtist.getArtistName();
+        assertNotNull(altArtist);
+        assertFalse(altArtist == artist);
+
+        // delete peer
+        context1.deleteObjects(altArtist);
+
+        // Update Artist
+        context.deleteObjects(artist);
+        context.commitChanges();
+
+        // check underlying cache
+        assertNull(context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(altArtist.getObjectId()));
+
+        // check peer artist
+        ParallelTestContainer helper = new ParallelTestContainer() {
+
+            @Override
+            protected void assertResult() throws Exception {
+                assertEquals(PersistenceState.TRANSIENT, altArtist.getPersistenceState());
+                assertNull(altArtist.getObjectContext());
+            }
+        };
+        helper.runTest(3000);
+
+        assertFalse(context1.hasChanges());
+    }
+
+    /**
+     * Test case to prove that deleting an object in one ObjectStore and committing to the
+     * database will be reflected in the peer ObjectStore using the same DataRowCache,
+     * including proper processing of deleted object being held in to-many collections.
+     */
+    public void testSnapshotDeletePropagationToManyRefresh() throws Exception {
+
+        Painting painting1 = (Painting) context.newObject("Painting");
+        painting1.setPaintingTitle("p1");
+        painting1.setToArtist(artist);
+
+        Painting painting2 = (Painting) context.newObject("Painting");
+        painting2.setPaintingTitle("p2");
+        painting2.setToArtist(artist);
+
+        context.commitChanges();
+
+        // make sure we have a fully resolved copy of an artist and painting
+        // objects
+        // in the second context
+
+        final Artist altArtist = context1.localObject(artist);
+        final Painting altPainting1 = context1.localObject(painting1);
+        final Painting altPainting2 = context1.localObject(painting2);
+
+        assertEquals(artist.getArtistName(), altArtist.getArtistName());
+        assertEquals(painting1.getPaintingTitle(), altPainting1.getPaintingTitle());
+        assertEquals(painting2.getPaintingTitle(), altPainting2.getPaintingTitle());
+        assertEquals(2, altArtist.getPaintingArray().size());
+        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
+        assertEquals(PersistenceState.COMMITTED, altPainting1.getPersistenceState());
+        assertEquals(PersistenceState.COMMITTED, altPainting2.getPersistenceState());
+
+        // make sure toOne relationships from Paintings
+        // are resolved...
+        altPainting1.getToArtist();
+        altPainting2.getToArtist();
+        assertSame(altArtist, altPainting1.readPropertyDirectly("toArtist"));
+        assertSame(altArtist, altPainting2.readPropertyDirectly("toArtist"));
+
+        // delete painting
+        context.deleteObjects(painting1);
+        context.commitChanges();
+
+        // check underlying cache
+        assertNull(context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(painting1.getObjectId()));
+
+        // check peer artist
+        ParallelTestContainer helper = new ParallelTestContainer() {
+
+            @Override
+            protected void assertResult() throws Exception {
+                assertEquals(
+                        PersistenceState.TRANSIENT,
+                        altPainting1.getPersistenceState());
+                assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
+
+                Collection<Painting> list = altArtist.getPaintingArray();
+                assertEquals(1, list.size());
+                assertFalse(list.contains(altPainting1));
+            }
+        };
+        helper.runTest(3000);
+    }
+
+    /**
+     * Test case to prove that inserting an object in one ObjectStore and committing to
+     * the database will be reflected in the peer ObjectStore using the same DataRowCache.
+     * This would mean refreshing to-many collections.
+     * 
+     * @throws Exception
+     */
+    public void testSnapshotInsertPropagationToManyRefresh() throws Exception {
+
+        Painting painting1 = (Painting) context.newObject("Painting");
+        painting1.setPaintingTitle("p1");
+        painting1.setToArtist(artist);
+
+        context.commitChanges();
+
+        // make sure we have a fully resolved copy of an artist and painting
+        // objects
+        // in the second context
+
+        final Artist altArtist = context1.localObject(artist);
+        final Painting altPainting1 = context1.localObject(painting1);
+
+        assertEquals(artist.getArtistName(), altArtist.getArtistName());
+        assertEquals(painting1.getPaintingTitle(), altPainting1.getPaintingTitle());
+        assertEquals(1, altArtist.getPaintingArray().size());
+        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
+        assertEquals(PersistenceState.COMMITTED, altPainting1.getPersistenceState());
+
+        // insert new painting and add to artist
+        Painting painting2 = (Painting) context.newObject("Painting");
+        painting2.setPaintingTitle("p2");
+        painting2.setToArtist(artist);
+        context.commitChanges();
+
+        // check peer artist
+
+        // use threaded helper as a barrier, to avoid triggering faults earlier than
+        // needed
+        ParallelTestContainer helper = new ParallelTestContainer() {
+
+            @Override
+            protected void assertResult() throws Exception {
+                Object value = altArtist.readPropertyDirectly("paintingArray");
+                assertTrue("Unexpected: " + value, value instanceof ToManyList);
+                assertTrue(((ToManyList) value).isFault());
+            }
+        };
+        helper.runTest(2000);
+        List<Painting> list = altArtist.getPaintingArray();
+        assertEquals(2, list.size());
+    }
+
+    /**
+     * Checks that cache is refreshed when a query "refreshingObjects" property is set to
+     * true.
+     */
+    public void testCacheRefreshingOnSelect() throws Exception {
+        String originalName = artist.getArtistName();
+        final String newName = "version2";
+
+        DataContext context = (DataContext) artist.getObjectContext();
+
+        DataRow oldSnapshot = context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId());
+        assertNotNull(oldSnapshot);
+        assertEquals(originalName, oldSnapshot.get("ARTIST_NAME"));
+
+        // update artist using raw SQL
+        SQLTemplate update = sqlTemplateCustomizer
+                .createSQLTemplate(
+                        Artist.class,
+                        "UPDATE ARTIST SET ARTIST_NAME = #bind($newName) WHERE ARTIST_NAME = #bind($oldName)");
+        Map map = new HashMap(3);
+        map.put("newName", newName);
+        map.put("oldName", originalName);
+        update.setParameters(map);
+        context.performNonSelectingQuery(update);
+
+        // fetch updated artist without refreshing
+        Expression qual = ExpressionFactory.matchExp("artistName", newName);
+        SelectQuery query = new SelectQuery(Artist.class, qual);
+        List artists = context.performQuery(query);
+        assertEquals(1, artists.size());
+        artist = (Artist) artists.get(0);
+
+        // check underlying cache
+        DataRow freshSnapshot = context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId());
+        assertNotSame(oldSnapshot, freshSnapshot);
+        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
+
+        // check an artist
+        assertEquals(newName, artist.getArtistName());
+    }
+
+    public void testSnapshotEvictedForHollow() throws Exception {
+        String originalName = artist.getArtistName();
+
+        context.invalidateObjects(artist);
+        assertEquals(PersistenceState.HOLLOW, artist.getPersistenceState());
+        assertNull(context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId()));
+
+        // resolve object
+        assertEquals(originalName, artist.getArtistName());
+        DataRow freshSnapshot = context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId());
+        assertNotNull(freshSnapshot);
+        assertEquals(originalName, freshSnapshot.get("ARTIST_NAME"));
+    }
+
+    public void testSnapshotEvictedAndObjectsHollowedForInvalidate() throws Exception {
+        String originalName = artist.getArtistName();
+
+        // make sure we have a fully resolved copy of an artist object
+        // in the second context
+        final Artist altArtist = context1.localObject(artist);
+        context1.prepareForAccess(altArtist, null, false);
+        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
+
+        context.invalidateObjects(artist);
+
+        // original context
+        assertEquals(PersistenceState.HOLLOW, artist.getPersistenceState());
+        assertNull(context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId()));
+
+        // alternate context
+        new ParallelTestContainer() {
+
+            @Override
+            protected void assertResult() throws Exception {
+                assertEquals(PersistenceState.HOLLOW, altArtist.getPersistenceState());
+                assertNull(context1
+                        .getObjectStore()
+                        .getDataRowCache()
+                        .getCachedSnapshot(altArtist.getObjectId()));
+            }
+        }.runTest(5000);
+
+        // resolve object
+        assertEquals(originalName, altArtist.getArtistName());
+        DataRow altFreshSnapshot = context1
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(altArtist.getObjectId());
+        assertNotNull(altFreshSnapshot);
+        assertEquals(originalName, altFreshSnapshot.get("ARTIST_NAME"));
+
+    }
+
+    public void testSnapshotEvictedForCommitted() throws Exception {
+        String newName = "version2";
+
+        assertEquals(PersistenceState.COMMITTED, artist.getPersistenceState());
+
+        context.getObjectStore().getDataRowCache().forgetSnapshot(artist.getObjectId());
+        assertNull(context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId()));
+
+        // modify object and try to save
+        artist.setArtistName(newName);
+        context.commitChanges();
+
+        assertEquals(newName, artist.getArtistName());
+        DataRow freshSnapshot = context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId());
+        assertNotNull(freshSnapshot);
+        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
+    }
+
+    public void testSnapshotEvictedForModified() throws Exception {
+        String newName = "version2";
+
+        assertEquals(PersistenceState.COMMITTED, artist.getPersistenceState());
+
+        // modify object PRIOR to killing the snapshot
+        artist.setArtistName(newName);
+
+        context.getObjectStore().getDataRowCache().forgetSnapshot(artist.getObjectId());
+        assertNull(context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId()));
+
+        context.commitChanges();
+
+        assertEquals(newName, artist.getArtistName());
+        DataRow freshSnapshot = context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId());
+        assertNotNull(freshSnapshot);
+        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
+    }
+
+    public void testSnapshotEvictedAndChangedForModified() throws Exception {
+        String originalName = artist.getArtistName();
+        String newName = "version2";
+        String backendName = "version3";
+
+        assertEquals(PersistenceState.COMMITTED, artist.getPersistenceState());
+
+        // modify object PRIOR to killing the snapshot
+        artist.setArtistName(newName);
+
+        context.getObjectStore().getDataRowCache().forgetSnapshot(artist.getObjectId());
+        assertNull(context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId()));
+
+        // now replace the row in the database
+        String template = "UPDATE ARTIST SET ARTIST_NAME = #bind($newName) WHERE ARTIST_NAME = #bind($oldName)";
+        SQLTemplate update = new SQLTemplate(Artist.class, template);
+
+        Map map = new HashMap(3);
+        map.put("newName", backendName);
+        map.put("oldName", originalName);
+        update.setParameters(map);
+        context.performNonSelectingQuery(update);
+
+        context.commitChanges();
+
+        assertEquals(newName, artist.getArtistName());
+        DataRow freshSnapshot = context
+                .getObjectStore()
+                .getDataRowCache()
+                .getCachedSnapshot(artist.getObjectId());
+        assertNotNull(freshSnapshot);
+        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
+    }
+
+    public void testSnapshotEvictedForDeleted() throws Exception {
+        // remember ObjectId
+        ObjectId id = artist.getObjectId();
+
+        assertEquals(PersistenceState.COMMITTED, artist.getPersistenceState());
+
+        // delete object PRIOR to killing the snapshot
+        context.deleteObjects(artist);
+
+        context.getObjectStore().getDataRowCache().forgetSnapshot(id);
+        assertNull(context.getObjectStore().getDataRowCache().getCachedSnapshot(id));
+
+        context.commitChanges();
+
+        assertEquals(PersistenceState.TRANSIENT, artist.getPersistenceState());
+        assertNull(context.getObjectStore().getDataRowCache().getCachedSnapshot(id));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheTest.java
deleted file mode 100644
index 916792b..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextSharedCacheTest.java
+++ /dev/null
@@ -1,725 +0,0 @@
-/*****************************************************************
- *   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
- *
- *    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.cayenne.access;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.cayenne.DataRow;
-import org.apache.cayenne.ObjectId;
-import org.apache.cayenne.PersistenceState;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.query.SQLTemplate;
-import org.apache.cayenne.query.SelectQuery;
-import org.apache.cayenne.test.jdbc.DBHelper;
-import org.apache.cayenne.test.parallel.ParallelTestContainer;
-import org.apache.cayenne.testdo.testmap.Artist;
-import org.apache.cayenne.testdo.testmap.Painting;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-import org.apache.cayenne.unit.util.SQLTemplateCustomizer;
-
-/**
- * Test suite for testing behavior of multiple DataContexts that share the same underlying
- * DataDomain.
- */
-@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
-public class DataContextSharedCacheTest extends ServerCase {
-
-    @Inject
-    private DataContext context;
-
-    @Inject
-    protected DBHelper dbHelper;
-
-    @Inject
-    private DataContext context1;
-
-    @Inject
-    private SQLTemplateCustomizer sqlTemplateCustomizer;
-
-    private Artist artist;
-
-    @Override
-    protected void setUpAfterInjection() throws Exception {
-
-        dbHelper.deleteAll("PAINTING_INFO");
-        dbHelper.deleteAll("PAINTING");
-        dbHelper.deleteAll("ARTIST_EXHIBIT");
-        dbHelper.deleteAll("ARTIST_GROUP");
-        dbHelper.deleteAll("ARTIST");
-        dbHelper.deleteAll("EXHIBIT");
-        dbHelper.deleteAll("GALLERY");
-
-        // prepare a single artist record
-        artist = (Artist) context.newObject("Artist");
-        artist.setArtistName("version1");
-        artist.setDateOfBirth(new Date());
-        context.commitChanges();
-    }
-
-    /**
-     * Test case to prove that refreshing snapshots as a result of the database fetch will
-     * be propagated across DataContexts.
-     */
-    public void testSnapshotChangePropagationOnSelect() throws Exception {
-        String originalName = artist.getArtistName();
-        final String newName = "version2";
-
-        // update artist using raw SQL
-        SQLTemplate query = sqlTemplateCustomizer.createSQLTemplate(
-                Artist.class,
-                "UPDATE ARTIST SET ARTIST_NAME = #bind($newName) "
-                        + "WHERE ARTIST_NAME = #bind($oldName)");
-
-        Map map = new HashMap(3);
-        map.put("newName", newName);
-        map.put("oldName", originalName);
-        query.setParameters(map);
-        context.performNonSelectingQuery(query);
-
-        // fetch updated artist into the new context, and see if the original
-        // one gets updated
-        Expression qual = ExpressionFactory.matchExp("artistName", newName);
-        List artists = context1.performQuery(new SelectQuery(Artist.class, qual));
-        assertEquals(1, artists.size());
-        Artist altArtist = (Artist) artists.get(0);
-
-        // check underlying cache
-        DataRow freshSnapshot = context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(altArtist.getObjectId());
-        assertNotNull(freshSnapshot);
-        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
-
-        // check both artists
-        assertEquals(newName, altArtist.getArtistName());
-
-        ParallelTestContainer helper = new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                assertEquals(
-                        "Peer object state wasn't refreshed on fetch",
-                        newName,
-                        artist.getArtistName());
-            }
-        };
-        helper.runTest(3000);
-    }
-
-    /**
-     * Test case to prove that changes made to an object in one ObjectStore and committed
-     * to the database will be reflected in the peer ObjectStore using the same
-     * DataRowCache.
-     */
-    public void testSnapshotChangePropagation() throws Exception {
-        String originalName = artist.getArtistName();
-        final String newName = "version2";
-
-        // make sure we have a fully resolved copy of an artist object
-        // in the second context
-        final Artist altArtist = context1.localObject(artist);
-        assertFalse(altArtist == artist);
-        assertEquals(originalName, altArtist.getArtistName());
-        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
-
-        // Update Artist
-        artist.setArtistName(newName);
-
-        // no changes propagated till commit...
-        assertEquals(originalName, altArtist.getArtistName());
-        context.commitChanges();
-
-        // check underlying cache
-        DataRow freshSnapshot = context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(altArtist.getObjectId());
-        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
-
-        // check peer artist
-        ParallelTestContainer helper = new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                assertEquals(newName, altArtist.getArtistName());
-            }
-        };
-        helper.runTest(3000);
-    }
-
-    /**
-     * Test case to prove that changes made to an object in one ObjectStore and committed
-     * to the database will be correctly merged in the peer ObjectStore using the same
-     * DataRowCache. E.g. modified objects will be merged so that no new changes are lost.
-     * 
-     * @throws Exception
-     */
-    public void testSnapshotChangePropagationToModifiedObjects() throws Exception {
-        String originalName = artist.getArtistName();
-        Date originalDate = artist.getDateOfBirth();
-        String newName = "version2";
-        final Date newDate = new Date(originalDate.getTime() - 10000);
-        final String newAltName = "version3";
-
-        // make sure we have a fully resolved copy of an artist object
-        // in the second context
-        final Artist altArtist = context1.localObject(artist);
-        assertNotNull(altArtist);
-        assertFalse(altArtist == artist);
-        assertEquals(originalName, altArtist.getArtistName());
-        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
-
-        // Update Artist peers independently
-        artist.setArtistName(newName);
-        artist.setDateOfBirth(newDate);
-        altArtist.setArtistName(newAltName);
-
-        context.commitChanges();
-
-        // check underlying cache
-        DataRow freshSnapshot = context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(altArtist.getObjectId());
-        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
-        assertEquals(newDate, freshSnapshot.get("DATE_OF_BIRTH"));
-
-        // check peer artist
-        ParallelTestContainer helper = new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                assertEquals(newAltName, altArtist.getArtistName());
-                assertEquals(newDate, altArtist.getDateOfBirth());
-                assertEquals(PersistenceState.MODIFIED, altArtist.getPersistenceState());
-            }
-        };
-        helper.runTest(3000);
-
-    }
-
-    /**
-     * Test case to prove that deleting an object in one ObjectStore and committing to the
-     * database will be reflected in the peer ObjectStore using the same DataRowCache. By
-     * default COMMITTED objects will be changed to TRANSIENT.
-     */
-    public void testSnapshotDeletePropagationToCommitted() throws Exception {
-
-        // make sure we have a fully resolved copy of an artist object
-        // in the second context
-        final Artist altArtist = context1.localObject(artist);
-        assertNotNull(altArtist);
-        assertFalse(altArtist == artist);
-        assertEquals(artist.getArtistName(), altArtist.getArtistName());
-        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
-
-        // Update Artist
-        context.deleteObjects(artist);
-        context.commitChanges();
-
-        // check underlying cache
-        assertNull(context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(altArtist.getObjectId()));
-
-        // check peer artist
-        ParallelTestContainer helper = new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                assertEquals(PersistenceState.TRANSIENT, altArtist.getPersistenceState());
-                assertNull(altArtist.getObjectContext());
-            }
-        };
-        helper.runTest(3000);
-    }
-
-    /**
-     * Test case to prove that deleting an object in one ObjectStore and committed to the
-     * database will be reflected in the peer ObjectStore using the same DataRowCache. By
-     * default HOLLOW objects will be changed to TRANSIENT.
-     * 
-     * @throws Exception
-     */
-    public void testSnapshotDeletePropagationToHollow() throws Exception {
-
-        final Artist altArtist = context1.localObject(artist);
-
-        assertNotNull(altArtist);
-        assertFalse(altArtist == artist);
-        assertEquals(PersistenceState.HOLLOW, altArtist.getPersistenceState());
-
-        // Update Artist
-        context.deleteObjects(artist);
-        context.commitChanges();
-
-        // check underlying cache
-        assertNull(context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(altArtist.getObjectId()));
-
-        // check peer artist
-        ParallelTestContainer helper = new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                assertEquals(PersistenceState.TRANSIENT, altArtist.getPersistenceState());
-                assertNull(altArtist.getObjectContext());
-            }
-        };
-        helper.runTest(3000);
-    }
-
-    /**
-     * Test case to prove that deleting an object in one ObjectStore and committed to the
-     * database will be reflected in the peer ObjectStore using the same DataRowCache. By
-     * default MODIFIED objects will be changed to NEW.
-     */
-    public void testSnapshotDeletePropagationToModified() throws Exception {
-
-        // make sure we have a fully resolved copy of an artist object
-        // in the second context
-        final Artist altArtist = context1.localObject(artist);
-        altArtist.getArtistName();
-        assertNotNull(altArtist);
-        assertFalse(altArtist == artist);
-
-        // modify peer
-        altArtist.setArtistName("version2");
-        assertEquals(PersistenceState.MODIFIED, altArtist.getPersistenceState());
-
-        // Update Artist
-        context.deleteObjects(artist);
-        context.commitChanges();
-
-        // check underlying cache
-        assertNull(context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(altArtist.getObjectId()));
-
-        // check peer artist
-        ParallelTestContainer helper = new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                assertEquals(PersistenceState.NEW, altArtist.getPersistenceState());
-            }
-        };
-        helper.runTest(3000);
-
-        // check if now we can save this object again, and with the original
-        // ObjectId
-        ObjectId id = altArtist.getObjectId();
-        assertNotNull(id);
-        assertNotNull(id.getIdSnapshot().get(Artist.ARTIST_ID_PK_COLUMN));
-        assertFalse(id.isTemporary());
-
-        context1.commitChanges();
-
-        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
-    }
-
-    /**
-     * Test case to prove that deleting an object in one ObjectStore and committing to the
-     * database will be reflected in the peer ObjectStore using the same DataRowCache. By
-     * default DELETED objects will be changed to TRANSIENT.
-     * 
-     * @throws Exception
-     */
-    public void testSnapshotDeletePropagationToDeleted() throws Exception {
-
-        // make sure we have a fully resolved copy of an artist object
-        // in the second context
-        final Artist altArtist = context1.localObject(artist);
-        altArtist.getArtistName();
-        assertNotNull(altArtist);
-        assertFalse(altArtist == artist);
-
-        // delete peer
-        context1.deleteObjects(altArtist);
-
-        // Update Artist
-        context.deleteObjects(artist);
-        context.commitChanges();
-
-        // check underlying cache
-        assertNull(context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(altArtist.getObjectId()));
-
-        // check peer artist
-        ParallelTestContainer helper = new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                assertEquals(PersistenceState.TRANSIENT, altArtist.getPersistenceState());
-                assertNull(altArtist.getObjectContext());
-            }
-        };
-        helper.runTest(3000);
-
-        assertFalse(context1.hasChanges());
-    }
-
-    /**
-     * Test case to prove that deleting an object in one ObjectStore and committing to the
-     * database will be reflected in the peer ObjectStore using the same DataRowCache,
-     * including proper processing of deleted object being held in to-many collections.
-     */
-    public void testSnapshotDeletePropagationToManyRefresh() throws Exception {
-
-        Painting painting1 = (Painting) context.newObject("Painting");
-        painting1.setPaintingTitle("p1");
-        painting1.setToArtist(artist);
-
-        Painting painting2 = (Painting) context.newObject("Painting");
-        painting2.setPaintingTitle("p2");
-        painting2.setToArtist(artist);
-
-        context.commitChanges();
-
-        // make sure we have a fully resolved copy of an artist and painting
-        // objects
-        // in the second context
-
-        final Artist altArtist = context1.localObject(artist);
-        final Painting altPainting1 = context1.localObject(painting1);
-        final Painting altPainting2 = context1.localObject(painting2);
-
-        assertEquals(artist.getArtistName(), altArtist.getArtistName());
-        assertEquals(painting1.getPaintingTitle(), altPainting1.getPaintingTitle());
-        assertEquals(painting2.getPaintingTitle(), altPainting2.getPaintingTitle());
-        assertEquals(2, altArtist.getPaintingArray().size());
-        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
-        assertEquals(PersistenceState.COMMITTED, altPainting1.getPersistenceState());
-        assertEquals(PersistenceState.COMMITTED, altPainting2.getPersistenceState());
-
-        // make sure toOne relationships from Paintings
-        // are resolved...
-        altPainting1.getToArtist();
-        altPainting2.getToArtist();
-        assertSame(altArtist, altPainting1.readPropertyDirectly("toArtist"));
-        assertSame(altArtist, altPainting2.readPropertyDirectly("toArtist"));
-
-        // delete painting
-        context.deleteObjects(painting1);
-        context.commitChanges();
-
-        // check underlying cache
-        assertNull(context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(painting1.getObjectId()));
-
-        // check peer artist
-        ParallelTestContainer helper = new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                assertEquals(
-                        PersistenceState.TRANSIENT,
-                        altPainting1.getPersistenceState());
-                assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
-
-                Collection<Painting> list = altArtist.getPaintingArray();
-                assertEquals(1, list.size());
-                assertFalse(list.contains(altPainting1));
-            }
-        };
-        helper.runTest(3000);
-    }
-
-    /**
-     * Test case to prove that inserting an object in one ObjectStore and committing to
-     * the database will be reflected in the peer ObjectStore using the same DataRowCache.
-     * This would mean refreshing to-many collections.
-     * 
-     * @throws Exception
-     */
-    public void testSnapshotInsertPropagationToManyRefresh() throws Exception {
-
-        Painting painting1 = (Painting) context.newObject("Painting");
-        painting1.setPaintingTitle("p1");
-        painting1.setToArtist(artist);
-
-        context.commitChanges();
-
-        // make sure we have a fully resolved copy of an artist and painting
-        // objects
-        // in the second context
-
-        final Artist altArtist = context1.localObject(artist);
-        final Painting altPainting1 = context1.localObject(painting1);
-
-        assertEquals(artist.getArtistName(), altArtist.getArtistName());
-        assertEquals(painting1.getPaintingTitle(), altPainting1.getPaintingTitle());
-        assertEquals(1, altArtist.getPaintingArray().size());
-        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
-        assertEquals(PersistenceState.COMMITTED, altPainting1.getPersistenceState());
-
-        // insert new painting and add to artist
-        Painting painting2 = (Painting) context.newObject("Painting");
-        painting2.setPaintingTitle("p2");
-        painting2.setToArtist(artist);
-        context.commitChanges();
-
-        // check peer artist
-
-        // use threaded helper as a barrier, to avoid triggering faults earlier than
-        // needed
-        ParallelTestContainer helper = new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                Object value = altArtist.readPropertyDirectly("paintingArray");
-                assertTrue("Unexpected: " + value, value instanceof ToManyList);
-                assertTrue(((ToManyList) value).isFault());
-            }
-        };
-        helper.runTest(2000);
-        List<Painting> list = altArtist.getPaintingArray();
-        assertEquals(2, list.size());
-    }
-
-    /**
-     * Checks that cache is refreshed when a query "refreshingObjects" property is set to
-     * true.
-     */
-    public void testCacheRefreshingOnSelect() throws Exception {
-        String originalName = artist.getArtistName();
-        final String newName = "version2";
-
-        DataContext context = (DataContext) artist.getObjectContext();
-
-        DataRow oldSnapshot = context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId());
-        assertNotNull(oldSnapshot);
-        assertEquals(originalName, oldSnapshot.get("ARTIST_NAME"));
-
-        // update artist using raw SQL
-        SQLTemplate update = sqlTemplateCustomizer
-                .createSQLTemplate(
-                        Artist.class,
-                        "UPDATE ARTIST SET ARTIST_NAME = #bind($newName) WHERE ARTIST_NAME = #bind($oldName)");
-        Map map = new HashMap(3);
-        map.put("newName", newName);
-        map.put("oldName", originalName);
-        update.setParameters(map);
-        context.performNonSelectingQuery(update);
-
-        // fetch updated artist without refreshing
-        Expression qual = ExpressionFactory.matchExp("artistName", newName);
-        SelectQuery query = new SelectQuery(Artist.class, qual);
-        List artists = context.performQuery(query);
-        assertEquals(1, artists.size());
-        artist = (Artist) artists.get(0);
-
-        // check underlying cache
-        DataRow freshSnapshot = context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId());
-        assertNotSame(oldSnapshot, freshSnapshot);
-        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
-
-        // check an artist
-        assertEquals(newName, artist.getArtistName());
-    }
-
-    public void testSnapshotEvictedForHollow() throws Exception {
-        String originalName = artist.getArtistName();
-
-        context.invalidateObjects(artist);
-        assertEquals(PersistenceState.HOLLOW, artist.getPersistenceState());
-        assertNull(context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId()));
-
-        // resolve object
-        assertEquals(originalName, artist.getArtistName());
-        DataRow freshSnapshot = context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId());
-        assertNotNull(freshSnapshot);
-        assertEquals(originalName, freshSnapshot.get("ARTIST_NAME"));
-    }
-
-    public void testSnapshotEvictedAndObjectsHollowedForInvalidate() throws Exception {
-        String originalName = artist.getArtistName();
-
-        // make sure we have a fully resolved copy of an artist object
-        // in the second context
-        final Artist altArtist = context1.localObject(artist);
-        context1.prepareForAccess(altArtist, null, false);
-        assertEquals(PersistenceState.COMMITTED, altArtist.getPersistenceState());
-
-        context.invalidateObjects(artist);
-
-        // original context
-        assertEquals(PersistenceState.HOLLOW, artist.getPersistenceState());
-        assertNull(context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId()));
-
-        // alternate context
-        new ParallelTestContainer() {
-
-            @Override
-            protected void assertResult() throws Exception {
-                assertEquals(PersistenceState.HOLLOW, altArtist.getPersistenceState());
-                assertNull(context1
-                        .getObjectStore()
-                        .getDataRowCache()
-                        .getCachedSnapshot(altArtist.getObjectId()));
-            }
-        }.runTest(5000);
-
-        // resolve object
-        assertEquals(originalName, altArtist.getArtistName());
-        DataRow altFreshSnapshot = context1
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(altArtist.getObjectId());
-        assertNotNull(altFreshSnapshot);
-        assertEquals(originalName, altFreshSnapshot.get("ARTIST_NAME"));
-
-    }
-
-    public void testSnapshotEvictedForCommitted() throws Exception {
-        String newName = "version2";
-
-        assertEquals(PersistenceState.COMMITTED, artist.getPersistenceState());
-
-        context.getObjectStore().getDataRowCache().forgetSnapshot(artist.getObjectId());
-        assertNull(context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId()));
-
-        // modify object and try to save
-        artist.setArtistName(newName);
-        context.commitChanges();
-
-        assertEquals(newName, artist.getArtistName());
-        DataRow freshSnapshot = context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId());
-        assertNotNull(freshSnapshot);
-        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
-    }
-
-    public void testSnapshotEvictedForModified() throws Exception {
-        String newName = "version2";
-
-        assertEquals(PersistenceState.COMMITTED, artist.getPersistenceState());
-
-        // modify object PRIOR to killing the snapshot
-        artist.setArtistName(newName);
-
-        context.getObjectStore().getDataRowCache().forgetSnapshot(artist.getObjectId());
-        assertNull(context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId()));
-
-        context.commitChanges();
-
-        assertEquals(newName, artist.getArtistName());
-        DataRow freshSnapshot = context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId());
-        assertNotNull(freshSnapshot);
-        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
-    }
-
-    public void testSnapshotEvictedAndChangedForModified() throws Exception {
-        String originalName = artist.getArtistName();
-        String newName = "version2";
-        String backendName = "version3";
-
-        assertEquals(PersistenceState.COMMITTED, artist.getPersistenceState());
-
-        // modify object PRIOR to killing the snapshot
-        artist.setArtistName(newName);
-
-        context.getObjectStore().getDataRowCache().forgetSnapshot(artist.getObjectId());
-        assertNull(context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId()));
-
-        // now replace the row in the database
-        String template = "UPDATE ARTIST SET ARTIST_NAME = #bind($newName) WHERE ARTIST_NAME = #bind($oldName)";
-        SQLTemplate update = new SQLTemplate(Artist.class, template);
-
-        Map map = new HashMap(3);
-        map.put("newName", backendName);
-        map.put("oldName", originalName);
-        update.setParameters(map);
-        context.performNonSelectingQuery(update);
-
-        context.commitChanges();
-
-        assertEquals(newName, artist.getArtistName());
-        DataRow freshSnapshot = context
-                .getObjectStore()
-                .getDataRowCache()
-                .getCachedSnapshot(artist.getObjectId());
-        assertNotNull(freshSnapshot);
-        assertEquals(newName, freshSnapshot.get("ARTIST_NAME"));
-    }
-
-    public void testSnapshotEvictedForDeleted() throws Exception {
-        // remember ObjectId
-        ObjectId id = artist.getObjectId();
-
-        assertEquals(PersistenceState.COMMITTED, artist.getPersistenceState());
-
-        // delete object PRIOR to killing the snapshot
-        context.deleteObjects(artist);
-
-        context.getObjectStore().getDataRowCache().forgetSnapshot(id);
-        assertNull(context.getObjectStore().getDataRowCache().getCachedSnapshot(id));
-
-        context.commitChanges();
-
-        assertEquals(PersistenceState.TRANSIENT, artist.getPersistenceState());
-        assertNull(context.getObjectStore().getDataRowCache().getCachedSnapshot(id));
-    }
-}


Mime
View raw message