Package org.springframework.data.redis.core

Source Code of org.springframework.data.redis.core.RedisTemplateTests

/*
* Copyright 2013-2014 the original author or authors.
*
* 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 org.springframework.data.redis.core;

import static org.junit.Assert.*;
import static org.junit.Assume.*;
import static org.springframework.data.redis.SpinBarrier.*;
import static org.springframework.data.redis.matcher.RedisTestMatchers.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.hamcrest.core.IsNot;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.redis.ObjectFactory;
import org.springframework.data.redis.RedisTestProfileValueSource;
import org.springframework.data.redis.SettingsUtils;
import org.springframework.data.redis.TestCondition;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.jredis.JredisConnectionFactory;
import org.springframework.data.redis.connection.srp.SrpConnectionFactory;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.data.redis.core.query.SortQueryBuilder;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
* Integration test of {@link RedisTemplate}
*
* @author Jennifer Hickey
* @author Christoph Strobl
*/
@RunWith(Parameterized.class)
public class RedisTemplateTests<K, V> {

  @Autowired private RedisTemplate<K, V> redisTemplate;

  private ObjectFactory<K> keyFactory;

  private ObjectFactory<V> valueFactory;

  public RedisTemplateTests(RedisTemplate<K, V> redisTemplate, ObjectFactory<K> keyFactory,
      ObjectFactory<V> valueFactory) {
    this.redisTemplate = redisTemplate;
    this.keyFactory = keyFactory;
    this.valueFactory = valueFactory;
  }

  @After
  public void tearDown() {
    redisTemplate.execute(new RedisCallback<Object>() {
      public Object doInRedis(RedisConnection connection) {
        connection.flushDb();
        return null;
      }
    });
  }

  @Parameters
  public static Collection<Object[]> testParams() {
    return AbstractOperationsTestParams.testParams();
  }

  @Test
  public void testDumpAndRestoreNoTtl() {
    assumeTrue(RedisTestProfileValueSource.matches("redisVersion", "2.6"));
    K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.boundValueOps(key1).set(value1);
    byte[] serializedValue = redisTemplate.dump(key1);
    assertNotNull(serializedValue);
    redisTemplate.delete(key1);
    redisTemplate.restore(key1, serializedValue, 0, TimeUnit.SECONDS);
    assertThat(redisTemplate.boundValueOps(key1).get(), isEqual(value1));
  }

  @Test
  public void testRestoreTtl() {
    assumeTrue(RedisTestProfileValueSource.matches("redisVersion", "2.6"));
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.boundValueOps(key1).set(value1);
    byte[] serializedValue = redisTemplate.dump(key1);
    assertNotNull(serializedValue);
    redisTemplate.delete(key1);
    redisTemplate.restore(key1, serializedValue, 200, TimeUnit.MILLISECONDS);
    assertThat(redisTemplate.boundValueOps(key1).get(), isEqual(value1));
    waitFor(new TestCondition() {
      public boolean passes() {
        return (!redisTemplate.hasKey(key1));
      }
    }, 400);
  }

  @SuppressWarnings("unchecked")
  @Test
  public void testKeys() throws Exception {
    K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    assumeTrue(key1 instanceof String || key1 instanceof byte[]);
    redisTemplate.opsForValue().set(key1, value1);
    K keyPattern = key1 instanceof String ? (K) "*" : (K) "*".getBytes();
    assertNotNull(redisTemplate.keys(keyPattern));
  }

  @SuppressWarnings("rawtypes")
  @Test(expected = IllegalArgumentException.class)
  public void testTemplateNotInitialized() throws Exception {
    RedisTemplate tpl = new RedisTemplate();
    tpl.setConnectionFactory(redisTemplate.getConnectionFactory());
    tpl.exec();
  }

  @Test
  public void testStringTemplateExecutesWithStringConn() {
    assumeTrue(redisTemplate instanceof StringRedisTemplate);
    String value = redisTemplate.execute(new RedisCallback<String>() {
      public String doInRedis(RedisConnection connection) {
        StringRedisConnection stringConn = (StringRedisConnection) connection;
        stringConn.set("test", "it");
        return stringConn.get("test");
      }
    });
    assertEquals(value, "it");
  }

