Package com.googlecode.objectify.test

Source Code of com.googlecode.objectify.test.EvilMemcacheBugTests$SimpleParent

/*
* $Id: BeanMixin.java 1075 2009-05-07 06:41:19Z lhoriman $
* $URL: https://subetha.googlecode.com/svn/branches/resin/rtest/src/org/subethamail/rtest/util/BeanMixin.java $
*/

package com.googlecode.objectify.test;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.memcache.MemcacheSerialization;
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Parent;
import com.googlecode.objectify.cache.CachingDatastoreServiceFactory;
import com.googlecode.objectify.test.util.TestBase;
import com.googlecode.objectify.test.util.TestObjectifyService;
import org.testng.annotations.Test;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static com.googlecode.objectify.test.util.TestObjectifyService.fact;

/**
* Tests of a bizarre bug in Google's memcache serialization of Key objects.
*
* @author Jeff Schnitzer <jeff@infohazard.org>
*/
public class EvilMemcacheBugTests extends TestBase
{
  /** */
  //private static Logger log = Logger.getLogger(EvilMemcacheBugTests.class.getName());

  /** */
  @com.googlecode.objectify.annotation.Entity
  static class SimpleParent
  {
    @Id String id;

    SimpleParent(){}
    SimpleParent(String id) {
      this.id = id;
    }

    static Key<SimpleParent> getSimpleParentKey(String id) {
      return Key.create(SimpleParent.class, id);
    }
  }

  /** */
  @com.googlecode.objectify.annotation.Entity
  @Cache
  static class SimpleEntity
  {
    @Id
    String id;
    @Parent Key<SimpleParent> simpleParentKey;
    String foo = "bar";

    static Key<SimpleEntity> getSimpleChildKey(String id) {
      return Key.create(SimpleParent.getSimpleParentKey(id), SimpleEntity.class, id);
    }

    SimpleEntity() {}
    SimpleEntity(String id) {
      this.id = id;
      this.simpleParentKey = SimpleParent.getSimpleParentKey(id);
    }
  }

//  /** */
//  @Test
//  public void testMoreSophisticatedInAndOutOfTransaction() throws Exception {
//    fact().register(SimpleParent.class);
//    fact().register(SimpleEntity.class);
//    String simpleId = "btoc";
//
//    Key<SimpleEntity> childKey = SimpleEntity.getSimpleChildKey(simpleId);
//    SimpleEntity simple = new SimpleEntity(simpleId);
//
//    TestObjectify nonTxnOfy = fact().begin();
//    nonTxnOfy.put(simple);
//
//    TestObjectify txnOfy = fact().begin().startTransaction();
//    SimpleEntity simple2;
//    try {
//      simple2 = txnOfy.get(childKey);
//      simple2.foo = "joe";
//      txnOfy.put(simple2);
//      txnOfy.getTransaction().commit();
//    } finally {
//      if (txnOfy.getTransaction().isActive())
//        txnOfy.getTransaction().rollback();
//    }
//
//    nonTxnOfy.clear();
//    SimpleEntity simple3 = nonTxnOfy.get(childKey);
//
//    assert simple2.foo.equals(simple3.foo);
//  }

  /** */
  @Test
  public void testRawTransactionalCaching() throws Exception {
    // Need to register it so the entity kind becomes cacheable
    fact().register(SimpleEntity.class);

    DatastoreService ds = TestObjectifyService.ds();
    DatastoreService cacheds = CachingDatastoreServiceFactory.getDatastoreService();

    // This is the weirdest thing.  If you change the *name* of one of these two keys, the test passes.
    // If the keys have the same *name*, the test fails because ent3 has the "original" property.  WTF??
    com.google.appengine.api.datastore.Key parentKey = KeyFactory.createKey("SimpleParent", "asdf");
    com.google.appengine.api.datastore.Key childKey = KeyFactory.createKey(parentKey, "SimpleEntity", "asdf");

    Entity ent1 = new Entity(childKey);
    ent1.setProperty("foo", "original");
    cacheds.put(ent1);

    // Weirdly, this will solve the problem too
    //MemcacheService cs = MemcacheServiceFactory.getMemcacheService();
    //cs.clearAll();

    Transaction txn = cacheds.beginTransaction();
    Entity ent2;
    try {
      ent2 = ds.get(txn, childKey);
      //ent2 = new Entity(childKey);  // solves the problem
      ent2.setProperty("foo", "changed");
      cacheds.put(txn, ent2);
      txn.commit();
    } finally {
      if (txn.isActive())
        txn.rollback();
    }

    Entity ent3 = cacheds.get(childKey);

    assert "changed".equals(ent3.getProperty("foo"));
  }

