diff --git a/pom.xml b/pom.xml index 479a434..3c4a69b 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ UTF-8 UTF-8 1.9.26 - [5.1.0,5.2.0) + 6.0.3 2.8.2 1.16.6 @@ -281,6 +281,9 @@ jar + + false + diff --git a/src/main/java/io/instacount/appengine/counter/data/CounterData.java b/src/main/java/io/instacount/appengine/counter/data/CounterData.java index d92df45..4ebbd31 100644 --- a/src/main/java/io/instacount/appengine/counter/data/CounterData.java +++ b/src/main/java/io/instacount/appengine/counter/data/CounterData.java @@ -172,7 +172,7 @@ public Key getTypedKey() * Assembles the Key for this entity. If an Entity has a Parent Key, that key will be included in the returned Key * heirarchy. */ - public com.google.appengine.api.datastore.Key getKey() + public com.google.cloud.datastore.Key getKey() { return this.getTypedKey().getRaw(); } diff --git a/src/main/java/io/instacount/appengine/counter/data/CounterShardData.java b/src/main/java/io/instacount/appengine/counter/data/CounterShardData.java index 460a752..c69ab10 100644 --- a/src/main/java/io/instacount/appengine/counter/data/CounterShardData.java +++ b/src/main/java/io/instacount/appengine/counter/data/CounterShardData.java @@ -136,7 +136,7 @@ public Key getTypedKey() * Assembles the Key for this entity. If an Entity has a Parent Key, that key will be included in the returned Key * heirarchy. */ - public com.google.appengine.api.datastore.Key getKey() + public com.google.cloud.datastore.Key getKey() { return this.getTypedKey().getRaw(); } diff --git a/src/main/java/io/instacount/appengine/counter/data/CounterShardOperationData.java b/src/main/java/io/instacount/appengine/counter/data/CounterShardOperationData.java index 953f1c8..dbc8fcd 100644 --- a/src/main/java/io/instacount/appengine/counter/data/CounterShardOperationData.java +++ b/src/main/java/io/instacount/appengine/counter/data/CounterShardOperationData.java @@ -141,7 +141,7 @@ public Key getTypedKey() * Assembles the Key for this entity. If an Entity has a Parent Key, that key will be included in the returned Key * heirarchy. */ - public com.google.appengine.api.datastore.Key getKey() + public com.google.cloud.datastore.Key getKey() { return this.getTypedKey().getRaw(); } diff --git a/src/test/java/com/google/appengine/api/memcache/LocalMemcacheService.java b/src/test/java/com/google/appengine/api/memcache/LocalMemcacheService.java new file mode 100644 index 0000000..6118a9c --- /dev/null +++ b/src/test/java/com/google/appengine/api/memcache/LocalMemcacheService.java @@ -0,0 +1,118 @@ +/** + * Copyright (C) 2019 Instacount Inc. (developers@instacount.io) + * + * Licensed 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 com.google.appengine.api.memcache; + +import com.googlecode.objectify.cache.IdentifiableValue; +import com.googlecode.objectify.cache.MemcacheService; +import com.googlecode.objectify.cache.spymemcached.SpyIdentifiableValue; + +import net.spy.memcached.CASValue; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Wrapper to use google's MemecacheService with Objectify + * + * This class is in google's appengine package to use a package private class + * + * @author Mohammad Sarhan + */ +public class LocalMemcacheService implements MemcacheService { + + private com.google.appengine.api.memcache.MemcacheService memcacheService; + + public LocalMemcacheService(com.google.appengine.api.memcache.MemcacheService memcacheService) + { + this.memcacheService = memcacheService; + } + + @Override + public Object get(String s) + { + return memcacheService.get(s); + } + + @Override + public Map getIdentifiables(Collection collection) + { + + Map values = + memcacheService.getIdentifiables(collection); + + Map transformed = new HashMap<>(values.size()); + + for (Map.Entry entry : values.entrySet()) + { + long cas = ((AsyncMemcacheServiceImpl.IdentifiableValueImpl) entry.getValue()).getCasId(); + Object value = entry.getValue().getValue(); + + transformed.put(entry.getKey(), + new SpyIdentifiableValue( + new CASValue<>(cas, value) + + )); + } + + return transformed; + } + + @Override + public Map getAll(Collection collection) + { + return memcacheService.getAll(collection); + } + + @Override + public void put(String s, Object o) + { + memcacheService.put(s, o); + } + + @Override + public void putAll(Map map) + { + memcacheService.putAll(map); + } + + @Override + public Set putIfUntouched(Map map) + { + + Map transformed = + new HashMap<>(map.size()); + + for (Map.Entry entry : map.entrySet()) + { + CasPut put = entry.getValue(); + long cas = ((SpyIdentifiableValue) put.getIv()).getCasValue().getCas(); + Object oldVal = put.getIv().getValue(); + Object newVal = put.getNextToStore(); + + transformed.put(entry.getKey(), + new com.google.appengine.api.memcache.MemcacheService.CasValues( + new AsyncMemcacheServiceImpl.IdentifiableValueImpl(oldVal, cas), newVal)); + } + + return memcacheService.putIfUntouched(transformed); + } + + @Override + public void deleteAll(Collection collection) + { + memcacheService.deleteAll(collection); + } +} diff --git a/src/test/java/io/instacount/appengine/counter/service/AbstractShardedCounterServiceTest.java b/src/test/java/io/instacount/appengine/counter/service/AbstractShardedCounterServiceTest.java index 58fd364..f1640e8 100644 --- a/src/test/java/io/instacount/appengine/counter/service/AbstractShardedCounterServiceTest.java +++ b/src/test/java/io/instacount/appengine/counter/service/AbstractShardedCounterServiceTest.java @@ -12,18 +12,11 @@ */ package io.instacount.appengine.counter.service; -import static org.junit.Assert.*; - -import java.math.BigInteger; - -import io.instacount.appengine.counter.data.CounterShardOperationData; -import org.junit.After; -import org.junit.Before; - import com.google.appengine.api.capabilities.CapabilitiesService; import com.google.appengine.api.capabilities.CapabilitiesServiceFactory; import com.google.appengine.api.capabilities.Capability; import com.google.appengine.api.capabilities.CapabilityStatus; +import com.google.appengine.api.memcache.LocalMemcacheService; import com.google.appengine.api.memcache.MemcacheService; import com.google.appengine.api.memcache.MemcacheServiceFactory; import com.google.appengine.api.urlfetch.URLFetchServicePb.URLFetchRequest; @@ -32,12 +25,28 @@ import com.google.appengine.tools.development.testing.LocalMemcacheServiceTestConfig; import com.google.appengine.tools.development.testing.LocalServiceTestHelper; import com.google.appengine.tools.development.testing.LocalTaskQueueTestConfig; +import com.google.cloud.datastore.Datastore; +import com.google.cloud.datastore.testing.LocalDatastoreHelper; + +import com.googlecode.objectify.ObjectifyFactory; import com.googlecode.objectify.ObjectifyService; import com.googlecode.objectify.impl.translate.opt.joda.JodaTimeTranslators; import com.googlecode.objectify.util.Closeable; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +import java.math.BigInteger; + import io.instacount.appengine.counter.Counter; import io.instacount.appengine.counter.data.CounterData; import io.instacount.appengine.counter.data.CounterShardData; +import io.instacount.appengine.counter.data.CounterShardOperationData; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; /** * An abstract base class for testing {@link ShardedCounterServiceImpl} @@ -64,6 +73,8 @@ public abstract class AbstractShardedCounterServiceTest protected MemcacheService memcache; + protected static LocalDatastoreHelper localDatastoreHelper; + protected CapabilitiesService capabilitiesService; public static class DeleteShardedCounterDeferredCallback extends LocalTaskQueueTestConfig.DeferredTaskCallback @@ -86,6 +97,13 @@ protected int executeNonDeferredRequest(URLFetchRequest req) } } + @BeforeClass + public static void startLocalDatastore() throws Exception + { + localDatastoreHelper = LocalDatastoreHelper.create(); + localDatastoreHelper.start(); + } + @Before public void setUp() throws Exception { @@ -111,6 +129,11 @@ public void setUp() throws Exception memcache = MemcacheServiceFactory.getMemcacheService(); capabilitiesService = CapabilitiesServiceFactory.getCapabilitiesService(); + // Objectify 6.x can only be tested with LocalDatastoreHelper and its own memcache interface. + final com.googlecode.objectify.cache.MemcacheService localMemcacheService = new LocalMemcacheService(memcache); + Datastore ds = localDatastoreHelper.getOptions().getService(); + ObjectifyService.init(new ObjectifyFactory(ds,localMemcacheService)); + // New Objectify 5.1 Way. See https://groups.google.com/forum/#!topic/objectify-appengine/O4FHC_i7EGk this.session = ObjectifyService.begin(); @@ -135,6 +158,21 @@ public void tearDown() this.session.close(); this.helper.tearDown(); + + try + { + //Reset after each test for test isolation. + localDatastoreHelper.reset(); + } catch (Exception e) { + //do nothing + } + } + + @AfterClass + public static void shutdownDatastore() throws Exception + { + //Only shutdown the datatstore at the end of all the tests. + localDatastoreHelper.stop(); } // ///////////////////////