  @Test
  public void testExec() {
    final K key1 = keyFactory.instance();
    final V value1 = valueFactory.instance();
    final K listKey = keyFactory.instance();
    final V listValue = valueFactory.instance();
    final K setKey = keyFactory.instance();
    final V setValue = valueFactory.instance();
    final K zsetKey = keyFactory.instance();
    final V zsetValue = valueFactory.instance();
    List<Object> results = redisTemplate.execute(new SessionCallback<List<Object>>() {
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public List<Object> execute(RedisOperations operations) throws DataAccessException {
        operations.multi();
        operations.opsForValue().set(key1, value1);
        operations.opsForValue().get(key1);
        operations.opsForList().leftPush(listKey, listValue);
        operations.opsForList().range(listKey, 0l, 1l);
        operations.opsForSet().add(setKey, setValue);
        operations.opsForSet().members(setKey);
        operations.opsForZSet().add(zsetKey, zsetValue, 1d);
        operations.opsForZSet().rangeWithScores(zsetKey, 0l, -1l);
        return operations.exec();
      }
    });
    List<V> list = Collections.singletonList(listValue);
    Set<V> set = new HashSet<V>(Collections.singletonList(setValue));
    Set<TypedTuple<V>> tupleSet = new LinkedHashSet<TypedTuple<V>>(Collections.singletonList(new DefaultTypedTuple<V>(
        zsetValue, 1d)));
    assertThat(results, isEqual(Arrays.asList(new Object[] { value1, 1l, list, 1l, set, true, tupleSet })));
  }

  @Test
  public void testDiscard() {
    final K key1 = keyFactory.instance();
    final V value1 = valueFactory.instance();
    final V value2 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    redisTemplate.execute(new SessionCallback<List<Object>>() {
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public List<Object> execute(RedisOperations operations) throws DataAccessException {
        operations.multi();
        operations.opsForValue().set(key1, value2);
        operations.discard();
        return null;
      }
    });
    assertThat(redisTemplate.boundValueOps(key1).get(), isEqual(value1));
  }

  @Test
  public void testExecCustomSerializer() {
    assumeTrue(redisTemplate instanceof StringRedisTemplate);
    List<Object> results = redisTemplate.execute(new SessionCallback<List<Object>>() {
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public List<Object> execute(RedisOperations operations) throws DataAccessException {
        operations.multi();
        operations.opsForValue().set("foo", "5");
        operations.opsForValue().get("foo");
        operations.opsForValue().append("foo1", "5");
        operations.opsForList().leftPush("foolist", "6");
        operations.opsForList().range("foolist", 0l, 1l);
        operations.opsForSet().add("fooset", "7");
        operations.opsForSet().members("fooset");
        operations.opsForZSet().add("foozset", "9", 1d);
        operations.opsForZSet().rangeWithScores("foozset", 0l, -1l);
        operations.opsForZSet().range("foozset", 0, -1);
        operations.opsForHash().put("foomap", "10", "11");
        operations.opsForHash().entries("foomap");
        return operations.exec(new GenericToStringSerializer<Long>(Long.class));
      }
    });
    // Everything should be converted to Longs
    List<Long> list = Collections.singletonList(6l);
    Set<Long> longSet = new HashSet<Long>(Collections.singletonList(7l));
    Set<TypedTuple<Long>> tupleSet = new LinkedHashSet<TypedTuple<Long>>(
        Collections.singletonList(new DefaultTypedTuple<Long>(9l, 1d)));
    Set<Long> zSet = new LinkedHashSet<Long>(Collections.singletonList(9l));
    Map<Long, Long> map = new LinkedHashMap<Long, Long>();
    map.put(10l, 11l);
    assertThat(results,
        isEqual(Arrays.asList(new Object[] { 5l, 1L, 1l, list, 1l, longSet, true, tupleSet, zSet, true, map })));
  }

