/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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.apache.geode.redis;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.test.junit.categories.IntegrationTest;
import org.apache.geode.redis.GeodeRedisServer;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Tuple;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import static org.apache.geode.distributed.ConfigurationProperties.*;
import static org.junit.Assert.*;
@Category(IntegrationTest.class)
public class SortedSetsJUnitTest {
private static Jedis jedis;
private static GeodeRedisServer server;
private static GemFireCache cache;
private static Random rand;
private static int port = 6379;
@BeforeClass
public static void setUp() throws IOException {
rand = new Random();
CacheFactory cf = new CacheFactory();
// cf.set("log-file", "redis.log");
cf.set(LOG_LEVEL, "error");
cf.set(MCAST_PORT, "0");
cf.set(LOCATORS, "");
cache = cf.create();
port = AvailablePortHelper.getRandomAvailableTCPPort();
server = new GeodeRedisServer("localhost", port);
server.start();
jedis = new Jedis("localhost", port, 10000000);
}
@Test
public void testZAddZRange() {
int numMembers = 10;
String key = randString();
Map<String, Double> scoreMembers = new HashMap<String, Double>();
for (int i = 0; i < numMembers; i++)
scoreMembers.put(randString(), rand.nextDouble());
jedis.zadd(key, scoreMembers);
int k = 0;
for (String entry : scoreMembers.keySet())
assertNotNull(jedis.zscore(key, entry));
Set<Tuple> results = jedis.zrangeWithScores(key, 0, -1);
Map<String, Double> resultMap = new HashMap<String, Double>();
for (Tuple t : results) {
resultMap.put(t.getElement(), t.getScore());
}
assertEquals(scoreMembers, resultMap);
for (int i = 0; i < 10; i++) {
int start;
int stop;
do {
start = rand.nextInt(numMembers);
stop = rand.nextInt(numMembers);
} while (start > stop);
results = jedis.zrangeWithScores(key, start, stop);
List<Entry<String, Double>> resultList = new ArrayList<Entry<String, Double>>();
for (Tuple t : results)
resultList.add(new AbstractMap.SimpleEntry<String, Double>(t.getElement(), t.getScore()));
List<Entry<String, Double>> list =
new ArrayList<Entry<String, Double>>(scoreMembers.entrySet());
Collections.sort(list, new EntryCmp());
list = list.subList(start, stop + 1);
assertEquals(list, resultList);
}
}
@Test
public void testZRevRange() {
int numMembers = 10;
String key = randString();
Map<String, Double> scoreMembers = new HashMap<String, Double>();
for (int i = 0; i < numMembers; i++)
scoreMembers.put(randString(), rand.nextDouble());
jedis.zadd(key, scoreMembers);
Set<Tuple> results;
for (int i = 0; i < 10; i++) {
int start;
int stop;
do {
start = rand.nextInt(numMembers);
stop = rand.nextInt(numMembers);
} while (start > stop);
results = jedis.zrevrangeWithScores(key, start, stop);
List<Entry<String, Double>> resultList = new ArrayList<Entry<String, Double>>();
for (Tuple t : results)
resultList.add(new AbstractMap.SimpleEntry<String, Double>(t.getElement(), t.getScore()));
List<Entry<String, Double>> list =
new ArrayList<Entry<String, Double>>(scoreMembers.entrySet());
Collections.sort(list, new EntryRevCmp());
list = list.subList(start, stop + 1);
assertEquals(list, resultList);
}
}
@Test
public void testZCount() {
int num = 10;
int runs = 2;
for (int i = 0; i < runs; i++) {
Double min;
Double max;
do {
min = rand.nextDouble();
max = rand.nextDouble();
} while (min > max);
int count = 0;
String key = randString();
Map<String, Double> scoreMembers = new HashMap<String, Double>();
for (int j = 0; j < num; j++) {
Double nextDouble = rand.nextDouble();
if (nextDouble >= min && nextDouble <= max)
count++;
scoreMembers.put(randString(), nextDouble);
}
jedis.zadd(key, scoreMembers);
Long countResult = jedis.zcount(key, min, max);
assertTrue(count == countResult);
}
}
@Test
public void testZIncrBy() {
String key = randString();
String member = randString();
Double score = 0.0;
for (int i = 0; i < 20; i++) {
Double incr = rand.nextDouble();
Double result = jedis.zincrby(key, incr, member);
score += incr;
assertEquals(score, result, 1.0 / 100000000.0);
}
jedis.zincrby(key, Double.MAX_VALUE, member);
Double infResult = jedis.zincrby(key, Double.MAX_VALUE, member);
assertEquals(infResult, Double.valueOf(Double.POSITIVE_INFINITY));
}
public void testZRangeByScore() {
Double min;
Double max;
for (int j = 0; j < 2; j++) {
do {
min = rand.nextDouble();
max = rand.nextDouble();
} while (min > max);
int numMembers = 500;
String key = randString();
Map<String, Double> scoreMembers = new HashMap<String, Double>();
List<Entry<String, Double>> expected = new ArrayList<Entry<String, Double>>();
for (int i = 0; i < numMembers; i++) {
String s = randString();
Double d = rand.nextDouble();
scoreMembers.put(s, d);
if (d > min && d < max)
expected.add(new AbstractMap.SimpleEntry<String, Double>(s, d));
}
jedis.zadd(key, scoreMembers);
Set<Tuple> results = jedis.zrangeByScoreWithScores(key, min, max);
List<Entry<String, Double>> resultList = new ArrayList<Entry<String, Double>>();
for (Tuple t : results)
resultList.add(new AbstractMap.SimpleEntry<String, Double>(t.getElement(), t.getScore()));
Collections.sort(expected, new EntryCmp());
assertEquals(expected, resultList);
jedis.del(key);
}
}
public void testZRevRangeByScore() {
Double min;
Double max;
for (int j = 0; j < 2; j++) {
do {
min = rand.nextDouble();
max = rand.nextDouble();
} while (min > max);
int numMembers = 500;
String key = randString();
Map<String, Double> scoreMembers = new HashMap<String, Double>();
List<Entry<String, Double>> expected = new ArrayList<Entry<String, Double>>();
for (int i = 0; i < numMembers; i++) {
String s = randString();
Double d = rand.nextDouble();
scoreMembers.put(s, d);
if (d > min && d < max)
expected.add(new AbstractMap.SimpleEntry<String, Double>(s, d));
}
jedis.zadd(key, scoreMembers);
Set<Tuple> results = jedis.zrevrangeByScoreWithScores(key, max, min);
List<Entry<String, Double>> resultList = new ArrayList<Entry<String, Double>>();
for (Tuple t : results)
resultList.add(new AbstractMap.SimpleEntry<String, Double>(t.getElement(), t.getScore()));
Collections.sort(expected, new EntryRevCmp());
assertEquals(expected, resultList);
jedis.del(key);
}
}
@Test
public void testZRemZScore() {
Double min;
Double max;
for (int j = 0; j < 2; j++) {
do {
min = rand.nextDouble();
max = rand.nextDouble();
} while (min > max);
int numMembers = 5000;
String key = randString();
Map<String, Double> scoreMembers = new HashMap<String, Double>();
List<Entry<String, Double>> expected = new ArrayList<Entry<String, Double>>();
for (int i = 0; i < numMembers; i++) {
String s = randString();
Double d = rand.nextDouble();
scoreMembers.put(s, d);
if (d > min && d < max)
expected.add(new AbstractMap.SimpleEntry<String, Double>(s, d));
}
jedis.zadd(key, scoreMembers);
Collections.sort(expected, new EntryCmp());
for (int i = expected.size(); i > 0; i--) {
Entry<String, Double> remEntry = expected.remove(i - 1);
String rem = remEntry.getKey();
Double val = remEntry.getValue();
assertEquals(val, jedis.zscore(key, rem));
assertTrue(jedis.zrem(key, rem) == 1);
}
String s = randString();
if (!expected.contains(s))
assertTrue(jedis.zrem(key, s) == 0);
jedis.del(key);
}
}
@Test
public void testZRank() {
for (int j = 0; j < 2; j++) {
int numMembers = 10;
String key = randString();
Map<String, Double> scoreMembers = new HashMap<String, Double>();
List<Entry<String, Double>> expected = new ArrayList<Entry<String, Double>>();
for (int i = 0; i < numMembers; i++) {
String s = randString();
Double d = rand.nextDouble();
scoreMembers.put(s, d);
expected.add(new AbstractMap.SimpleEntry<String, Double>(s, d));
}
Collections.sort(expected, new EntryCmp());
jedis.zadd(key, scoreMembers);
for (int i = 0; i < expected.size(); i++) {
Entry<String, Double> en = expected.get(i);
String field = en.getKey();
Long rank = jedis.zrank(key, field);
assertEquals(new Long(i), rank);
}
String field = randString();
if (!expected.contains(field))
assertNull(jedis.zrank(key, field));
jedis.del(key);
}
}
@Test
public void testZRevRank() {
for (int j = 0; j < 2; j++) {
int numMembers = 10;
String key = randString();
Map<String, Double> scoreMembers = new HashMap<String, Double>();
List<Entry<String, Double>> expected = new ArrayList<Entry<String, Double>>();
for (int i = 0; i < numMembers; i++) {
String s = randString();
Double d = rand.nextDouble();
scoreMembers.put(s, d);
expected.add(new AbstractMap.SimpleEntry<String, Double>(s, d));
}
Collections.sort(expected, new EntryRevCmp());
jedis.zadd(key, scoreMembers);
for (int i = 0; i < expected.size(); i++) {
Entry<String, Double> en = expected.get(i);
String field = en.getKey();
Long rank = jedis.zrevrank(key, field);
assertEquals(new Long(i), rank);
}
String field = randString();
if (!expected.contains(field))
assertNull(jedis.zrank(key, field));
jedis.del(key);
}
}
private class EntryCmp implements Comparator<Entry<String, Double>> {
@Override
public int compare(Entry<String, Double> o1, Entry<String, Double> o2) {
Double diff = o1.getValue() - o2.getValue();
if (diff == 0)
return o2.getKey().compareTo(o1.getKey());
else
return diff > 0 ? 1 : -1;
}
}
private class EntryRevCmp implements Comparator<Entry<String, Double>> {
@Override
public int compare(Entry<String, Double> o1, Entry<String, Double> o2) {
Double diff = o2.getValue() - o1.getValue();
if (diff == 0)
return o1.getKey().compareTo(o2.getKey());
else
return diff > 0 ? 1 : -1;
}
}
@Test
public void testZRemRangeByScore() {
Double min;
Double max;
for (int j = 0; j < 3; j++) {
do {
min = rand.nextDouble();
max = rand.nextDouble();
} while (min > max);
int numMembers = 10;
String key = randString();
Map<String, Double> scoreMembers = new HashMap<String, Double>();
List<Entry<String, Double>> fullList = new ArrayList<Entry<String, Double>>();
List<Entry<String, Double>> toRemoveList = new ArrayList<Entry<String, Double>>();
for (int i = 0; i < numMembers; i++) {
String s = randString();
Double d = rand.nextDouble();
scoreMembers.put(s, d);
fullList.add(new AbstractMap.SimpleEntry<String, Double>(s, d));
if (d > min && d < max)
toRemoveList.add(new AbstractMap.SimpleEntry<String, Double>(s, d));
}
jedis.zadd(key, scoreMembers);
Long numRemoved = jedis.zremrangeByScore(key, min, max);
List<Entry<String, Double>> expectedList = new ArrayList<Entry<String, Double>>(fullList);
expectedList.removeAll(toRemoveList);
Collections.sort(expectedList, new EntryCmp());
Set<Tuple> result = jedis.zrangeWithScores(key, 0, -1);
List<Entry<String, Double>> resultList = new ArrayList<Entry<String, Double>>();
for (Tuple t : result)
resultList.add(new AbstractMap.SimpleEntry<String, Double>(t.getElement(), t.getScore()));
assertEquals(expectedList, resultList);
jedis.del(key);
}
}
private String randString() {
return Long.toHexString(Double.doubleToLongBits(Math.random()));
}
@After
public void flushAll() {
jedis.flushAll();
}
@AfterClass
public static void tearDown() {
jedis.close();
cache.close();
server.shutdown();
}
}