PageRenderTime 66ms CodeModel.GetById 43ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 1ms

/tests/com/google/appengine/datanucleus/jdo/JDOConcurrentModificationTest.java

http://datanucleus-appengine.googlecode.com/
Java | 485 lines | 391 code | 46 blank | 48 comment | 10 complexity | 9f4ff023848d89da426de04cbfa6f7eb MD5 | raw file
  1/*
  2 * /**********************************************************************
  3 * Copyright (c) 2009 Google Inc.
  4 *
  5 * Licensed under the Apache License, Version 2.0 (the "License");
  6 * you may not use this file except in compliance with the License.
  7 * You may obtain a copy of the License at
  8 *
  9 * http://www.apache.org/licenses/LICENSE-2.0
 10 *
 11 * Unless required by applicable law or agreed to in writing, software
 12 * distributed under the License is distributed on an "AS IS" BASIS,
 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14 * See the License for the specific language governing permissions and
 15 * limitations under the License.
 16 * **********************************************************************/
 17package com.google.appengine.datanucleus.jdo;
 18
 19import com.google.appengine.api.datastore.Entity;
 20import com.google.appengine.datanucleus.CollisionDatastoreDelegate;
 21import com.google.appengine.datanucleus.ExceptionThrowingDatastoreDelegate;
 22import com.google.appengine.datanucleus.Inner;
 23import com.google.appengine.datanucleus.test.jdo.Flight;
 24
 25import java.util.ConcurrentModificationException;
 26
 27import javax.jdo.JDODataStoreException;
 28
 29import org.datanucleus.exceptions.NucleusDataStoreException;
 30
 31/**
 32 * @author Max Ross <maxr@google.com>
 33 */
 34@Inner
 35public class JDOConcurrentModificationTest extends JDOTestCase {
 36
 37  public void testInsertCollides() {
 38    CollisionDatastoreDelegate dd = new CollisionDatastoreDelegate(getDelegateForThread());
 39    setDelegateForThread(dd);
 40    try {
 41      Flight flight = new Flight();
 42      flight.setName("harold");
 43      flight.setOrigin("bos");
 44      flight.setDest("mia");
 45      flight.setYou(23);
 46      flight.setMe(24);
 47      flight.setFlightNumber(88);
 48      beginTxn();
 49      try {
 50        pm.makePersistent(flight);
 51        fail("expected exception");
 52      } catch (JDODataStoreException e) {
 53        // good
 54        assertTrue(e.getCause() instanceof ConcurrentModificationException);
 55      }
 56      assertTrue(pm.currentTransaction().isActive());
 57      rollbackTxn();
 58      assertEquals(flight, "harold", "bos", "mia", 23, 24, 88);
 59    } finally {
 60      setDelegateForThread(dd.getInner());
 61    }
 62  }
 63
 64  public void testInsertCollidesOnCommit() {
 65    ExceptionThrowingDatastoreDelegate.ExceptionPolicy policy =
 66        new ExceptionThrowingDatastoreDelegate.BaseExceptionPolicy() {
 67          int count = 0;
 68          protected void doIntercept(String methodName) {
 69            if (count != 0) {
 70              throw new ConcurrentModificationException();
 71            }
 72            count++;
 73          }
 74        };
 75    ExceptionThrowingDatastoreDelegate dd =
 76        new ExceptionThrowingDatastoreDelegate(getDelegateForThread(), policy);
 77    setDelegateForThread(dd);
 78    try {
 79      Flight flight = new Flight();
 80      flight.setName("harold");
 81      flight.setOrigin("bos");
 82      flight.setDest("mia");
 83      flight.setYou(23);
 84      flight.setMe(24);
 85      flight.setFlightNumber(88);
 86      beginTxn();
 87      pm.makePersistent(flight);
 88      try {
 89        commitTxn();
 90        fail("expected exception");
 91      } catch (JDODataStoreException e) {
 92        // good
 93        assertTrue(e.getCause() instanceof ConcurrentModificationException);
 94      }
 95      assertFalse(pm.currentTransaction().isActive());
 96      assertEquals(flight, "harold", "bos", "mia", 23, 24, 88);
 97    } finally {
 98      setDelegateForThread(dd.getInner());
 99    }
100  }
101
102  public void testUpdateCollides() {
103    Entity e = Flight.newFlightEntity("harold", "bos", "mia", 23, 24, 88);
104    ds.put(e);
105    CollisionDatastoreDelegate dd = new CollisionDatastoreDelegate(getDelegateForThread());
106    setDelegateForThread(dd);
107    try {
108      beginTxn();
109      Flight f = pm.getObjectById(Flight.class, e.getKey());
110      f.setYou(12);
111      try {
112        commitTxn();
113        fail("expected exception");
114      } catch (JDODataStoreException ex) {
115        // good
116        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
117      }
118      assertFalse(pm.currentTransaction().isActive());
119    } finally {
120      setDelegateForThread(dd.getInner());
121    }
122  }
123
124  public void testUpdateOfDetachedCollides() {
125    Entity e = Flight.newFlightEntity("harold", "bos", "mia", 23, 24, 88);
126    ds.put(e);
127    beginTxn();
128    Flight f = pm.detachCopy(pm.getObjectById(Flight.class, e.getKey()));
129    commitTxn();
130
131    CollisionDatastoreDelegate dd = new CollisionDatastoreDelegate(getDelegateForThread());
132    setDelegateForThread(dd);
133
134    try {
135      // update detached object
136      f.setYou(12);
137      beginTxn();
138
139      // reattach
140      pm.makePersistent(f);
141      try {
142        commitTxn();
143        fail("expected exception");
144      } catch (JDODataStoreException ex) {
145        // good
146        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
147      }
148      assertFalse(pm.currentTransaction().isActive());
149      // now verify that the new value is still in the detached version.
150      assertEquals(f, "harold", "bos", "mia", 12, 24, 88);
151    } finally {
152      setDelegateForThread(dd.getInner());
153    }
154  }
155
156  public void testUpdateOfDetachedCollidesThenSucceeds() {
157
158    ExceptionThrowingDatastoreDelegate.ExceptionPolicy policy =
159        new ExceptionThrowingDatastoreDelegate.BaseExceptionPolicy() {
160          int count = 0;
161          protected void doIntercept(String methodName) {
162            if (count == 0) {
163              count++;
164              throw new ConcurrentModificationException();
165            }
166          }
167        };
168
169    Entity e = Flight.newFlightEntity("harold", "bos", "mia", 23, 24, 88);
170    ds.put(e);
171    beginTxn();
172    Flight f = pm.detachCopy(pm.getObjectById(Flight.class, e.getKey()));
173    commitTxn();
174
175    ExceptionThrowingDatastoreDelegate dd =
176        new ExceptionThrowingDatastoreDelegate(getDelegateForThread(), policy);
177    setDelegateForThread(dd);
178
179    try {
180      // update detached object
181      f.setYou(12);
182      beginTxn();
183
184      // reattach
185      pm.makePersistent(f);
186      try {
187        commitTxn();
188        fail("expected exception");
189      } catch (JDODataStoreException ex) {
190        // good
191        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
192      }
193      assertFalse(pm.currentTransaction().isActive());
194      beginTxn();
195      pm.makePersistent(f);
196      commitTxn();
197      beginTxn();
198      f = pm.getObjectById(Flight.class, e.getKey());
199      assertEquals(f, "harold", "bos", "mia", 12, 24, 88);
200      commitTxn();
201    } finally {
202      setDelegateForThread(dd.getInner());
203    }
204  }
205
206  public void testUpdateOfAttachedCollidesThenSucceeds() {
207
208    ExceptionThrowingDatastoreDelegate.ExceptionPolicy policy =
209        new ExceptionThrowingDatastoreDelegate.BaseExceptionPolicy() {
210          int count = 0;
211          protected void doIntercept(String methodName) {
212            if (count == 0) {
213              count++;
214              throw new ConcurrentModificationException();
215            }
216          }
217        };
218
219    Entity e = Flight.newFlightEntity("harold", "bos", "mia", 23, 24, 88);
220    ds.put(e);
221    beginTxn();
222    Flight f = pm.getObjectById(Flight.class, e.getKey());
223    // make a copy right away, otherwise our change will get reverted
224    // when the txn rolls back
225    Flight fCopy = pm.detachCopy(f);
226    ExceptionThrowingDatastoreDelegate dd =
227        new ExceptionThrowingDatastoreDelegate(getDelegateForThread(), policy);
228    setDelegateForThread(dd);
229
230    try {
231      // update attached object
232      fCopy.setYou(12);
233      pm.makePersistent(fCopy);
234      try {
235        commitTxn();
236        fail("expected exception");
237      } catch (JDODataStoreException ex) {
238        // good
239        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
240      }
241      assertFalse(pm.currentTransaction().isActive());
242      beginTxn();
243      pm.makePersistent(fCopy);
244      commitTxn();
245      beginTxn();
246      f = pm.getObjectById(Flight.class, e.getKey());
247      assertEquals(f, "harold", "bos", "mia", 12, 24, 88);
248      commitTxn();
249    } finally {
250      setDelegateForThread(dd.getInner());
251    }
252  }
253
254  public void testDeleteCollides() {
255    Entity e = Flight.newFlightEntity("harold", "bos", "mia", 23, 24, 88);
256    ds.put(e);
257    CollisionDatastoreDelegate dd = new CollisionDatastoreDelegate(getDelegateForThread());
258    setDelegateForThread(dd);
259
260    try {
261      beginTxn();
262      Flight f = pm.getObjectById(Flight.class, e.getKey());
263
264      try {
265        pm.deletePersistent(f);
266        fail("expected exception");
267      } catch (JDODataStoreException ex) {
268        // good
269        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
270      }
271      assertTrue(pm.currentTransaction().isActive());
272      rollbackTxn();
273    } finally {
274      setDelegateForThread(dd.getInner());
275    }
276  }
277
278  public void testInsertCollides_NoTxn() {
279    switchDatasource(PersistenceManagerFactoryName.nontransactional);
280    CollisionDatastoreDelegate dd = new CollisionDatastoreDelegate(getDelegateForThread());
281    setDelegateForThread(dd);
282    try {
283      Flight flight = new Flight();
284      flight.setName("harold");
285      flight.setOrigin("bos");
286      flight.setDest("mia");
287      flight.setYou(23);
288      flight.setMe(24);
289      flight.setFlightNumber(88);
290      try {
291        pm.makePersistent(flight);
292        fail("expected exception");
293      } catch (JDODataStoreException e) {
294        // good
295        assertTrue(e.getCause() instanceof ConcurrentModificationException);
296      }
297      assertEquals(flight, "harold", "bos", "mia", 23, 24, 88);
298    } finally {
299      setDelegateForThread(dd.getInner());
300    }
301  }
302
303  public void testUpdateCollides_NoTxn() {
304    switchDatasource(PersistenceManagerFactoryName.nontransactional);
305    Entity e = Flight.newFlightEntity("harold", "bos", "mia", 23, 24, 88);
306    ds.put(e);
307    CollisionDatastoreDelegate dd = new CollisionDatastoreDelegate(getDelegateForThread());
308    setDelegateForThread(dd);
309
310    try {
311      try {
312        Flight f = pm.getObjectById(Flight.class, e.getKey());
313        f.setYou(12);
314        pm.close();
315        fail("expected exception");
316      } catch (JDODataStoreException ex) {
317        // good
318        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
319      } catch (NucleusDataStoreException ex) {
320        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
321      }
322    } finally {
323      setDelegateForThread(dd.getInner());
324    }
325  }
326
327  public void testUpdateOfDetachedCollides_NoTxn() {
328    switchDatasource(PersistenceManagerFactoryName.nontransactional);
329    Entity e = Flight.newFlightEntity("harold", "bos", "mia", 23, 24, 88);
330    ds.put(e);
331    Flight f = pm.detachCopy(pm.getObjectById(Flight.class, e.getKey()));
332    pm.close();
333    pm = pmf.getPersistenceManager();
334
335    CollisionDatastoreDelegate dd = new CollisionDatastoreDelegate(getDelegateForThread());
336    setDelegateForThread(dd);
337
338    try {
339      // update detached object
340      f.setYou(12);
341
342      // reattach
343      try {
344        pm.makePersistent(f);
345        pm.close();
346        fail("expected exception");
347      } catch (JDODataStoreException ex) {
348        // good
349        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
350      }
351      // now verify that the new value is still in the detached version.
352      assertEquals(f, "harold", "bos", "mia", 12, 24, 88);
353    } finally {
354      setDelegateForThread(dd.getInner());
355    }
356  }
357
358  public void testUpdateOfDetachedCollidesThenSucceeds_NoTxn() {
359    switchDatasource(PersistenceManagerFactoryName.nontransactional);
360
361    ExceptionThrowingDatastoreDelegate.ExceptionPolicy policy =
362        new ExceptionThrowingDatastoreDelegate.BaseExceptionPolicy() {
363          int count = 0;
364          protected void doIntercept(String methodName) {
365            if (count == 0) {
366              count++;
367              throw new ConcurrentModificationException();
368            }
369          }
370        };
371
372    Entity e = Flight.newFlightEntity("harold", "bos", "mia", 23, 24, 88);
373    ds.put(e);
374    Flight f = pm.detachCopy(pm.getObjectById(Flight.class, e.getKey()));
375    pm.close();
376    pm = pmf.getPersistenceManager();
377    ExceptionThrowingDatastoreDelegate dd =
378        new ExceptionThrowingDatastoreDelegate(getDelegateForThread(), policy);
379    setDelegateForThread(dd);
380
381    try {
382      // update detached object
383      f.setYou(12);
384
385      // reattach
386      try {
387        pm.makePersistent(f);
388        pm.close();
389        fail("expected exception");
390      } catch (JDODataStoreException ex) {
391        // good
392        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
393      }
394      pm = pmf.getPersistenceManager();
395      pm.makePersistent(f);
396      pm.close();
397      pm = pmf.getPersistenceManager();
398      f = pm.getObjectById(Flight.class, e.getKey());
399      assertEquals(f, "harold", "bos", "mia", 12, 24, 88);
400      pm.close();
401    } finally {
402      setDelegateForThread(dd.getInner());
403    }
404  }
405
406  public void testUpdateOfAttachedCollidesThenSucceeds_NoTxn() {
407    switchDatasource(PersistenceManagerFactoryName.nontransactional);
408
409    ExceptionThrowingDatastoreDelegate.ExceptionPolicy policy =
410        new ExceptionThrowingDatastoreDelegate.BaseExceptionPolicy() {
411          int count = 0;
412          protected void doIntercept(String methodName) {
413            if (count == 0) {
414              count++;
415              throw new ConcurrentModificationException();
416            }
417          }
418        };
419
420    Entity e = Flight.newFlightEntity("harold", "bos", "mia", 23, 24, 88);
421    ds.put(e);
422    Flight f = pm.getObjectById(Flight.class, e.getKey());
423    // make a copy right away, otherwise our change will get reverted
424    // when the txn rolls back
425    Flight fCopy = pm.detachCopy(f);
426    ExceptionThrowingDatastoreDelegate dd =
427        new ExceptionThrowingDatastoreDelegate(getDelegateForThread(), policy);
428    setDelegateForThread(dd);
429
430    try {
431      // update attached object
432      fCopy.setYou(12);
433      try {
434        pm.makePersistent(fCopy);
435        pm.close();
436        fail("expected exception");
437      } catch (JDODataStoreException ex) {
438        // good
439        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
440      }
441      pm = pmf.getPersistenceManager();
442      pm.makePersistent(fCopy);
443      pm.close();
444      pm = pmf.getPersistenceManager();
445      f = pm.getObjectById(Flight.class, e.getKey());
446      assertEquals(f, "harold", "bos", "mia", 12, 24, 88);
447      pm.close();
448    } finally {
449      setDelegateForThread(dd.getInner());
450    }
451  }
452
453  public void testDeleteCollides_NoTxn() {
454    switchDatasource(PersistenceManagerFactoryName.nontransactional);
455
456    Entity e = Flight.newFlightEntity("harold", "bos", "mia", 23, 24, 88);
457    ds.put(e);
458    CollisionDatastoreDelegate dd = new CollisionDatastoreDelegate(getDelegateForThread());
459    setDelegateForThread(dd);
460
461    try {
462      Flight f = pm.getObjectById(Flight.class, e.getKey());
463
464      try {
465        pm.deletePersistent(f);
466        fail("expected exception");
467      } catch (JDODataStoreException ex) {
468        // good
469        assertTrue(ex.getCause() instanceof ConcurrentModificationException);
470      }
471      pm.close();
472    } finally {
473      setDelegateForThread(dd.getInner());
474    }
475  }
476
477  private void assertEquals(Flight f, String name, String orig, String dest, int you, int me, int flightNumber) {
478    assertEquals(name, f.getName());
479    assertEquals(orig, f.getOrigin());
480    assertEquals(dest, f.getDest());
481    assertEquals(you, f.getYou());
482    assertEquals(me, f.getMe());
483    assertEquals(flightNumber, f.getFlightNumber());
484  }
485}