  @Test
  public void testExecConversionDisabled() {
    SrpConnectionFactory factory2 = new SrpConnectionFactory(SettingsUtils.getHost(), SettingsUtils.getPort());
    factory2.setConvertPipelineAndTxResults(false);
    factory2.afterPropertiesSet();
    StringRedisTemplate template = new StringRedisTemplate(factory2);
    template.afterPropertiesSet();
    List<Object> results = template.execute(new SessionCallback<List<Object>>() {
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public List<Object> execute(RedisOperations operations) throws DataAccessException {
        operations.multi();
        operations.opsForValue().set("foo", "bar");
        operations.opsForValue().get("foo");
        return operations.exec();
      }
    });
    // first value is "OK" from set call, results should still be in byte[]
    assertEquals("bar", new String((byte[]) results.get(1)));
  }

  @SuppressWarnings("rawtypes")
  @Test
  public void testExecutePipelined() {
    final K key1 = keyFactory.instance();
    final V value1 = valueFactory.instance();
    final K listKey = keyFactory.instance();
    final V listValue = valueFactory.instance();
    final V listValue2 = valueFactory.instance();
    List<Object> results = redisTemplate.executePipelined(new RedisCallback() {
      public Object doInRedis(RedisConnection connection) throws DataAccessException {
        byte[] rawKey = serialize(key1, redisTemplate.getKeySerializer());
        byte[] rawListKey = serialize(listKey, redisTemplate.getKeySerializer());
        connection.set(rawKey, serialize(value1, redisTemplate.getValueSerializer()));
        connection.get(rawKey);
        connection.rPush(rawListKey, serialize(listValue, redisTemplate.getValueSerializer()));
        connection.rPush(rawListKey, serialize(listValue2, redisTemplate.getValueSerializer()));
        connection.lRange(rawListKey, 0, -1);
        return null;
      }
    });
    assertThat(results,
        isEqual(Arrays.asList(new Object[] { value1, 1l, 2l, Arrays.asList(new Object[] { listValue, listValue2 }) })));
  }

  @SuppressWarnings("rawtypes")
  @Test
  public void testExecutePipelinedCustomSerializer() {
    assumeTrue(redisTemplate instanceof StringRedisTemplate);
    List<Object> results = redisTemplate.executePipelined(new RedisCallback() {
      public Object doInRedis(RedisConnection connection) throws DataAccessException {
        StringRedisConnection stringRedisConn = (StringRedisConnection) connection;
        stringRedisConn.set("foo", "5");
        stringRedisConn.get("foo");
        stringRedisConn.rPush("foolist", "10");
        stringRedisConn.rPush("foolist", "11");
        stringRedisConn.lRange("foolist", 0, -1);
        return null;
      }
    }, new GenericToStringSerializer<Long>(Long.class));
    assertEquals(Arrays.asList(new Object[] { 5l, 1l, 2l, Arrays.asList(new Long[] { 10l, 11l }) }), results);
  }

  @Test(expected = InvalidDataAccessApiUsageException.class)
  public void testExecutePipelinedNonNullRedisCallback() {
    redisTemplate.executePipelined(new RedisCallback<String>() {
      public String doInRedis(RedisConnection connection) throws DataAccessException {
        return "Hey There";
      }
    });
  }

  @SuppressWarnings({ "rawtypes", "unchecked" })
  @Test
  public void testExecutePipelinedTx() {
    final K key1 = keyFactory.instance();
    final V value1 = valueFactory.instance();
    List<Object> pipelinedResults = redisTemplate.executePipelined(new SessionCallback() {
      public Object execute(RedisOperations operations) throws DataAccessException {
        operations.multi();
        operations.opsForList().leftPush(key1, value1);
        operations.opsForList().rightPop(key1);
        operations.opsForList().size(key1);
        operations.exec();
        operations.opsForValue().set(key1, value1);
        operations.opsForValue().get(key1);
        return null;
      }
    });
    // Should contain the List of deserialized exec results and the result of the last call to get()
    assertThat(pipelinedResults,
        isEqual(Arrays.asList(new Object[] { Arrays.asList(new Object[] { 1l, value1, 0l }), value1 })));
  }

