Package com.google.appengine.tck.memcache

Source Code of com.google.appengine.tck.memcache.MemcacheAsync2Test

/*
* Copyright 2013 Google Inc. All Rights Reserved.
* 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.tck.memcache;


import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;

import com.google.appengine.api.memcache.AsyncMemcacheService;
import com.google.appengine.api.memcache.Expiration;
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheService.CasValues;
import com.google.appengine.api.memcache.MemcacheService.IdentifiableValue;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.api.memcache.Stats;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;


/**
* Tests Async Memcache.
*
* @author hchen@google.com (Hannah Chen)
*/
@RunWith(Arquillian.class)
public class MemcacheAsync2Test extends CacheTestBase {
    private MemcacheService memcache;
    private AsyncMemcacheService asyncMemcache;

    @Before
    public void setUp() {
        memcache = MemcacheServiceFactory.getMemcacheService();
        asyncMemcache = MemcacheServiceFactory.getAsyncMemcacheService();
        memcache.clearAll();
    }

    /**
     * Tests single put/get.
     */
    @Test
    public void testPutAndGetBasic() {
        verifyAsyncGet(KEY1, STR_VALUE);
    }

    /**
     * Tests different data type put/get.
     */
    @Test
    public void testPutAndGetTypes() {
        for (Object key : TEST_DATA) {
            assertNull(memcache.get(key));
            for (Object value : TEST_DATA) {
                verifyAsyncGet(key, value);
            }
        }
    }

    @Test
    public void testGetArray1() {
        Future<Void> future = asyncMemcache.put(KEY1, ARRAY1);
        waitOnFuture(future);
        assertArrayEquals(ARRAY1, (int[]) memcache.get(KEY1));
    }

    @Test
    public void testGetArray2() {
        Future<Void> future = asyncMemcache.put(KEY1, ARRAY2);
        waitOnFuture(future);
        assertArrayEquals(ARRAY2, (Object[]) memcache.get(KEY1));
    }

    @Test
    public void testDelete() {
        memcache.put(KEY1, STR_VALUE);
        Future<Boolean> future = asyncMemcache.delete(KEY1);
        waitOnFuture(future);
        assertNull("key1 should hold null", memcache.get(KEY1));
    }

    @Test
    public void testDeleteNoReAddTime() {
        String key = createTimeStampKey("testDeleteNoReAddTime");
        memcache.put(key, STR_VALUE);
        assertNotNull(memcache.get(key));

        // delete and do not allow re-add for another 10 seconds.
        Future<Boolean> future = asyncMemcache.delete(key, 10 * 1000);
        waitOnFuture(future);
        assertNull("key should be null", memcache.get(KEY1));

        // re-add should fail since within 10 seconds.
        assertFalse(memcache.put(key, STR_VALUE, null, MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT));
        assertNull("key should be null because of policy.", memcache.get(KEY1));
    }

    @Test
    public void testPutAll() {
        Map<Object, Object> data = createSmallBatchData();
        Future<Void> future = asyncMemcache.putAll(data);
        waitOnFuture(future);

        Map<Object, Object> fetched = memcache.getAll(data.keySet());
        assertEquals("All the keys inserted should exist.", data, fetched);
    }

    @Test
    public void testDeleteAll() {
        Map<Object, Object> data = createSmallBatchData();
        memcache.putAll(data);

        Future<Set<Object>> future = asyncMemcache.deleteAll(data.keySet());
        Set<Object> deletedKeys = waitOnFuture(future);

        assertEquals(data.keySet(), deletedKeys);
    }

    @Test
    public void testDeleteAllNoReAddTime() {
        Map<Object, Object> cacheDat = createSmallBatchData();
        memcache.putAll(cacheDat);
        Future<Set<Object>> future = asyncMemcache.deleteAll(cacheDat.keySet(), 10 * 1000);
        waitOnFuture(future);
        Map<Object, Object> retValues = memcache.getAll(cacheDat.keySet());
        assertEquals("All keys should be deleted.", 0, retValues.size());

        memcache.putAll(cacheDat, null, MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT);
        Map<Object, Object> retValuesAfter = memcache.getAll(cacheDat.keySet());
        assertEquals("No keys should be added because of policy.", 0, retValuesAfter.size());
    }

    @Test
    public void testCancel() {
        Map<Object, Object> data = createSmallBatchData();
        Future<Void> future = asyncMemcache.putAll(data);
        boolean cancelled = future.cancel(true);

        // There's no guarantee that the cancel succeeds on the backend, so just verify that the
        // fundamental future api works.
        assertTrue(future.isDone())// Should always be true once cancel() returns.

        if (cancelled) {
            assertTrue(future.isCancelled());
        }
    }

