PageRenderTime 145ms CodeModel.GetById 25ms app.highlight 109ms RepoModel.GetById 2ms app.codeStats 0ms

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

http://datanucleus-appengine.googlecode.com/
Java | 1713 lines | 1415 code | 213 blank | 85 comment | 96 complexity | dd56daf6ee210431500db8af72891577 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/**********************************************************************
   2Copyright (c) 2009 Google Inc.
   3
   4Licensed under the Apache License, Version 2.0 (the "License");
   5you may not use this file except in compliance with the License.
   6You may obtain a copy of the License at
   7
   8http://www.apache.org/licenses/LICENSE-2.0
   9
  10Unless required by applicable law or agreed to in writing, software
  11distributed under the License is distributed on an "AS IS" BASIS,
  12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13See the License for the specific language governing permissions and
  14limitations under the License.
  15**********************************************************************/
  16package com.google.appengine.datanucleus.jdo;
  17
  18import com.google.appengine.api.datastore.DatastoreService;
  19import com.google.appengine.api.datastore.DatastoreServiceConfig;
  20import com.google.appengine.api.datastore.Entity;
  21import com.google.appengine.api.datastore.EntityNotFoundException;
  22import com.google.appengine.api.datastore.Key;
  23import com.google.appengine.api.datastore.KeyFactory;
  24import com.google.appengine.api.datastore.Query;
  25import com.google.appengine.api.datastore.Transaction;
  26import com.google.appengine.api.datastore.TransactionOptions;
  27import com.google.appengine.datanucleus.DatastoreServiceFactoryInternal;
  28import com.google.appengine.datanucleus.DatastoreServiceInterceptor;
  29import com.google.appengine.datanucleus.StorageVersion;
  30import com.google.appengine.datanucleus.Utils;
  31import com.google.appengine.datanucleus.test.jdo.BidirectionalChildJDO;
  32import com.google.appengine.datanucleus.test.jdo.BidirectionalChildLongPkJDO;
  33import com.google.appengine.datanucleus.test.jdo.BidirectionalChildUnencodedStringPkJDO;
  34import com.google.appengine.datanucleus.test.jdo.Flight;
  35import com.google.appengine.datanucleus.test.jdo.HasExplicitIndexColumnJDO;
  36import com.google.appengine.datanucleus.test.jdo.HasKeyPkJDO;
  37import com.google.appengine.datanucleus.test.jdo.HasOneToManyJDO;
  38import com.google.appengine.datanucleus.test.jdo.HasOneToManyKeyPkJDO;
  39import com.google.appengine.datanucleus.test.jdo.HasOneToManyListJDO;
  40import com.google.appengine.datanucleus.test.jdo.HasOneToManyListWithOrderByJDO;
  41import com.google.appengine.datanucleus.test.jdo.HasOneToManyLongPkJDO;
  42import com.google.appengine.datanucleus.test.jdo.HasOneToManyUnencodedStringPkJDO;
  43import com.google.appengine.datanucleus.test.jdo.HasOneToManyWithOrderByJDO;
  44
  45import org.easymock.EasyMock;
  46
  47import java.lang.reflect.Method;
  48import java.util.Collection;
  49import java.util.Collections;
  50import java.util.ConcurrentModificationException;
  51import java.util.Iterator;
  52import java.util.List;
  53import java.util.Set;
  54
  55import javax.jdo.JDOFatalUserException;
  56
  57import static com.google.appengine.datanucleus.TestUtils.assertKeyParentEquals;
  58
  59/**
  60 * @author Max Ross <maxr@google.com>
  61 */
  62abstract class JDOOneToManyTestCase extends JDOTestCase {
  63
  64  @Override
  65  protected void tearDown() throws Exception {
  66    try {
  67      if (!pm.isClosed() && pm.currentTransaction().isActive()) {
  68        pm.currentTransaction().rollback();
  69      }
  70      pmf.close();
  71    } finally {
  72      super.tearDown();
  73    }
  74  }
  75
  76  void testInsert_NewParentAndChild(HasOneToManyJDO parent,
  77      BidirectionalChildJDO bidirChild, StartEnd startEnd) throws EntityNotFoundException {
  78    bidirChild.setChildVal("yam");
  79
  80    Flight f = newFlight();
  81
  82    HasKeyPkJDO hasKeyPk = new HasKeyPkJDO();
  83    hasKeyPk.setStr("yag");
  84
  85    parent.addBidirChild(bidirChild);
  86    bidirChild.setParent(parent);
  87    parent.addFlight(f);
  88    parent.addHasKeyPk(hasKeyPk);
  89    parent.setVal("yar");
  90
  91    startEnd.start();
  92    pm.makePersistent(parent);
  93    startEnd.end();
  94
  95    assertNotNull(bidirChild.getId());
  96    assertNotNull(f.getId());
  97    assertNotNull(hasKeyPk.getKey());
  98
  99    Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidirChild.getId()));
 100    assertNotNull(bidirChildEntity);
 101    assertEquals("yam", bidirChildEntity.getProperty("childVal"));
 102    assertEquals(KeyFactory.stringToKey(bidirChild.getId()), bidirChildEntity.getKey());
 103    assertKeyParentEquals(parent.getId(), bidirChildEntity, bidirChild.getId());
 104    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 105      assertEquals(0L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
 106    }
 107
 108    Entity flightEntity = ds.get(KeyFactory.stringToKey(f.getId()));
 109    assertNotNull(flightEntity);
 110    assertEquals("bos", flightEntity.getProperty("origin"));
 111    assertEquals("mia", flightEntity.getProperty("dest"));
 112    assertEquals("jimmy", flightEntity.getProperty("name"));
 113    assertEquals(KeyFactory.stringToKey(f.getId()), flightEntity.getKey());
 114    assertKeyParentEquals(parent.getId(), flightEntity, f.getId());
 115    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 116      assertEquals(0L, flightEntity.getProperty("flights_INTEGER_IDX"));
 117    }
 118
 119    Entity hasKeyPkEntity = ds.get(hasKeyPk.getKey());
 120    assertNotNull(hasKeyPkEntity);
 121    assertEquals("yag", hasKeyPkEntity.getProperty("str"));
 122    assertEquals(hasKeyPk.getKey(), hasKeyPkEntity.getKey());
 123    assertKeyParentEquals(parent.getId(), hasKeyPkEntity, hasKeyPk.getKey());
 124    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 125      assertEquals(0L, hasKeyPkEntity.getProperty("hasKeyPks_INTEGER_IDX"));
 126    }
 127
 128    Entity parentEntity = ds.get(KeyFactory.stringToKey(parent.getId()));
 129    assertNotNull(parentEntity);
 130    assertEquals(4, parentEntity.getProperties().size());
 131    assertEquals("yar", parentEntity.getProperty("val"));
 132    assertEquals(Utils.newArrayList(bidirChildEntity.getKey()), parentEntity.getProperty("bidirChildren"));
 133    assertEquals(Utils.newArrayList(flightEntity.getKey()), parentEntity.getProperty("flights"));
 134    assertEquals(Utils.newArrayList(hasKeyPkEntity.getKey()), parentEntity.getProperty("hasKeyPks"));
 135
 136    assertCountsInDatastore(parent.getClass(), bidirChild.getClass(), 1, 1);
 137  }
 138
 139  void testInsert_ExistingParentNewChild(HasOneToManyJDO pojo,
 140      BidirectionalChildJDO bidirChild, StartEnd startEnd) throws EntityNotFoundException {
 141    pojo.setVal("yar");
 142
 143    startEnd.start();
 144    pm.makePersistent(pojo);
 145    startEnd.end();
 146
 147    startEnd.start();
 148    assertNotNull(pojo.getId());
 149    assertTrue(pojo.getFlights().isEmpty());
 150    assertTrue(pojo.getHasKeyPks().isEmpty());
 151    assertTrue(pojo.getBidirChildren().isEmpty());
 152
 153    Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
 154    assertNotNull(pojoEntity);
 155    assertEquals(4, pojoEntity.getProperties().size());
 156    assertEquals("yar", pojoEntity.getProperty("val"));
 157    assertTrue(pojoEntity.hasProperty("bidirChildren"));
 158    assertNull(pojoEntity.getProperty("bidirChildren"));
 159    assertTrue(pojoEntity.hasProperty("flights"));
 160    assertNull(pojoEntity.getProperty("flights"));
 161    assertTrue(pojoEntity.hasProperty("hasKeyPks"));
 162    assertNull(pojoEntity.getProperty("hasKeyPks"));
 163    startEnd.end();
 164
 165    startEnd.start();
 166    pojo = pm.makePersistent(pojo);
 167    assertEquals("yar", pojo.getVal());
 168    Flight f = newFlight();
 169    pojo.addFlight(f);
 170
 171    HasKeyPkJDO hasKeyPk = new HasKeyPkJDO();
 172    hasKeyPk.setStr("yag");
 173    pojo.addHasKeyPk(hasKeyPk);
 174    bidirChild.setChildVal("yam");
 175    pojo.addBidirChild(bidirChild);
 176    startEnd.end();
 177
 178    startEnd.start();
 179    assertNotNull(bidirChild.getId());
 180    assertNotNull(bidirChild.getParent());
 181    assertNotNull(f.getId());
 182    assertNotNull(hasKeyPk.getKey());
 183    startEnd.end();
 184    
 185    Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidirChild.getId()));
 186    assertNotNull(bidirChildEntity);
 187    assertEquals("yam", bidirChildEntity.getProperty("childVal"));
 188    assertEquals(KeyFactory.stringToKey(bidirChild.getId()), bidirChildEntity.getKey());
 189    assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidirChild.getId());
 190    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 191      assertEquals(0L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
 192    }
 193
 194    Entity flightEntity = ds.get(KeyFactory.stringToKey(f.getId()));
 195    assertNotNull(flightEntity);
 196    assertEquals("bos", flightEntity.getProperty("origin"));
 197    assertEquals("mia", flightEntity.getProperty("dest"));
 198    assertEquals("jimmy", flightEntity.getProperty("name"));
 199    assertEquals(KeyFactory.stringToKey(f.getId()), flightEntity.getKey());
 200    assertKeyParentEquals(pojo.getId(), flightEntity, f.getId());
 201    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 202      assertEquals(0L, flightEntity.getProperty("flights_INTEGER_IDX"));
 203    }
 204
 205    Entity hasKeyPkEntity = ds.get(hasKeyPk.getKey());
 206    assertNotNull(hasKeyPkEntity);
 207    assertEquals("yag", hasKeyPkEntity.getProperty("str"));
 208    assertEquals(hasKeyPk.getKey(), hasKeyPkEntity.getKey());
 209    assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk.getKey());
 210    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 211      assertEquals(0L, hasKeyPkEntity.getProperty("hasKeyPks_INTEGER_IDX"));
 212    }
 213
 214    Entity parentEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
 215    assertNotNull(parentEntity);
 216    assertEquals(4, parentEntity.getProperties().size());
 217    assertEquals("yar", parentEntity.getProperty("val"));
 218    assertEquals(Utils.newArrayList(bidirChildEntity.getKey()), parentEntity.getProperty("bidirChildren"));
 219    assertEquals(Utils.newArrayList(flightEntity.getKey()), parentEntity.getProperty("flights"));
 220    assertEquals(Utils.newArrayList(hasKeyPkEntity.getKey()), parentEntity.getProperty("hasKeyPks"));
 221
 222    assertCountsInDatastore(pojo.getClass(), bidirChild.getClass(), 1, 1);
 223  }
 224
 225  void testSwapAtPosition(HasOneToManyJDO pojo,
 226      BidirectionalChildJDO bidir1,
 227      BidirectionalChildJDO bidir2, StartEnd startEnd) throws EntityNotFoundException {
 228    pojo.setVal("yar");
 229    bidir2.setChildVal("yam");
 230    Flight f = newFlight();
 231    HasKeyPkJDO hasKeyPk = new HasKeyPkJDO();
 232
 233    pojo.addFlight(f);
 234    pojo.addHasKeyPk(hasKeyPk);
 235    pojo.addBidirChild(bidir1);
 236    bidir1.setParent(pojo);
 237
 238    startEnd.start();
 239    pm.makePersistent(pojo);
 240    startEnd.end();
 241
 242    assertCountsInDatastore(pojo.getClass(), bidir1.getClass(), 1, 1);
 243
 244    startEnd.start();
 245    pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
 246    String bidir1Id = pojo.getBidirChildren().iterator().next().getId();
 247    String flight1Id = pojo.getFlights().iterator().next().getId();
 248    Key hasKeyPk1Key = pojo.getHasKeyPks().iterator().next().getKey();
 249    pojo.addBidirChildAtPosition(bidir2, 0);
 250
 251    Flight f2 = newFlight();
 252    f2.setName("another name");
 253    pojo.addFlightAtPosition(f2, 0);
 254
 255    HasKeyPkJDO hasKeyPk2 = new HasKeyPkJDO();
 256    hasKeyPk2.setStr("another str");
 257    pojo.addHasKeyPkAtPosition(hasKeyPk2, 0);
 258    startEnd.end();
 259
 260    startEnd.start();
 261    pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
 262    assertNotNull(pojo.getId());
 263    assertEquals(1, pojo.getFlights().size());
 264    assertEquals(1, pojo.getHasKeyPks().size());
 265    assertEquals(1, pojo.getBidirChildren().size());
 266    assertNotNull(bidir2.getId());
 267    assertNotNull(bidir2.getParent());
 268    assertNotNull(f2.getId());
 269    assertNotNull(hasKeyPk2.getKey());
 270
 271    Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
 272    assertNotNull(pojoEntity);
 273    assertEquals(4, pojoEntity.getProperties().size());
 274    assertEquals(Utils.newArrayList(KeyFactory.stringToKey(bidir2.getId())), pojoEntity.getProperty("bidirChildren"));
 275    assertEquals(Utils.newArrayList(KeyFactory.stringToKey(f2.getId())), pojoEntity.getProperty("flights"));
 276    assertEquals(Utils.newArrayList(hasKeyPk2.getKey()), pojoEntity.getProperty("hasKeyPks"));
 277
 278    startEnd.end();
 279
 280    try {
 281      ds.get(KeyFactory.stringToKey(bidir1Id));
 282      fail("expected EntityNotFoundException");
 283    } catch (EntityNotFoundException enfe) {
 284      // good
 285    }
 286    try {
 287      ds.get(KeyFactory.stringToKey(flight1Id));
 288      fail("expected EntityNotFoundException");
 289    } catch (EntityNotFoundException enfe) {
 290      // good
 291    }
 292    try {
 293      ds.get(hasKeyPk1Key);
 294      fail("expected EntityNotFoundException");
 295    } catch (EntityNotFoundException enfe) {
 296      // good
 297    }
 298    Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidir2.getId()));
 299    assertNotNull(bidirChildEntity);
 300    assertEquals("yam", bidirChildEntity.getProperty("childVal"));
 301    assertEquals(KeyFactory.stringToKey(bidir2.getId()), bidirChildEntity.getKey());
 302    assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidir2.getId());
 303    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 304      assertEquals(0L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
 305    }
 306
 307    Entity flightEntity = ds.get(KeyFactory.stringToKey(f2.getId()));
 308    assertNotNull(flightEntity);
 309    assertEquals("bos", flightEntity.getProperty("origin"));
 310    assertEquals("mia", flightEntity.getProperty("dest"));
 311    assertEquals("another name", flightEntity.getProperty("name"));
 312    assertEquals(KeyFactory.stringToKey(f2.getId()), flightEntity.getKey());
 313    assertKeyParentEquals(pojo.getId(), flightEntity, f2.getId());
 314    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 315      assertEquals(0L, flightEntity.getProperty("flights_INTEGER_IDX"));
 316    }
 317
 318    Entity hasKeyPkEntity = ds.get(hasKeyPk2.getKey());
 319    assertNotNull(hasKeyPkEntity);
 320    assertEquals("another str", hasKeyPkEntity.getProperty("str"));
 321    assertEquals(hasKeyPk2.getKey(), hasKeyPkEntity.getKey());
 322    assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk2.getKey());
 323    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 324      assertEquals(0L, hasKeyPkEntity.getProperty("hasKeyPks_INTEGER_IDX"));
 325    }
 326
 327    Entity parentEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
 328    assertNotNull(parentEntity);
 329    assertEquals(4, parentEntity.getProperties().size());
 330    assertEquals("yar", parentEntity.getProperty("val"));
 331    assertEquals(Utils.newArrayList(bidirChildEntity.getKey()), parentEntity.getProperty("bidirChildren"));
 332    assertEquals(Utils.newArrayList(flightEntity.getKey()), parentEntity.getProperty("flights"));
 333    assertEquals(Utils.newArrayList(hasKeyPkEntity.getKey()), parentEntity.getProperty("hasKeyPks"));
 334
 335    assertCountsInDatastore(pojo.getClass(), bidir2.getClass(), 1, 1);
 336  }
 337
 338  void testRemoveAtPosition(HasOneToManyJDO pojo,
 339      BidirectionalChildJDO bidir1,
 340      BidirectionalChildJDO bidir2,
 341      BidirectionalChildJDO bidir3, StartEnd startEnd) throws EntityNotFoundException {
 342    pojo.setVal("yar");
 343    bidir2.setChildVal("another yam");
 344    bidir3.setChildVal("yet another yam");
 345    Flight f = newFlight();
 346    Flight f2 = newFlight();
 347    Flight f3 = newFlight();
 348    f2.setName("another name");
 349    f3.setName("yet another name");
 350    HasKeyPkJDO hasKeyPk = new HasKeyPkJDO();
 351    HasKeyPkJDO hasKeyPk2 = new HasKeyPkJDO();
 352    HasKeyPkJDO hasKeyPk3 = new HasKeyPkJDO();
 353    hasKeyPk2.setStr("another str");
 354    hasKeyPk3.setStr("yet another str");
 355
 356    pojo.addFlight(f);
 357    pojo.addFlight(f2);
 358    pojo.addFlight(f3);
 359    pojo.addHasKeyPk(hasKeyPk);
 360    pojo.addHasKeyPk(hasKeyPk2);
 361    pojo.addHasKeyPk(hasKeyPk3);
 362    pojo.addBidirChild(bidir1);
 363    pojo.addBidirChild(bidir2);
 364    pojo.addBidirChild(bidir3);
 365
 366    startEnd.start();
 367    pm.makePersistent(pojo);
 368    startEnd.end();
 369
 370    assertCountsInDatastore(pojo.getClass(), bidir1.getClass(), 1, 3);
 371
 372    startEnd.start();
 373    pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
 374    String bidir1Id = pojo.getBidirChildren().iterator().next().getId();
 375    String flight1Id = pojo.getFlights().iterator().next().getId();
 376    Key hasKeyPk1Key = pojo.getHasKeyPks().iterator().next().getKey();
 377    pojo.removeBidirChildAtPosition(0);
 378    pojo.removeFlightAtPosition(0);
 379    pojo.removeHasKeyPkAtPosition(0);
 380    startEnd.end();
 381
 382    startEnd.start();
 383    assertNotNull(pojo.getId());
 384    assertEquals(2, pojo.getFlights().size());
 385    assertEquals(2, pojo.getHasKeyPks().size());
 386    assertEquals(2, pojo.getBidirChildren().size());
 387
 388    Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
 389    assertNotNull(pojoEntity);
 390    assertEquals(4, pojoEntity.getProperties().size());
 391    assertEquals(Utils.newArrayList(
 392        KeyFactory.stringToKey(bidir2.getId()),
 393        KeyFactory.stringToKey(bidir3.getId())), pojoEntity.getProperty("bidirChildren"));
 394    assertEquals(Utils.newArrayList(
 395        KeyFactory.stringToKey(f2.getId()),
 396        KeyFactory.stringToKey(f3.getId())), pojoEntity.getProperty("flights"));
 397    assertEquals(Utils.newArrayList(
 398        hasKeyPk2.getKey(),
 399        hasKeyPk3.getKey()), pojoEntity.getProperty("hasKeyPks"));
 400
 401    startEnd.end();
 402
 403    try {
 404      ds.get(KeyFactory.stringToKey(bidir1Id));
 405      fail("expected EntityNotFoundException");
 406    } catch (EntityNotFoundException enfe) {
 407      // good
 408    }
 409    try {
 410      ds.get(KeyFactory.stringToKey(flight1Id));
 411      fail("expected EntityNotFoundException");
 412    } catch (EntityNotFoundException enfe) {
 413      // good
 414    }
 415    try {
 416      ds.get(hasKeyPk1Key);
 417      fail("expected EntityNotFoundException");
 418    } catch (EntityNotFoundException enfe) {
 419      // good
 420    }
 421    Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidir2.getId()));
 422    assertNotNull(bidirChildEntity);
 423    assertEquals("another yam", bidirChildEntity.getProperty("childVal"));
 424    assertEquals(KeyFactory.stringToKey(bidir2.getId()), bidirChildEntity.getKey());
 425    assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidir2.getId());
 426    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 427      assertEquals(0L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
 428    }
 429
 430    bidirChildEntity = ds.get(KeyFactory.stringToKey(bidir3.getId()));
 431    assertNotNull(bidirChildEntity);
 432    assertEquals("yet another yam", bidirChildEntity.getProperty("childVal"));
 433    assertEquals(KeyFactory.stringToKey(bidir3.getId()), bidirChildEntity.getKey());
 434    assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidir2.getId());
 435    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 436      assertEquals(1L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
 437    }
 438
 439    Entity flightEntity = ds.get(KeyFactory.stringToKey(f2.getId()));
 440    assertNotNull(flightEntity);
 441    assertEquals("bos", flightEntity.getProperty("origin"));
 442    assertEquals("mia", flightEntity.getProperty("dest"));
 443    assertEquals("another name", flightEntity.getProperty("name"));
 444    assertEquals(KeyFactory.stringToKey(f2.getId()), flightEntity.getKey());
 445    assertKeyParentEquals(pojo.getId(), flightEntity, f2.getId());
 446    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 447      assertEquals(0L, flightEntity.getProperty("flights_INTEGER_IDX"));
 448    }
 449
 450    flightEntity = ds.get(KeyFactory.stringToKey(f3.getId()));
 451    assertNotNull(flightEntity);
 452    assertEquals("bos", flightEntity.getProperty("origin"));
 453    assertEquals("mia", flightEntity.getProperty("dest"));
 454    assertEquals("yet another name", flightEntity.getProperty("name"));
 455    assertEquals(KeyFactory.stringToKey(f3.getId()), flightEntity.getKey());
 456    assertKeyParentEquals(pojo.getId(), flightEntity, f2.getId());
 457    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 458      assertEquals(1L, flightEntity.getProperty("flights_INTEGER_IDX"));
 459    }
 460
 461    Entity hasKeyPkEntity = ds.get(hasKeyPk2.getKey());
 462    assertNotNull(hasKeyPkEntity);
 463    assertEquals("another str", hasKeyPkEntity.getProperty("str"));
 464    assertEquals(hasKeyPk2.getKey(), hasKeyPkEntity.getKey());
 465    assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk2.getKey());
 466    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 467      assertEquals(0L, hasKeyPkEntity.getProperty("hasKeyPks_INTEGER_IDX"));
 468    }
 469
 470    hasKeyPkEntity = ds.get(hasKeyPk3.getKey());
 471    assertNotNull(hasKeyPkEntity);
 472    assertEquals("yet another str", hasKeyPkEntity.getProperty("str"));
 473    assertEquals(hasKeyPk3.getKey(), hasKeyPkEntity.getKey());
 474    assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk2.getKey());
 475    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 476      assertEquals(1L, hasKeyPkEntity.getProperty("hasKeyPks_INTEGER_IDX"));
 477    }
 478
 479    Entity parentEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
 480    assertNotNull(parentEntity);
 481    assertEquals(4, parentEntity.getProperties().size());
 482    assertEquals("yar", parentEntity.getProperty("val"));
 483    assertEquals(Utils.newArrayList(
 484        KeyFactory.stringToKey(bidir2.getId()),
 485        KeyFactory.stringToKey(bidir3.getId())), parentEntity.getProperty("bidirChildren"));
 486    assertEquals(Utils.newArrayList(
 487        KeyFactory.stringToKey(f2.getId()),
 488        KeyFactory.stringToKey(f3.getId())), parentEntity.getProperty("flights"));
 489    assertEquals(Utils.newArrayList(
 490        hasKeyPk2.getKey(),
 491        hasKeyPk3.getKey()), parentEntity.getProperty("hasKeyPks"));
 492
 493    assertCountsInDatastore(pojo.getClass(), bidir2.getClass(), 1, 2);
 494  }
 495
 496  void testAddAtPosition(HasOneToManyJDO pojo,
 497      BidirectionalChildJDO bidir1,
 498      BidirectionalChildJDO bidir2, StartEnd startEnd) throws EntityNotFoundException {
 499    pojo.setVal("yar");
 500    bidir2.setChildVal("yam");
 501    Flight f = newFlight();
 502    Flight f2 = newFlight();
 503    f2.setName("another name");
 504    HasKeyPkJDO hasKeyPk = new HasKeyPkJDO();
 505    HasKeyPkJDO hasKeyPk2 = new HasKeyPkJDO();
 506    hasKeyPk2.setStr("another str");
 507
 508    pojo.addFlight(f);
 509    pojo.addHasKeyPk(hasKeyPk);
 510    pojo.addBidirChild(bidir1);
 511
 512    startEnd.start();
 513    pm.makePersistent(pojo);
 514    startEnd.end();
 515
 516    assertCountsInDatastore(pojo.getClass(), bidir1.getClass(), 1, 1);
 517
 518    startEnd.start();
 519    pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
 520    String bidir1Id = pojo.getBidirChildren().iterator().next().getId();
 521    String flight1Id = pojo.getFlights().iterator().next().getId();
 522    Key hasKeyPk1Key = pojo.getHasKeyPks().iterator().next().getKey();
 523    pojo.addAtPosition(0, bidir2);
 524    pojo.addAtPosition(0, f2);
 525    pojo.addAtPosition(0, hasKeyPk2);
 526    startEnd.end();
 527
 528    startEnd.start();
 529    pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
 530    assertNotNull(pojo.getId());
 531    assertEquals(2, pojo.getFlights().size());
 532    assertEquals(2, pojo.getHasKeyPks().size());
 533    assertEquals(2, pojo.getBidirChildren().size());
 534    assertNotNull(bidir2.getId());
 535    assertNotNull(bidir2.getParent());
 536    assertNotNull(f2.getId());
 537    assertNotNull(hasKeyPk2.getKey());
 538
 539    Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
 540    assertNotNull(pojoEntity);
 541    assertEquals(4, pojoEntity.getProperties().size());
 542    assertEquals(Utils.newArrayList(
 543        KeyFactory.stringToKey(bidir2.getId()),
 544        KeyFactory.stringToKey(bidir1.getId())), pojoEntity.getProperty("bidirChildren"));
 545    assertEquals(Utils.newArrayList(
 546        KeyFactory.stringToKey(f2.getId()),
 547        KeyFactory.stringToKey(f.getId())), pojoEntity.getProperty("flights"));
 548    assertEquals(Utils.newArrayList(
 549        hasKeyPk2.getKey(),
 550        hasKeyPk.getKey()), pojoEntity.getProperty("hasKeyPks"));
 551
 552    startEnd.end();
 553
 554    ds.get(KeyFactory.stringToKey(bidir1Id));
 555    ds.get(KeyFactory.stringToKey(flight1Id));
 556    ds.get(hasKeyPk1Key);
 557    Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidir2.getId()));
 558    assertNotNull(bidirChildEntity);
 559    assertEquals("yam", bidirChildEntity.getProperty("childVal"));
 560    assertEquals(KeyFactory.stringToKey(bidir2.getId()), bidirChildEntity.getKey());
 561    assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidir2.getId());
 562    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 563      assertEquals(0L, bidirChildEntity.getProperty("bidirChildren_INTEGER_IDX"));
 564    }
 565
 566    Entity flightEntity = ds.get(KeyFactory.stringToKey(f2.getId()));
 567    assertNotNull(flightEntity);
 568    assertEquals("bos", flightEntity.getProperty("origin"));
 569    assertEquals("mia", flightEntity.getProperty("dest"));
 570    assertEquals("another name", flightEntity.getProperty("name"));
 571    assertEquals(KeyFactory.stringToKey(f2.getId()), flightEntity.getKey());
 572    assertKeyParentEquals(pojo.getId(), flightEntity, f2.getId());
 573    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 574      assertEquals(0L, flightEntity.getProperty("flights_INTEGER_IDX"));
 575    }
 576
 577    Entity hasKeyPkEntity = ds.get(hasKeyPk2.getKey());
 578    assertNotNull(hasKeyPkEntity);
 579    assertEquals("another str", hasKeyPkEntity.getProperty("str"));
 580    assertEquals(hasKeyPk2.getKey(), hasKeyPkEntity.getKey());
 581    assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk2.getKey());
 582    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 583      assertEquals(0L, hasKeyPkEntity.getProperty("hasKeyPks_INTEGER_IDX"));
 584    }
 585
 586    Entity parentEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
 587    assertNotNull(parentEntity);
 588    assertEquals(4, parentEntity.getProperties().size());
 589    assertEquals("yar", parentEntity.getProperty("val"));
 590    assertEquals(Utils.newArrayList(
 591        KeyFactory.stringToKey(bidir2.getId()),
 592        KeyFactory.stringToKey(bidir1.getId())), parentEntity.getProperty("bidirChildren"));
 593    assertEquals(Utils.newArrayList(
 594        KeyFactory.stringToKey(f2.getId()),
 595        KeyFactory.stringToKey(f.getId())), parentEntity.getProperty("flights"));
 596    assertEquals(Utils.newArrayList(
 597        hasKeyPk2.getKey(),
 598        hasKeyPk.getKey()), parentEntity.getProperty("hasKeyPks"));
 599
 600    assertCountsInDatastore(pojo.getClass(), bidir2.getClass(), 1, 2);
 601  }
 602
 603  void testUpdate_UpdateChildWithMerge(HasOneToManyJDO pojo,
 604      BidirectionalChildJDO bidir, StartEnd startEnd) throws EntityNotFoundException {
 605    Flight f = newFlight();
 606    HasKeyPkJDO hasKeyPk = new HasKeyPkJDO();
 607
 608    pojo.addFlight(f);
 609    pojo.addHasKeyPk(hasKeyPk);
 610    pojo.addBidirChild(bidir);
 611    bidir.setParent(pojo);
 612
 613    startEnd.start();
 614    pm.makePersistent(pojo);
 615    startEnd.end();
 616
 617    assertNotNull(f.getId());
 618    assertNotNull(hasKeyPk.getKey());
 619    assertNotNull(bidir.getId());
 620    assertNotNull(pojo.getId());
 621
 622    startEnd.start();
 623    f.setOrigin("yam");
 624    hasKeyPk.setStr("yar");
 625    bidir.setChildVal("yap");
 626    pm.makePersistent(pojo);
 627    startEnd.end();
 628
 629    Entity flightEntity = ds.get(KeyFactory.stringToKey(f.getId()));
 630    assertNotNull(flightEntity);
 631    assertEquals("yam", flightEntity.getProperty("origin"));
 632    assertKeyParentEquals(pojo.getId(), flightEntity, f.getId());
 633    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 634      assertEquals(0L, flightEntity.getProperty("flights_INTEGER_IDX"));
 635    }
 636
 637    Entity hasKeyPkEntity = ds.get(hasKeyPk.getKey());
 638    assertNotNull(hasKeyPkEntity);
 639    assertEquals("yar", hasKeyPkEntity.getProperty("str"));
 640    assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk.getKey());
 641    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 642      assertEquals(0L, hasKeyPkEntity.getProperty("hasKeyPks_INTEGER_IDX"));
 643    }
 644
 645    Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidir.getId()));
 646    assertNotNull(bidirEntity);
 647    assertEquals("yap", bidirEntity.getProperty("childVal"));
 648    assertKeyParentEquals(pojo.getId(), bidirEntity, bidir.getId());
 649    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 650      assertEquals(0L, bidirEntity.getProperty("bidirChildren_INTEGER_IDX"));
 651    }
 652
 653    assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 1);
 654  }
 655
 656  void testUpdate_UpdateChild(HasOneToManyJDO pojo,
 657      BidirectionalChildJDO bidir, StartEnd startEnd) throws EntityNotFoundException {
 658    Flight f = newFlight();
 659    HasKeyPkJDO hasKeyPk = new HasKeyPkJDO();
 660
 661    pojo.addFlight(f);
 662    pojo.addHasKeyPk(hasKeyPk);
 663    pojo.addBidirChild(bidir);
 664    bidir.setParent(pojo);
 665
 666    startEnd.start();
 667    pm.makePersistent(pojo);
 668    startEnd.end();
 669
 670    assertNotNull(f.getId());
 671    assertNotNull(hasKeyPk.getKey());
 672    assertNotNull(bidir.getId());
 673    assertNotNull(pojo.getId());
 674
 675    startEnd.start();
 676    pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
 677    pojo.getFlights().iterator().next().setOrigin("yam");
 678    pojo.getHasKeyPks().iterator().next().setStr("yar");
 679    pojo.getBidirChildren().iterator().next().setChildVal("yap");
 680    startEnd.end();
 681
 682    Entity flightEntity = ds.get(KeyFactory.stringToKey(f.getId()));
 683    assertNotNull(flightEntity);
 684    assertEquals("yam", flightEntity.getProperty("origin"));
 685    assertKeyParentEquals(pojo.getId(), flightEntity, f.getId());
 686    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 687      assertEquals(0L, flightEntity.getProperty("flights_INTEGER_IDX"));
 688    }
 689
 690    Entity hasKeyPkEntity = ds.get(hasKeyPk.getKey());
 691    assertNotNull(hasKeyPkEntity);
 692    assertEquals("yar", hasKeyPkEntity.getProperty("str"));
 693    assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk.getKey());
 694    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 695      assertEquals(0L, hasKeyPkEntity.getProperty("hasKeyPks_INTEGER_IDX"));
 696    }
 697
 698    Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidir.getId()));
 699    assertNotNull(bidirEntity);
 700    assertEquals("yap", bidirEntity.getProperty("childVal"));
 701    assertKeyParentEquals(pojo.getId(), bidirEntity, bidir.getId());
 702    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
 703      assertEquals(0L, bidirEntity.getProperty("bidirChildren_INTEGER_IDX"));
 704    }
 705
 706    assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 1);
 707  }
 708
 709  void testUpdate_NullOutChildren(HasOneToManyJDO pojo,
 710    BidirectionalChildJDO bidir, StartEnd startEnd) throws EntityNotFoundException {
 711    Flight f = newFlight();
 712    HasKeyPkJDO hasKeyPk = new HasKeyPkJDO();
 713
 714    pojo.addFlight(f);
 715    pojo.addHasKeyPk(hasKeyPk);
 716    pojo.addBidirChild(bidir);
 717    bidir.setParent(pojo);
 718
 719    startEnd.start();
 720    pm.makePersistent(pojo);
 721    startEnd.end();
 722
 723    assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 1);
 724
 725    startEnd.start();
 726    String flightId = f.getId();
 727    Key hasKeyPkKey = hasKeyPk.getKey();
 728    String bidirChildId = bidir.getId();
 729
 730    pojo.nullFlights();
 731    pojo.nullHasKeyPks();
 732    pojo.nullBidirChildren();
 733    pm.makePersistent(pojo);
 734    startEnd.end();
 735
 736    try {
 737      ds.get(KeyFactory.stringToKey(flightId));
 738      fail("expected enfe");
 739    } catch (EntityNotFoundException enfe) {
 740      // good
 741    }
 742
 743    try {
 744      ds.get(hasKeyPkKey);
 745      fail("expected enfe");
 746    } catch (EntityNotFoundException enfe) {
 747      // good
 748    }
 749
 750    try {
 751      ds.get(KeyFactory.stringToKey(bidirChildId));
 752      fail("expected enfe");
 753    } catch (EntityNotFoundException enfe) {
 754      // good
 755    }
 756
 757    Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
 758    assertEquals(4, pojoEntity.getProperties().size());
 759    assertTrue(pojoEntity.hasProperty("bidirChildren"));
 760    assertNull(pojoEntity.getProperty("bidirChildren"));
 761    assertTrue(pojoEntity.hasProperty("flights"));
 762    assertNull(pojoEntity.getProperty("flights"));
 763    assertTrue(pojoEntity.hasProperty("hasKeyPks"));
 764    assertNull(pojoEntity.getProperty("hasKeyPks"));
 765
 766    assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 0);
 767  }
 768
 769  void testUpdate_ClearOutChildren(HasOneToManyJDO pojo,
 770      BidirectionalChildJDO bidir, StartEnd startEnd) throws EntityNotFoundException {
 771    Flight f = newFlight();
 772    HasKeyPkJDO hasKeyPk = new HasKeyPkJDO();
 773
 774    pojo.addFlight(f);
 775    pojo.addHasKeyPk(hasKeyPk);
 776    pojo.addBidirChild(bidir);
 777    bidir.setParent(pojo);
 778
 779    startEnd.start();
 780    pm.makePersistent(pojo);
 781    startEnd.end();
 782    String flightId = f.getId();
 783    Key hasKeyPkId = hasKeyPk.getKey();
 784    String bidirChildId = bidir.getId();
 785    assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 1);
 786
 787    startEnd.start();
 788    pojo = pm.makePersistent(pojo);
 789    pojo.clearFlights();
 790    pojo.clearHasKeyPks();
 791    pojo.clearBidirChildren();
 792    startEnd.end();
 793
 794    try {
 795      ds.get(KeyFactory.stringToKey(flightId));
 796      fail("expected enfe");
 797    } catch (EntityNotFoundException enfe) {
 798      // good
 799    }
 800
 801    try {
 802      ds.get(hasKeyPkId);
 803      fail("expected enfe");
 804    } catch (EntityNotFoundException enfe) {
 805      // good
 806    }
 807
 808    try {
 809      ds.get(KeyFactory.stringToKey(bidirChildId));
 810      fail("expected enfe");
 811    } catch (EntityNotFoundException enfe) {
 812      // good
 813    }
 814
 815    Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId()));
 816    assertEquals(4, pojoEntity.getProperties().size());
 817    assertTrue(pojoEntity.hasProperty("bidirChildren"));
 818    assertNull(pojoEntity.getProperty("bidirChildren"));
 819    assertTrue(pojoEntity.hasProperty("flights"));
 820    assertNull(pojoEntity.getProperty("flights"));
 821    assertTrue(pojoEntity.hasProperty("hasKeyPks"));
 822    assertNull(pojoEntity.getProperty("hasKeyPks"));
 823
 824    assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 0);
 825  }
 826
 827  void testFindWithOrderBy(Class<? extends HasOneToManyWithOrderByJDO> pojoClass, StartEnd startEnd)
 828      throws EntityNotFoundException {
 829    getExecutionContext().getNucleusContext().getPersistenceConfiguration().setProperty(
 830        "datanucleus.appengine.allowMultipleRelationsOfSameType", true);
 831    Entity pojoEntity = new Entity(pojoClass.getSimpleName());
 832    ds.put(pojoEntity);
 833
 834    Entity flightEntity1 = newFlightEntity(pojoEntity.getKey(), "bos1", "mia2", "name 1");
 835    flightEntity1.setProperty("flightsByOrigAndDest_INTEGER_IDX", 0);
 836    flightEntity1.setProperty("flightsByIdAndOrig_INTEGER_IDX", 0);
 837    flightEntity1.setProperty("flightsByOrigAndId_INTEGER_IDX", 0);
 838    ds.put(flightEntity1);
 839
 840    Entity flightEntity2 = newFlightEntity(pojoEntity.getKey(), "bos2", "mia2", "name 2");
 841    flightEntity2.setProperty("flightsByOrigAndDest_INTEGER_IDX", 1);
 842    flightEntity2.setProperty("flightsByIdAndOrig_INTEGER_IDX", 1);
 843    flightEntity2.setProperty("flightsByOrigAndId_INTEGER_IDX", 1);
 844    ds.put(flightEntity2);
 845
 846    Entity flightEntity3 = newFlightEntity(pojoEntity.getKey(), "bos1", "mia1", "name 0");
 847    flightEntity3.setProperty("flightsByOrigAndDest_INTEGER_IDX", 2);
 848    flightEntity3.setProperty("flightsByIdAndOrig_INTEGER_IDX", 2);
 849    flightEntity3.setProperty("flightsByOrigAndId_INTEGER_IDX", 2);
 850    ds.put(flightEntity3);
 851
 852    Entity explicitIndexEntity1 =
 853        new Entity(HasExplicitIndexColumnJDO.class.getSimpleName(), pojoEntity.getKey());
 854    explicitIndexEntity1.setProperty("index", 3);
 855    ds.put(explicitIndexEntity1);
 856
 857    Entity explicitIndexEntity2 =
 858        new Entity(HasExplicitIndexColumnJDO.class.getSimpleName(), pojoEntity.getKey());
 859    explicitIndexEntity2.setProperty("index", 2);
 860    ds.put(explicitIndexEntity2);
 861
 862    Entity explicitIndexEntity3 =
 863        new Entity(HasExplicitIndexColumnJDO.class.getSimpleName(), pojoEntity.getKey());
 864    explicitIndexEntity3.setProperty("index", 1);
 865    ds.put(explicitIndexEntity3);
 866
 867    pojoEntity.setProperty("flightsByOrigAndDest", Utils.newArrayList(flightEntity2.getKey(), flightEntity3.getKey(), flightEntity1.getKey()));
 868    pojoEntity.setProperty("flightsByIdAndOrig", Utils.newArrayList(flightEntity3.getKey(), flightEntity2.getKey(), flightEntity1.getKey()));
 869    pojoEntity.setProperty("flightsByOrigAndId", Utils.newArrayList(flightEntity2.getKey(), flightEntity1.getKey(), flightEntity3.getKey()));
 870    pojoEntity.setProperty("hasIndexColumn", Utils.newArrayList(explicitIndexEntity3.getKey(), explicitIndexEntity2.getKey(), explicitIndexEntity1.getKey()));
 871    ds.put(pojoEntity);
 872
 873    startEnd.start();
 874    HasOneToManyWithOrderByJDO pojo = pm.getObjectById(
 875        pojoClass, KeyFactory.keyToString(pojoEntity.getKey()));
 876    assertNotNull(pojo);
 877    assertNotNull(pojo.getFlightsByOrigAndDest());
 878    assertEquals(3, pojo.getFlightsByOrigAndDest().size());
 879    assertEquals("name 2", pojo.getFlightsByOrigAndDest().get(0).getName());
 880    assertEquals("name 0", pojo.getFlightsByOrigAndDest().get(1).getName());
 881    assertEquals("name 1", pojo.getFlightsByOrigAndDest().get(2).getName());
 882
 883    assertNotNull(pojo.getFlightsByIdAndOrig());
 884    assertEquals(3, pojo.getFlightsByIdAndOrig().size());
 885    assertEquals("name 0", pojo.getFlightsByIdAndOrig().get(0).getName());
 886    assertEquals("name 2", pojo.getFlightsByIdAndOrig().get(1).getName());
 887    assertEquals("name 1", pojo.getFlightsByIdAndOrig().get(2).getName());
 888
 889    assertNotNull(pojo.getFlightsByOrigAndId());
 890    assertEquals(3, pojo.getFlightsByOrigAndId().size());
 891    assertEquals("name 2", pojo.getFlightsByOrigAndId().get(0).getName());
 892    assertEquals("name 1", pojo.getFlightsByOrigAndId().get(1).getName());
 893    assertEquals("name 0", pojo.getFlightsByOrigAndId().get(2).getName());
 894
 895    assertNotNull(pojo.getHasIndexColumn());
 896    assertEquals(3, pojo.getHasIndexColumn().size());
 897    assertEquals(explicitIndexEntity3.getKey(), pojo.getHasIndexColumn().get(0).getId());
 898    assertEquals(explicitIndexEntity2.getKey(), pojo.getHasIndexColumn().get(1).getId());
 899    assertEquals(explicitIndexEntity1.getKey(), pojo.getHasIndexColumn().get(2).getId());
 900
 901    startEnd.end();
 902  }
 903
 904  void testFind(Class<? extends HasOneToManyJDO> pojoClass,
 905      Class<? extends BidirectionalChildJDO> bidirClass, StartEnd startEnd) throws EntityNotFoundException {
 906    Entity pojoEntity = new Entity(pojoClass.getSimpleName());
 907    ds.put(pojoEntity);
 908
 909    Entity flightEntity = newFlightEntity(pojoEntity.getKey(), "bos1", "mia2", "name 1");
 910    ds.put(flightEntity);
 911
 912    Entity hasKeyPkEntity = new Entity(HasKeyPkJDO.class.getSimpleName(), pojoEntity.getKey());
 913    hasKeyPkEntity.setProperty("str", "yar");
 914    hasKeyPkEntity.setProperty("hasKeyPks_INTEGER_IDX", 1);
 915    ds.put(hasKeyPkEntity);
 916
 917    Entity bidirEntity = new Entity(bidirClass.getSimpleName(), pojoEntity.getKey());
 918    bidirEntity.setProperty("childVal", "yap");
 919    bidirEntity.setProperty("bidirChildren_INTEGER_IDX", 1);
 920    ds.put(bidirEntity);
 921
 922    pojoEntity.setProperty("bidirChildren", Utils.newArrayList(bidirEntity.getKey()));
 923    pojoEntity.setProperty("hasKeyPks", Utils.newArrayList(hasKeyPkEntity.getKey()));
 924    pojoEntity.setProperty("flights", Utils.newArrayList(flightEntity.getKey()));
 925    ds.put(pojoEntity);
 926
 927    startEnd.start();
 928    HasOneToManyJDO pojo =
 929        pm.getObjectById(pojoClass, KeyFactory.keyToString(pojoEntity.getKey()));
 930    assertNotNull(pojo);
 931    assertNotNull(pojo.getFlights());
 932    assertEquals(1, pojo.getFlights().size());
 933    assertEquals("bos1", pojo.getFlights().iterator().next().getOrigin());
 934    assertNotNull(pojo.getHasKeyPks());
 935    assertEquals(1, pojo.getHasKeyPks().size());
 936    assertEquals("yar", pojo.getHasKeyPks().iterator().next().getStr());
 937    assertNotNull(pojo.getBidirChildren());
 938    assertEquals(1, pojo.getBidirChildren().size());
 939    assertEquals("yap", pojo.getBidirChildren().iterator().next().getChildVal());
 940    assertEquals(pojo, pojo.getBidirChildren().iterator().next().getParent());
 941    startEnd.end();
 942  }
 943
 944  void testQuery(Class<? extends HasOneToManyJDO> pojoClass,
 945      Class<? extends BidirectionalChildJDO> bidirClass, StartEnd startEnd) throws EntityNotFoundException {
 946    Entity pojoEntity = new Entity(pojoClass.getSimpleName());
 947    ds.put(pojoEntity);
 948
 949    Entity flightEntity = newFlightEntity(pojoEntity.getKey(), "bos", "mia2", "name");
 950    ds.put(flightEntity);
 951
 952    Entity hasKeyPkEntity = new Entity(HasKeyPkJDO.class.getSimpleName(), pojoEntity.getKey());
 953    hasKeyPkEntity.setProperty("str", "yar");
 954    hasKeyPkEntity.setProperty("hasKeyPks_INTEGER_IDX", 1);
 955    ds.put(hasKeyPkEntity);
 956
 957    Entity bidirEntity = new Entity(bidirClass.getSimpleName(), pojoEntity.getKey());
 958    bidirEntity.setProperty("childVal", "yap");
 959    bidirEntity.setProperty("bidirChildren_INTEGER_IDX", 1);
 960    ds.put(bidirEntity);
 961
 962    pojoEntity.setProperty("bidirChildren", Utils.newArrayList(bidirEntity.getKey()));
 963    pojoEntity.setProperty("hasKeyPks", Utils.newArrayList(hasKeyPkEntity.getKey()));
 964    pojoEntity.setProperty("flights", Utils.newArrayList(flightEntity.getKey()));
 965    ds.put(pojoEntity);
 966
 967    javax.jdo.Query q = pm.newQuery(
 968        "select from " + pojoClass.getName() + " where id == key parameters String key");
 969    startEnd.start();
 970    @SuppressWarnings("unchecked")
 971    List<HasOneToManyListJDO> result =
 972        (List<HasOneToManyListJDO>) q.execute(KeyFactory.keyToString(pojoEntity.getKey()));
 973    assertEquals(1, result.size());
 974    HasOneToManyJDO pojo = result.get(0);
 975    assertNotNull(pojo.getFlights());
 976    assertEquals(1, pojo.getFlights().size());
 977    assertEquals("bos", pojo.getFlights().iterator().next().getOrigin());
 978    assertEquals(1, pojo.getFlights().size());
 979    assertNotNull(pojo.getHasKeyPks());
 980    assertEquals(1, pojo.getHasKeyPks().size());
 981    assertEquals("yar", pojo.getHasKeyPks().iterator().next().getStr());
 982    assertNotNull(pojo.getBidirChildren());
 983    assertEquals(1, pojo.getBidirChildren().size());
 984    assertEquals("yap", pojo.getBidirChildren().iterator().next().getChildVal());
 985    assertEquals(pojo, pojo.getBidirChildren().iterator().next().getParent());
 986    startEnd.end();
 987  }
 988
 989  void testChildFetchedLazily(Class<? extends HasOneToManyJDO> pojoClass,
 990      Class<? extends BidirectionalChildJDO> bidirClass) throws Exception {
 991    DatastoreServiceConfig config = getStoreManager().getDefaultDatastoreServiceConfigForReads();
 992    tearDown();
 993    DatastoreService mockDatastore = EasyMock.createMock(DatastoreService.class);
 994    DatastoreService original = DatastoreServiceFactoryInternal.getDatastoreService(config);
 995    DatastoreServiceFactoryInternal.setDatastoreService(mockDatastore);
 996    try {
 997      setUp();
 998
 999      Entity pojoEntity = new Entity(pojoClass.getSimpleName());
1000      ds.put(pojoEntity);
1001
1002      Entity FlightEntity = newFlightEntity(pojoEntity.getKey(), "bos", "mia", "name");
1003      ds.put(FlightEntity);
1004
1005      Entity hasKeyPkEntity = new Entity(HasKeyPkJDO.class.getSimpleName(), pojoEntity.getKey());
1006      hasKeyPkEntity.setProperty("str", "yar");
1007      ds.put(hasKeyPkEntity);
1008
1009      Entity bidirEntity = new Entity(bidirClass.getSimpleName(), pojoEntity.getKey());
1010      bidirEntity.setProperty("childVal", "yap");
1011      ds.put(bidirEntity);
1012
1013      Transaction txn = EasyMock.createMock(Transaction.class);
1014      EasyMock.expect(txn.getId()).andReturn("1").times(2);
1015      txn.commit();
1016      EasyMock.expectLastCall();
1017      EasyMock.replay(txn);
1018      EasyMock.expect(mockDatastore.beginTransaction(EasyMock.isA(TransactionOptions.class))).andReturn(txn);
1019      // the only get we're going to perform is for the pojo
1020      EasyMock.expect(mockDatastore.get(txn, pojoEntity.getKey())).andReturn(pojoEntity);
1021      EasyMock.replay(mockDatastore);
1022
1023      beginTxn();
1024      HasOneToManyJDO pojo =
1025          pm.getObjectById(pojoClass, KeyFactory.keyToString(pojoEntity.getKey()));
1026      assertNotNull(pojo);
1027      pojo.getId();
1028      commitTxn();
1029    } finally {
1030      DatastoreServiceFactoryInternal.setDatastoreService(original);
1031    }
1032    EasyMock.verify(mockDatastore);
1033  }
1034
1035  void testDeleteParentDeletesChild(Class<? extends HasOneToManyJDO> pojoClass,
1036      Class<? extends BidirectionalChildJDO> bidirClass, StartEnd startEnd) throws Exception {
1037    Entity pojoEntity = new Entity(pojoClass.getSimpleName());
1038    ds.put(pojoEntity);
1039
1040    Entity flightEntity = newFlightEntity(pojoEntity.getKey(), "bos", "mia", "name");
1041    flightEntity.setProperty("flights_INTEGER_IDX", 1);
1042    ds.put(flightEntity);
1043
1044    Entity hasKeyPkEntity = new Entity(HasKeyPkJDO.class.getSimpleName(), pojoEntity.getKey());
1045    hasKeyPkEntity.setProperty("str", "yar");
1046    hasKeyPkEntity.setProperty("hasKeyPks_INTEGER_IDX", 1);
1047    ds.put(hasKeyPkEntity);
1048
1049    Entity bidirEntity = new Entity(bidirClass.getSimpleName(), pojoEntity.getKey());
1050    bidirEntity.setProperty("childVal", "yap");
1051    bidirEntity.setProperty("bidirChildren_INTEGER_IDX", 1);
1052    ds.put(bidirEntity);
1053
1054    pojoEntity.setProperty("bidirChildren", Utils.newArrayList(bidirEntity.getKey()));
1055    pojoEntity.setProperty("hasKeyPks", Utils.newArrayList(hasKeyPkEntity.getKey()));
1056    pojoEntity.setProperty("flights", Utils.newArrayList(flightEntity.getKey()));
1057    ds.put(pojoEntity);
1058
1059    startEnd.start();
1060    HasOneToManyJDO pojo = pm.getObjectById(pojoClass, KeyFactory.keyToString(pojoEntity.getKey()));
1061    pm.deletePersistent(pojo);
1062    startEnd.end();
1063    assertCountsInDatastore(pojoClass, bidirClass, 0, 0);
1064  }
1065
1066  void testRemoveAll(HasOneToManyJDO pojo, BidirectionalChildJDO bidir1,
1067                     BidirectionalChildJDO bidir2, BidirectionalChildJDO bidir3, StartEnd startEnd)
1068      throws EntityNotFoundException {
1069    Flight f1 = new Flight();
1070    Flight f2 = new Flight();
1071    Flight f3 = new Flight();
1072    pojo.addFlight(f1);
1073    pojo.addFlight(f2);
1074    pojo.addFlight(f3);
1075
1076    pojo.addBidirChild(bidir1);
1077    pojo.addBidirChild(bidir2);
1078    pojo.addBidirChild(bidir3);
1079
1080    startEnd.start();
1081    pm.makePersistent(pojo);
1082    startEnd.end();
1083    startEnd.start();
1084    pojo = pm.makePersistent(pojo);
1085    String f2Id = f2.getId();
1086    String bidir2Id = bidir2.getId();
1087    pojo.removeFlights(Collections.singleton(f2));
1088    pojo.removeBidirChildren(Collections.singleton(bidir2));
1089    startEnd.end();
1090    startEnd.start();
1091
1092    pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
1093
1094    assertEquals(2, pojo.getFlights().size());
1095    Set<String> flightIds = Utils.newHashSet(f1.getId(), f2.getId(), f3.getId());
1096    for (Flight f : pojo.getFlights()) {
1097      flightIds.remove(f.getId());
1098    }
1099    assertEquals(1, flightIds.size());
1100    assertEquals(f2.getId(), flightIds.iterator().next());
1101
1102    assertEquals(2, pojo.getBidirChildren().size());
1103    Set<String> bidirIds = Utils.newHashSet(bidir1.getId(), bidir2.getId(), bidir3.getId());
1104    for (BidirectionalChildJDO b : pojo.getBidirChildren()) {
1105      bidirIds.remove(b.getId());
1106    }
1107    assertEquals(1, bidirIds.size());
1108    assertEquals(bidir2.getId(), bidirIds.iterator().next());
1109    startEnd.end();
1110
1111    Entity flightEntity1 = ds.get(KeyFactory.stringToKey(f1.getId()));
1112    Entity flightEntity3 = ds.get(KeyFactory.stringToKey(f3.getId()));
1113    Entity bidirEntity1 = ds.get(KeyFactory.stringToKey(bidir1.getId()));
1114    Entity bidirEntity3 = ds.get(KeyFactory.stringToKey(bidir3.getId()));
1115    if (isIndexed() && getStorageVersion(pm) == StorageVersion.PARENTS_DO_NOT_REFER_TO_CHILDREN) {
1116      assertEquals(0L, flightEntity1.getProperty("flights_INTEGER_IDX"));
1117      assertEquals(1L, flightEntity3.getProperty("flights_INTEGER_IDX"));
1118      assertEquals(0L, bidirEntity1.getProperty("bidirChildren_INTEGER_IDX"));
1119      assertEquals(1L, bidirEntity3.getProperty("bidirChildren_INTEGER_IDX"));
1120    }
1121    try {
1122      ds.get(KeyFactory.stringToKey(f2Id));
1123      fail("expected enfe");
1124    } catch (EntityNotFoundException enfe) {
1125      // good
1126    }
1127    try {
1128      ds.get(KeyFactory.stringToKey(bidir2Id));
1129      fail("expected enfe");
1130    } catch (EntityNotFoundException enfe) {
1131      // good
1132    }
1133  }
1134
1135  void testRemoveAll_LongPkOnParent(HasOneToManyLongPkJDO pojo, BidirectionalChildLongPkJDO bidir1,
1136                     BidirectionalChildLongPkJDO bidir2, BidirectionalChildLongPkJDO bidir3, StartEnd startEnd)
1137      throws EntityNotFoundException {
1138    Flight f1 = new Flight();
1139    Flight f2 = new Flight();
1140    Flight f3 = new Flight();
1141    pojo.addFlight(f1);
1142    pojo.addFlight(f2);
1143    pojo.addFlight(f3);
1144
1145    pojo.addBidirChild(bidir1);
1146    pojo.addBidirChild(bidir2);
1147    pojo.addBidirChild(bidir3);
1148
1149    startEnd.start();
1150    pm.makePersistent(pojo);
1151    startEnd.end();
1152    startEnd.start();
1153    pojo = pm.makePersistent(pojo);
1154    String f2Id = f2.getId();
1155    String bidir2Id = bidir2.getId();
1156    pojo.removeFlights(Collections.singleton(f2));
1157    pojo.removeBidirChildren(Collections.singleton(bidir2));
1158    startEnd.end();
1159    startEnd.start();
1160
1161    pojo = pm.getObjectById(pojo.getClass(), pojo.getId());
1162    assertEquals(2, pojo.getFlights().size());
1163    Set<String

Large files files are truncated, but you can click here to view the full file