  @SuppressWarnings({ "rawtypes", "unchecked" })
  @Test
  public void testExecutePipelinedTxCustomSerializer() {
    assumeTrue(redisTemplate instanceof StringRedisTemplate);
    List<Object> pipelinedResults = redisTemplate.executePipelined(new SessionCallback() {
      public Object execute(RedisOperations operations) throws DataAccessException {
        operations.multi();
        operations.opsForList().leftPush("fooList", "5");
        operations.opsForList().rightPop("fooList");
        operations.opsForList().size("fooList");
        operations.exec();
        operations.opsForValue().set("foo", "2");
        operations.opsForValue().get("foo");
        return null;
      }
    }, new GenericToStringSerializer<Long>(Long.class));
    // Should contain the List of deserialized exec results and the result of the last call to get()
    assertEquals(Arrays.asList(new Object[] { Arrays.asList(new Object[] { 1l, 5l, 0l }), 2l }), pipelinedResults);
  }

  @Test(expected = InvalidDataAccessApiUsageException.class)
  public void testExecutePipelinedNonNullSessionCallback() {
    redisTemplate.executePipelined(new SessionCallback<String>() {
      @SuppressWarnings("rawtypes")
      public String execute(RedisOperations operations) throws DataAccessException {
        return "Whatup";
      }
    });
  }

  @Test
  public void testDelete() {
    K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    assertTrue(redisTemplate.hasKey(key1));
    redisTemplate.delete(key1);
    assertFalse(redisTemplate.hasKey(key1));
  }

  @Test
  public void testDeleteMultiple() {
    K key1 = keyFactory.instance();
    K key2 = keyFactory.instance();
    V value1 = valueFactory.instance();
    V value2 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    redisTemplate.opsForValue().set(key2, value2);
    List<K> keys = new ArrayList<K>();
    keys.add(key1);
    keys.add(key2);
    redisTemplate.delete(keys);
    assertFalse(redisTemplate.hasKey(key1));
    assertFalse(redisTemplate.hasKey(key2));
  }

  @Test
  public void testSort() {
    K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    assumeTrue(value1 instanceof Number);
    redisTemplate.opsForList().rightPush(key1, value1);
    List<V> results = redisTemplate.sort(SortQueryBuilder.sort(key1).build());
    assertEquals(Collections.singletonList(value1), results);
  }

  @Test
  public void testSortStore() {
    K key1 = keyFactory.instance();
    K key2 = keyFactory.instance();
    V value1 = valueFactory.instance();
    assumeTrue(value1 instanceof Number);
    redisTemplate.opsForList().rightPush(key1, value1);
    assertEquals(Long.valueOf(1), redisTemplate.sort(SortQueryBuilder.sort(key1).build(), key2));
    assertEquals(Collections.singletonList(value1), redisTemplate.boundListOps(key2).range(0, -1));
  }

  @Test
  public void testSortBulkMapper() {
    K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    assumeTrue(value1 instanceof Number);
    redisTemplate.opsForList().rightPush(key1, value1);
    List<String> results = redisTemplate.sort(SortQueryBuilder.sort(key1).get("#").build(),
        new BulkMapper<String, V>() {
          public String mapBulk(List<V> tuple) {
            return "FOO";
          }
        });
    assertEquals(Collections.singletonList("FOO"), results);
  }

  @Test
  public void testExpireAndGetExpireMillis() {
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.boundValueOps(key1).set(value1);
    redisTemplate.expire(key1, 10, TimeUnit.MILLISECONDS);
    assertTrue(redisTemplate.getExpire(key1, TimeUnit.MILLISECONDS) > 0l);
    // Timeout is longer because expire will be 1 sec if pExpire not supported
    waitFor(new TestCondition() {
      public boolean passes() {
        return (!redisTemplate.hasKey(key1));
      }
    }, 1500l);
  }

  @Test
  public void testExpireMillisNotSupported() throws Exception {
    assumeTrue(RedisTestProfileValueSource.matches("runLongTests", "true"));
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    assumeTrue(key1 instanceof String && value1 instanceof String);
    // JRedis does not support pExpire
    JredisConnectionFactory factory = new JredisConnectionFactory();
    factory.setHostName(SettingsUtils.getHost());
    factory.setPort(SettingsUtils.getPort());
    factory.afterPropertiesSet();
    final StringRedisTemplate template2 = new StringRedisTemplate(factory);
    template2.boundValueOps((String) key1).set((String) value1);
    template2.expire((String) key1, 10, TimeUnit.MILLISECONDS);
    Thread.sleep(15);
    // 10 millis should get rounded up to 1 sec if pExpire not supported
    assertTrue(template2.hasKey((String) key1));
    waitFor(new TestCondition() {
      public boolean passes() {
        return (!template2.hasKey((String) key1));
      }
    }, 1000l);
  }