    @Test
    public void testIncrementAll() {
        Map<Object, Long> map = createLongBatchData();
        memcache.putAll(map);

        long delta = 10;
        Future<Map<Object, Long>> future = asyncMemcache.incrementAll(map.keySet(), delta);
        Map<Object, Long> returned = waitOnFuture(future);

        Map<Object, Object> expected = new HashMap<Object, Object>();
        for (Map.Entry<Object, Long> entry : map.entrySet()) {
            expected.put(entry.getKey(), entry.getValue() + delta);
        }
        assertEquals(expected, returned);

        Map<Object, Object> fetched = memcache.getAll(map.keySet());
        assertEquals(expected, fetched);
    }

    @Test
    public void testIncrementAllInitValue() {
        Map<Object, Long> map = createLongBatchData();
        memcache.putAll(map);

        long delta = 10;
        Long initVal = -111L;
        Map<Object, Long> expected = copyMapIncrementLongValue(map, delta);

        // Add the key which doesn't exist yet.
        String nonExistentKey = "testIncrementAllInitValue-" + System.currentTimeMillis();
        expected.put(nonExistentKey, initVal + delta);

        Future<Map<Object, Long>> future = asyncMemcache.incrementAll(expected.keySet(), delta, initVal);
        Map<Object, Long> returned = waitOnFuture(future);
        assertEquals(expected, returned);

        Map<Object, Object> fetched = memcache.getAll(expected.keySet());
        assertEquals(expected, fetched);
    }

    @Test
    public void testIncrementAllFromMap() {
        Map<Object, Long> map = createLongBatchData();
        memcache.putAll(map);

        Map<Object, Long> incMap = createRandomIncrementMap(map);

        Future<Map<Object, Long>> future = asyncMemcache.incrementAll(incMap);
        Map<Object, Long> returned = waitOnFuture(future);

        Map<Object, Long> expected = createMapFromIncrementMap(map, incMap);
        assertEquals(expected, returned);

        Map<Object, Object> fetched = memcache.getAll(map.keySet());
        assertEquals(expected, fetched);
    }

    @Test
    public void testIncrementAllFromMapInitValue() {
        Map<Object, Long> map = createLongBatchData();
        memcache.putAll(map);

        Map<Object, Long> incMap = createRandomIncrementMap(map);

        Map<Object, Long> expected = createMapFromIncrementMap(map, incMap);

        Long initVal = -111L;
        // Add the key which doesn't exist yet.
        String nonExistentKey = "testIncrementAllFromMapInitValue-" + System.currentTimeMillis();
        incMap.put(nonExistentKey, 123L);
        expected.put(nonExistentKey, initVal + 123L);

        Future<Map<Object, Long>> future = asyncMemcache.incrementAll(incMap, initVal);
        Map<Object, Long> returned = waitOnFuture(future);
        assertEquals(expected, returned);

        Map<Object, Object> fetched = memcache.getAll(incMap.keySet());
        assertEquals(expected, fetched);
    }

    @Test
    public void testGetIdentifiables() {
        memcache.put(KEY1, STR_VALUE);

        Future<IdentifiableValue> future = asyncMemcache.getIdentifiable(KEY1);
        IdentifiableValue identVal = waitOnFuture(future);
        assertEquals(STR_VALUE, identVal.getValue());

        // batch versions
        Map<Object, Object> map = new HashMap<Object, Object>();
        for (Object key : TEST_DATA) {
            map.put(key, key);
        }
        waitOnFuture(asyncMemcache.putAll(map));

        Future<Map<Object, IdentifiableValue>> futureMap = asyncMemcache.getIdentifiables(Arrays.asList(TEST_DATA));
        Map<Object, IdentifiableValue> ivMap = waitOnFuture(futureMap);
        for (Object key : ivMap.keySet()) {
            assertEquals(key, ivMap.get(key).getValue());
        }
    }

    @Test
    public void testPutIfUntouched() {
        final String TS_KEY = createTimeStampKey("testPutIfUntouched");

        memcache.put(TS_KEY, STR_VALUE);
        IdentifiableValue oldOriginalIdValue = memcache.getIdentifiable(TS_KEY);
        final String NEW_VALUE = "new-" + STR_VALUE;
        Future<Boolean> future;
        Boolean valueWasStored;

        // Store NEW_VALUE if no other value stored since oldOriginalIdValue was retrieved.
        // memcache.get() has not been called, so this put should succeed.
        future = asyncMemcache.putIfUntouched(TS_KEY, oldOriginalIdValue, NEW_VALUE);
        valueWasStored = waitOnFuture(future);
        assertEquals(true, valueWasStored);
        assertEquals(NEW_VALUE, memcache.get(TS_KEY));

        // NEW_VALUE was stored so this put should not happen.
        final String ANOTHER_VALUE = "another-" + STR_VALUE;
        future = asyncMemcache.putIfUntouched(TS_KEY, oldOriginalIdValue, ANOTHER_VALUE);
        valueWasStored = waitOnFuture(future);
        assertEquals(false, valueWasStored);

        assertNotSame(ANOTHER_VALUE, memcache.get(TS_KEY));
        assertEquals(NEW_VALUE, memcache.get(TS_KEY));
    }

