Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google App Engine: Unit testing concurrent access to memcache

Would you guys show me a way to simulating concurrent access to memcache on Google App Engine? I'm trying with LocalServiceTestHelpers and threads but don't have any luck. Every time I try to access Memcache within a thread, then I get this error:

ApiProxy$CallNotFoundException: The API package 'memcache' or call 'Increment()' was not found

I guess that the testing library of GAE SDK tried to mimic the real environment and thus setup the environment for only one thread (the thread that running the test) which cannot be seen by other thread.

Here is a piece of code that can reproduce the problem

package org.seamoo.cache.memcacheImpl;

import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.tools.development.testing.LocalMemcacheServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;

public class MemcacheTest {
 LocalServiceTestHelper helper;

 public MemcacheTest() {
  LocalMemcacheServiceTestConfig memcacheConfig = new LocalMemcacheServiceTestConfig();
  helper = new LocalServiceTestHelper(memcacheConfig);
 }

 /**
  * 
  */
 @BeforeMethod
 public void setUp() {
  helper.setUp();
 }

 /**
  * @see LocalServiceTest#tearDown()
  */
 @AfterMethod
 public void tearDown() {
  helper.tearDown();
 }

 @Test
 public void memcacheConcurrentAccess() throws InterruptedException {
  final MemcacheService service = MemcacheServiceFactory.getMemcacheService();
  Runnable runner = new Runnable() {

   @Override
   public void run() {
    // TODO Auto-generated method stub
    service.increment("test-key", 1L, 1L);
    try {
     Thread.sleep(200L);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    service.increment("test-key", 1L, 1L);
   }
  };

  Thread t1 = new Thread(runner);
  Thread t2 = new Thread(runner);
  t1.start();
  t2.start();
  while (t1.isAlive()) {
   Thread.sleep(100L);
  }
  Assert.assertEquals((Long) (service.get("test-key")), new Long(4L));
 }
}
like image 390
Phương Nguyễn Avatar asked Feb 28 '23 03:02

Phương Nguyễn


1 Answers

Are you trying to test your app, or App Engine's memcache implementation? The semantics of memcache under concurrent reads and writes are well understood - you'd be better off simply simulating the conditions that can occur in order to verify your app handles them fine.

like image 157
Nick Johnson Avatar answered Apr 02 '23 20:04

Nick Johnson