  @Test
  public void testGetExpireNoTimeUnit() {
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.boundValueOps(key1).set(value1);
    redisTemplate.expire(key1, 2, TimeUnit.SECONDS);
    Long expire = redisTemplate.getExpire(key1);
    // Default behavior is to return seconds
    assertTrue(expire > 0l && expire <= 2l);
  }

  @Test
  public void testGetExpireSeconds() {
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.boundValueOps(key1).set(value1);
    redisTemplate.expire(key1, 1500, TimeUnit.MILLISECONDS);
    assertEquals(Long.valueOf(1), redisTemplate.getExpire(key1, TimeUnit.SECONDS));
  }

  @Test
  public void testGetExpireMillisNotSupported() {
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    assumeTrue(key1 instanceof String && value1 instanceof String);
    // Jedis does not support pTtl
    JedisConnectionFactory factory = new JedisConnectionFactory();
    factory.setHostName(SettingsUtils.getHost());
    factory.setPort(SettingsUtils.getPort());
    factory.afterPropertiesSet();
    final StringRedisTemplate template2 = new StringRedisTemplate(factory);
    template2.boundValueOps((String) key1).set((String) value1);
    template2.expire((String) key1, 5, TimeUnit.SECONDS);
    long expire = template2.getExpire((String) key1, TimeUnit.MILLISECONDS);
    // we should still get expire in milliseconds if requested
    assertTrue(expire > 1000 && expire <= 5000);
  }

  @Test
  public void testExpireAt() {
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.boundValueOps(key1).set(value1);
    redisTemplate.expireAt(key1, new Date(System.currentTimeMillis() + 5l));
    waitFor(new TestCondition() {
      public boolean passes() {
        return (!redisTemplate.hasKey(key1));
      }
    }, 5l);
  }

  @Test
  public void testExpireAtMillisNotSupported() {
    assumeTrue(RedisTestProfileValueSource.matches("runLongTests", "true"));
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    assumeTrue(key1 instanceof String && value1 instanceof String);
    // Jedis does not support pExpireAt
    JedisConnectionFactory factory = new JedisConnectionFactory();
    factory.setHostName(SettingsUtils.getHost());
    factory.setPort(SettingsUtils.getPort());
    factory.afterPropertiesSet();
    final StringRedisTemplate template2 = new StringRedisTemplate(factory);
    template2.boundValueOps((String) key1).set((String) value1);
    template2.expireAt((String) key1, new Date(System.currentTimeMillis() + 5l));
    // Just ensure this works as expected, pExpireAt just adds some precision over expireAt
    waitFor(new TestCondition() {
      public boolean passes() {
        return (!template2.hasKey((String) key1));
      }
    }, 5l);
  }

  @Test
  public void testPersist() throws Exception {
    // Test is meaningless in Redis 2.4 because key won't expire after 10 ms
    assumeTrue(RedisTestProfileValueSource.matches("redisVersion", "2.6"));
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    redisTemplate.expire(key1, 10, TimeUnit.MILLISECONDS);
    redisTemplate.persist(key1);
    Thread.sleep(10);
    assertTrue(redisTemplate.hasKey(key1));
  }

  @Test
  public void testRandomKey() {
    K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    assertThat(redisTemplate.randomKey(), isEqual(key1));
  }

  @Test
  public void testRename() {
    K key1 = keyFactory.instance();
    K key2 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    redisTemplate.rename(key1, key2);
    assertThat(redisTemplate.opsForValue().get(key2), isEqual(value1));
  }

  @Test
  public void testRenameIfAbsent() {
    K key1 = keyFactory.instance();
    K key2 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    redisTemplate.renameIfAbsent(key1, key2);
    assertTrue(redisTemplate.hasKey(key2));
  }