  /** */
  @SuppressWarnings({ "unchecked", "rawtypes" })
  @Test
  public void testRawCaching() throws Exception {
    // I can not for the life of me figure out why this test passes when the
    // previous test fails.

    MemcacheService cs1 = MemcacheServiceFactory.getMemcacheService("blah");

    com.google.appengine.api.datastore.Key parentKey = KeyFactory.createKey("SimpleParent", "asdf");
    com.google.appengine.api.datastore.Key childKey = KeyFactory.createKey(parentKey, "SimpleEntity", "asdf");

    Entity ent = new Entity(childKey);
    ent.setProperty("foo", "original");
    cs1.put(childKey, ent);

    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    ds.put(ent);

    Transaction txn = ds.beginTransaction();
    try {
      Entity ent2 = ds.get(txn, childKey);
 
      //Entity ent2 = (Entity)cs1.get(childKey);
      assert ent2.getProperty("foo").equals("original");
      ent2.setProperty("foo", "changed");
 
      Map<Object, Object> holder = new HashMap<>();
      holder.put(childKey, ent2);
      cs1.putAll(holder);
 
      Map<Object, Object> fetched = cs1.getAll((Collection)Collections.singleton(childKey));
      Entity ent3 = (Entity)fetched.get(childKey);
      assert ent3.getProperty("foo").equals("changed");
    } finally {
      if (txn.isActive())
        txn.rollback();
    }
  }

  /** */
  @Test
  public void testEntityKeys() throws Exception
  {
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();

    com.google.appengine.api.datastore.Key parentKeyA = KeyFactory.createKey("SimpleParent", "same");
    com.google.appengine.api.datastore.Key childKeyA = KeyFactory.createKey(parentKeyA, "SimpleEntity", "different");

    Entity entA1 = new Entity(childKeyA);
    ds.put(entA1);

    Entity entA2 = ds.get(childKeyA);

    assert new String(MemcacheSerialization.makePbKey(entA1.getKey())).equals(new String(MemcacheSerialization.makePbKey(childKeyA)));
    assert new String(MemcacheSerialization.makePbKey(entA2.getKey())).equals(new String(MemcacheSerialization.makePbKey(childKeyA)));

    com.google.appengine.api.datastore.Key parentKeyB = KeyFactory.createKey("SimpleParent", "same");
    com.google.appengine.api.datastore.Key childKeyB = KeyFactory.createKey(parentKeyB, "SimpleEntity", "same");

    Entity entB1 = new Entity(childKeyB);
    ds.put(entB1);

    Entity entB2 = ds.get(childKeyB);

    // This works
    assert new String(MemcacheSerialization.makePbKey(entB1.getKey())).equals(new String(MemcacheSerialization.makePbKey(childKeyB)));

    // This fails!  It is a bug in the datastore.  See http://code.google.com/p/googleappengine/issues/detail?id=2088
    // Objectify works around this problem, so it is not a serious issue.
    // Update: This succeeds!  As of SDK 1.6.0 this has been fixed.  The Objectify workaround (stringifying keys) has been removed.
    assert new String(MemcacheSerialization.makePbKey(entB2.getKey())).equals(new String(MemcacheSerialization.makePbKey(childKeyB)));
  }

//  /** The comment was wrong - the grabTail method was removed in GAE SDK 1.6.0! */
//  @SuppressWarnings("rawtypes")
//  @Test
//  public void testWithoutObjectify()  throws Exception {
//    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
//    MemcacheService ms = MemcacheServiceFactory.getMemcacheService("testing1423");
//
//    com.google.appengine.api.datastore.Key parentKey = KeyFactory.createKey("SimpleParent", "asdf");
//    com.google.appengine.api.datastore.Key childKey = KeyFactory.createKey(parentKey, "SimpleEntity", "asdf");
//
//    //save a test entity
//    Entity ent1 = new Entity(childKey);
//    ent1.setProperty("foo", "original");
//    ds.put(null, ent1);
//    ms.put(ent1.getKey(), ent1);
//
//    //load it, and change the value.
//    Entity ent1loaded = ds.get(null, ent1.getKey());
//    ent1loaded.setProperty("foo", "changed");
//    //save it to the datastore and memcache
//    ds.put(null, ent1loaded);
//    ms.put(ent1loaded.getKey(), ent1loaded);
//
//    //dump memcache -- silly GAE can't hide this method from me!
//    Method meth = ms.getClass().getMethod("grabTail", int.class);
//    meth.setAccessible(true);
//    List dump = (List)meth.invoke(ms, 100);
//    for(Object obj : dump)
//      log.info(obj.toString());
//
//    assert (dump.size() == 1);
////    Entity ent3 = (Entity) ms.getAll((Collection)Collections.singleton(childKey)).values().toArray()[0];
//
////    assert "changed".equals(ent3.getProperty("foo"));
//
//  }
}
TOP

Related Classes of com.googlecode.objectify.test.EvilMemcacheBugTests$SimpleParent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.