    @Test
    public void testPutIfUntouchedMap() {
        // batch versions
        Object[] testDat = {1, STR_VALUE};
        Map<Object, Object> inputDat = new HashMap<Object, Object>();
        for (Object key : testDat) {
            inputDat.put(key, key);
        }
        memcache.putAll(inputDat);
        Set<Object> set;

        Map<Object, CasValues> updateDat = new HashMap<Object, CasValues>();
        for (Object key : testDat) {
            updateDat.put(key, new CasValues(memcache.getIdentifiable(key), "new value"));
        }
        Future<Set<Object>> futureSet = asyncMemcache.putIfUntouched(updateDat);
        set = waitOnFuture(futureSet);
        assertEquals(2, set.size());
        assertEquals("new value", memcache.get(testDat[0]));

        futureSet = asyncMemcache.putIfUntouched(updateDat);
        set = waitOnFuture(futureSet);
        assertEquals(0, set.size());
    }

    @Test
    public void testPutIfUntouchedExpire() {
        final String TS_KEY = createTimeStampKey("testPutIfUntouched");

        memcache.put(TS_KEY, STR_VALUE);
        IdentifiableValue oldOriginalIdValue = memcache.getIdentifiable(TS_KEY);
        final String NEW_VALUE = "new-" + STR_VALUE;
        Future<Boolean> future;
        Boolean valueWasStored;

        // Store NEW_VALUE if no other value stored since oldOriginalIdValue was retrieved.
        // memcache.get() has not been called, so this put should succeed.
        future = asyncMemcache.putIfUntouched(TS_KEY, oldOriginalIdValue, NEW_VALUE, Expiration.byDeltaSeconds(1));
        valueWasStored = waitOnFuture(future);
        assertEquals(true, valueWasStored);
        assertEquals(NEW_VALUE, memcache.get(TS_KEY));

        // Value should not be stored after expiration period.
        sync(3000);
        assertNull(memcache.get(TS_KEY));
    }

    @Test
    public void testPutIfUntouchedMapExpire() {
        // batch versions
        Object[] testDat = {1, STR_VALUE};
        Map<Object, Object> inputDat = new HashMap<Object, Object>();
        for (Object key : testDat) {
            inputDat.put(key, key);
        }
        memcache.putAll(inputDat);
        Set<Object> set;

        Map<Object, CasValues> updateDat = new HashMap<Object, CasValues>();
        for (Object key : testDat) {
            updateDat.put(key, new CasValues(memcache.getIdentifiable(key), "new value", Expiration.byDeltaSeconds(60 * 60)));
        }
        Future<Set<Object>> futureSet = asyncMemcache.putIfUntouched(updateDat, Expiration.byDeltaMillis(1000));
        set = waitOnFuture(futureSet);
        assertEquals(2, set.size());
        assertEquals("new value", memcache.get(testDat[0]));

        sync(3000);
        assertNull(memcache.get(testDat));
    }

    @Test
    public void testStatistics() {
        Future<Stats> future = asyncMemcache.getStatistics();
        Stats stats = waitOnFuture(future);
        assertNotNull("Stats should never be null.", stats);

        // Only verify that all stats are non-negative.
        assertTrue(stats.getBytesReturnedForHits() > -1L);
        assertTrue(stats.getHitCount() > -1L);
        assertTrue(stats.getItemCount() > -1L);
        assertTrue(stats.getMaxTimeWithoutAccess() > -1);
        assertTrue(stats.getMissCount() > -1L);
        assertTrue(stats.getTotalItemBytes() > -1L);
    }

    @Test
    public void testAsyncWithNamespace() {
        String namespace = "namespace-123";

        AsyncMemcacheService ams = MemcacheServiceFactory.getAsyncMemcacheService(namespace);

        String key = "some-random-key";
        String value = "some-random-value";

        waitOnFuture(ams.put(key, value));

        // non-namespaced lookup
        Assert.assertFalse(memcache.contains(key));

        MemcacheService ms = MemcacheServiceFactory.getMemcacheService(namespace);
        Assert.assertEquals(value, ms.get(key));
    }

    private void verifyAsyncGet(Object key, Object value) {
        Future<Void> putFuture = asyncMemcache.put(key, value);
        waitOnFuture(putFuture);
        Future<Object> getFuture = asyncMemcache.get(key);
        waitOnFuture(getFuture);
        assertFalse("future shouldn't be cancelled", getFuture.isCancelled());
        assertEquals(value, memcache.get(key));
    }

    // A debugging aid to show cache stats along with a failure message
    @SuppressWarnings("unused")
    private String failure(String msg) {
        Stats statistics = memcache.getStatistics();
        StringBuilder sb = new StringBuilder();
        sb
            .append(msg)
            .append(" (")
            .append(statistics.getItemCount())
            .append("/")
            .append(statistics.getHitCount())
            .append("/")
            .append(statistics.getMissCount())
            .append(")");
        return sb.toString();
    }
}
TOP

Related Classes of com.google.appengine.tck.memcache.MemcacheAsync2Test

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.