package org.handwerkszeug.riak.mapreduce; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.and; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.between; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.endsWith; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.equal; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.filters; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.floatToString; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.greaterThan; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.greaterThanEq; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.intToString; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.lessThan; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.lessThanEq; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.matches; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.not; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.notEqual; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.or; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.setMember; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.similarTo; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.startsWith; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.stringToFloat; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.stringToInt; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.toLower; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.toUpper; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.tokenize; import static org.handwerkszeug.riak.mapreduce.MapReduceQuerySupport.urldecode; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.node.ArrayNode; import org.handwerkszeug.riak.Hosts; import org.handwerkszeug.riak._; import org.handwerkszeug.riak.model.DefaultRiakObject; import org.handwerkszeug.riak.model.JavaScript; import org.handwerkszeug.riak.model.KeyResponse; import org.handwerkszeug.riak.model.Location; import org.handwerkszeug.riak.model.RiakContentsResponse; import org.handwerkszeug.riak.model.RiakFuture; import org.handwerkszeug.riak.op.TestingHandler; import org.handwerkszeug.riak.transport.protobuf.ProtoBufRiakConfig; import org.handwerkszeug.riak.transport.protobuf.ProtoBufRiakOperations; import org.handwerkszeug.riak.transport.protobuf.internal.ProtoBufPipelineFactory; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * @author taichi */ public class MapReduceQuerySupportTest { static final String TEST_BUCKET = "MapReduceQuerySupportTest"; ClientBootstrap bootstrap; Channel channel; static final ProtoBufRiakConfig config = ProtoBufRiakConfig.newConfig( Hosts.RIAK_HOST, Hosts.RIAK_PB_PORT); ProtoBufRiakOperations target; @Before public void setUp() throws Exception { this.bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); this.bootstrap.setPipelineFactory(new ProtoBufPipelineFactory()); ChannelFuture future = this.bootstrap.connect(config.getRiakAddress()); this.channel = future.awaitUninterruptibly().getChannel(); this.target = new ProtoBufRiakOperations(this.channel); deleteFromBucket(); } @After public void tearDown() throws Exception { deleteFromBucket(); this.channel.close().awaitUninterruptibly(); this.bootstrap.releaseExternalResources(); } void waitFor(RiakFuture rf) throws Exception { assertTrue("timeout.", rf.await(5, TimeUnit.SECONDS)); } void deleteFromBucket() throws Exception { final List<String> keys = new ArrayList<String>(); RiakFuture rf = this.target.listKeys(TEST_BUCKET, new TestingHandler<KeyResponse>() { @Override public void handle( RiakContentsResponse<KeyResponse> response) throws Exception { KeyResponse kr = response.getContents(); keys.addAll(kr.getKeys()); } }); waitFor(rf); for (String s : keys) { delete(s); } } void put(String key) throws Exception { Location location = new Location(TEST_BUCKET, key); DefaultRiakObject ro = new DefaultRiakObject(location); String s = key + " [" + new Date() + "]"; ro.setContent(s.getBytes()); ro.setContentEncoding("UTF-8"); System.out.println("**** " + ro); RiakFuture rf = this.target.put(ro, new TestingHandler<_>() { @Override public void handle(RiakContentsResponse<_> response) throws Exception { assertTrue(true); } }); waitFor(rf); } void delete(String key) throws Exception { RiakFuture rf = this.target.delete(new Location(TEST_BUCKET, key), new TestingHandler<_>() { @Override public void handle(RiakContentsResponse<_> response) throws Exception { assertTrue(true); } }); waitFor(rf); } void assertFilters(int expectedCount, MapReduceKeyFilter primary, final MapReduceKeyFilter... keyFilters) throws Exception { final List<String> list = new ArrayList<String>(); MapReduceQueryBuilder<RiakFuture> builder = this.target .mapReduce(new TestingHandler<MapReduceResponse>() { @Override public void handle( RiakContentsResponse<MapReduceResponse> response) throws Exception { MapReduceResponse mrr = response.getContents(); if (mrr.getDone() == false) { ArrayNode an = mrr.getResponse(); System.out.println(an); for (JsonNode jn : an) { list.add(jn.getTextValue()); } } } }); RiakFuture rf = builder.inputs(TEST_BUCKET) .keyFilters(primary, keyFilters).map(JavaScript.mapValues) .execute(); waitFor(rf); System.out.println(list); assertEquals(expectedCount, list.size()); } @Test public void testTransformInt() throws Exception { for (int i = 0; i < 5; i++) { put(String.valueOf(i)); } assertFilters(3, stringToInt, intToString, stringToInt, greaterThan(1)); assertFilters(3, stringToInt, greaterThan(1L)); assertFilters(3, stringToInt, greaterThan(BigInteger.valueOf(1L))); assertFilters(3, stringToInt, lessThan(3)); assertFilters(3, stringToInt, lessThan(3L)); assertFilters(3, stringToInt, lessThan(BigInteger.valueOf(3L))); assertFilters(3, stringToInt, greaterThanEq(2)); assertFilters(3, stringToInt, greaterThanEq(2L)); assertFilters(3, stringToInt, greaterThanEq(BigInteger.valueOf(2L))); assertFilters(3, stringToInt, lessThanEq(2)); assertFilters(3, stringToInt, lessThanEq(2L)); assertFilters(3, stringToInt, lessThanEq(BigInteger.valueOf(2L))); assertFilters(4, stringToInt, notEqual(3)); assertFilters(4, stringToInt, notEqual(3L)); assertFilters(4, stringToInt, notEqual(BigInteger.valueOf(3L))); assertFilters(1, stringToInt, equal(2)); assertFilters(1, stringToInt, equal(2L)); assertFilters(1, stringToInt, equal(BigInteger.valueOf(2L))); assertFilters(3, stringToInt, between(1, 3)); assertFilters(1, stringToInt, between(1, 3, false)); assertFilters(3, stringToInt, between(1L, 3L)); assertFilters(1, stringToInt, between(1L, 3L, false)); assertFilters(3, stringToInt, between(BigInteger.valueOf(1L), BigInteger.valueOf(3L))); assertFilters(1, stringToInt, between(BigInteger.valueOf(1L), BigInteger.valueOf(3L), false)); assertFilters(3, stringToInt, setMember(1, 2, 3)); assertFilters(2, stringToInt, setMember(0L, 4L)); assertFilters(2, stringToInt, setMember(BigInteger.valueOf(0L), BigInteger.valueOf(4L))); } @Test public void testTransformFloat() throws Exception { for (int i = 0; i < 5; i++) { put(Float.toString(i)); } assertFilters(3, stringToFloat, floatToString, stringToFloat, greaterThan(1.0f)); assertFilters(3, stringToFloat, greaterThan(1.0)); assertFilters(3, stringToFloat, greaterThan(BigDecimal.valueOf(1.0))); assertFilters(3, stringToFloat, lessThan(3.0)); assertFilters(3, stringToFloat, lessThan(3.0f)); assertFilters(3, stringToFloat, lessThan(BigDecimal.valueOf(3.0))); assertFilters(3, stringToFloat, greaterThanEq(2.0)); assertFilters(3, stringToFloat, greaterThanEq(2.0f)); assertFilters(3, stringToFloat, greaterThanEq(BigDecimal.valueOf(2.0f))); assertFilters(3, stringToFloat, lessThanEq(2.0)); assertFilters(3, stringToFloat, lessThanEq(2.0f)); assertFilters(3, stringToFloat, lessThanEq(BigDecimal.valueOf(2.0f))); assertFilters(4, stringToFloat, notEqual(3.0)); assertFilters(4, stringToFloat, notEqual(3.0f)); assertFilters(4, stringToFloat, notEqual(BigDecimal.valueOf(3.0f))); assertFilters(1, stringToFloat, equal(2.0)); assertFilters(1, stringToFloat, equal(2.0f)); assertFilters(1, stringToFloat, equal(BigDecimal.valueOf(2.0f))); assertFilters(3, stringToFloat, between(1.0, 3.0)); assertFilters(1, stringToFloat, between(1.0, 3.0, false)); assertFilters(3, stringToFloat, between(1.0f, 3.0f)); assertFilters(1, stringToFloat, between(1.0f, 3.0f, false)); assertFilters(3, stringToFloat, between(BigDecimal.valueOf(1.0f), BigDecimal.valueOf(3.0f))); assertFilters( 1, stringToFloat, between(BigDecimal.valueOf(1.0f), BigDecimal.valueOf(3.0f), false)); assertFilters(2, stringToFloat, setMember(1.0f, 3.0f)); assertFilters(3, stringToFloat, setMember(1.0, 3.0, 4.0)); assertFilters( 3, stringToFloat, setMember(BigDecimal.valueOf(1.0), BigDecimal.valueOf(3.0), BigDecimal.valueOf(4.0))); } @Test public void testTransformString() throws Exception { String[] ary = { "a,0", "b,1", "c,2", "d,3", "e,4" }; for (String s : ary) { put(s); } assertFilters(3, tokenize(",", 2), stringToInt, greaterThanEq(2)); assertFilters(3, toLower, toUpper, tokenize(",", 1), greaterThan("B")); } @Test public void testStringSimilarity() throws Exception { String[] ary = { "1a2", "1b3", "2c4", "2d4", "3e5" }; for (String s : ary) { put(s); } assertFilters(3, greaterThan("2c")); assertFilters(2, lessThan("2c")); assertFilters(2, greaterThanEq("2d4")); assertFilters(2, lessThanEq("1b3")); assertFilters(4, notEqual("1b3")); assertFilters(1, equal("1b3")); assertFilters(4, between("1b3", "3e5")); assertFilters(2, between("1b3", "3e5", false)); assertFilters(1, startsWith("1a")); assertFilters(2, endsWith("4")); assertFilters(2, similarTo("2a4", 1)); assertFilters(3, setMember("1a2", "2c4", "3e5")); assertFilters(4, matches("[12][a-z]\\d+")); } @Test public void testUrlDecode() throws Exception { String[] ary = { "1%2F2", "1%2F3", "2%2F4", "3%2F4", "3%2F5" }; for (String s : ary) { put(s); } assertFilters(2, urldecode, tokenize("/", 1), stringToInt, greaterThan(2)); } @Test public void testLogicalFilters() throws Exception { for (int i = 0; i < 5; i++) { put(String.valueOf(i)); } assertFilters( 3, and(filters(stringToInt, greaterThan(0)), filters(lessThan("4")))); assertFilters(2, or(filters(stringToInt, equal(1L)), filters(equal("2")))); assertFilters( 3, and(filters(stringToInt, lessThan(4)), filters(not(filters(equal("2")))))); } }