  @Test
  public void testType() {
    K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    assertEquals(DataType.STRING, redisTemplate.type(key1));
  }

  @Test
  public void testWatch() {
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    final V value2 = valueFactory.instance();
    final V value3 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    final Thread th = new Thread(new Runnable() {
      public void run() {
        redisTemplate.opsForValue().set(key1, value2);
      }
    });
    List<Object> results = redisTemplate.execute(new SessionCallback<List<Object>>() {
      @SuppressWarnings({ "unchecked", "rawtypes" })
      public List<Object> execute(RedisOperations operations) throws DataAccessException {
        operations.watch(key1);
        th.start();
        try {
          th.join();
        } catch (InterruptedException e) {}
        operations.multi();
        operations.opsForValue().set(key1, value3);
        return operations.exec();
      }
    });
    assertNull(results);
    assertThat(redisTemplate.opsForValue().get(key1), isEqual(value2));
  }

  @Test
  public void testUnwatch() {
    final K key1 = keyFactory.instance();
    V value1 = valueFactory.instance();
    final V value2 = valueFactory.instance();
    final V value3 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    final Thread th = new Thread(new Runnable() {
      public void run() {
        redisTemplate.opsForValue().set(key1, value2);
      }
    });
    List<Object> results = redisTemplate.execute(new SessionCallback<List<Object>>() {
      @SuppressWarnings({ "unchecked", "rawtypes" })
      public List<Object> execute(RedisOperations operations) throws DataAccessException {
        operations.watch(key1);
        th.start();
        try {
          th.join();
        } catch (InterruptedException e) {}
        operations.unwatch();
        operations.multi();
        operations.opsForValue().set(key1, value3);
        return operations.exec();
      }
    });
    assertTrue(results.isEmpty());
    assertThat(redisTemplate.opsForValue().get(key1), isEqual(value3));
  }

  @Test
  public void testWatchMultipleKeys() {
    final K key1 = keyFactory.instance();
    final K key2 = keyFactory.instance();
    V value1 = valueFactory.instance();
    final V value2 = valueFactory.instance();
    final V value3 = valueFactory.instance();
    redisTemplate.opsForValue().set(key1, value1);
    final Thread th = new Thread(new Runnable() {
      public void run() {
        redisTemplate.opsForValue().set(key1, value2);
      }
    });
    List<Object> results = redisTemplate.execute(new SessionCallback<List<Object>>() {
      @SuppressWarnings({ "unchecked", "rawtypes" })
      public List<Object> execute(RedisOperations operations) throws DataAccessException {
        List<K> keys = new ArrayList<K>();
        keys.add(key1);
        keys.add(key2);
        operations.watch(keys);
        th.start();
        try {
          th.join();
        } catch (InterruptedException e) {}
        operations.multi();
        operations.opsForValue().set(key1, value3);
        return operations.exec();
      }
    });
    assertNull(results);
    assertThat(redisTemplate.opsForValue().get(key1), isEqual(value2));
  }

  @Test
  public void testConvertAndSend() {
    V value1 = valueFactory.instance();
    // Make sure basic message sent without Exception on serialization
    redisTemplate.convertAndSend("Channel", value1);
  }

  @Test
  public void testExecuteScriptCustomSerializers() {
    assumeTrue(RedisTestProfileValueSource.matches("redisVersion", "2.6"));
    K key1 = keyFactory.instance();
    final DefaultRedisScript<String> script = new DefaultRedisScript<String>();
    script.setScriptText("return 'Hey'");
    script.setResultType(String.class);
    assertEquals(
        "Hey",
        redisTemplate.execute(script, redisTemplate.getValueSerializer(), new StringRedisSerializer(),
            Collections.singletonList(key1)));
  }

  @Test
  public void clientListShouldReturnCorrectly() {
    assertThat(redisTemplate.getClientList().size(), IsNot.not(0));
  }

  @SuppressWarnings({ "unchecked", "rawtypes" })
  private byte[] serialize(Object value, RedisSerializer serializer) {
    if (serializer == null && value instanceof byte[]) {
      return (byte[]) value;
    }
    return serializer.serialize(value);
  }
}
TOP

Related Classes of org.springframework.data.redis.core.RedisTemplateTests

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.