/* * Copyright (c) 2014-2015 Spotify AB * * 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.spotify.folsom.ketama; import com.google.common.base.Charsets; import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.google.common.net.HostAndPort; import com.spotify.folsom.FakeRawMemcacheClient; import com.spotify.folsom.MemcacheClient; import com.spotify.folsom.RawMemcacheClient; import com.spotify.folsom.client.NoopMetrics; import com.spotify.folsom.client.ascii.DefaultAsciiMemcacheClient; import com.spotify.folsom.client.binary.DefaultBinaryMemcacheClient; import com.spotify.folsom.transcoder.StringTranscoder; import org.junit.Test; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.ExecutionException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; public class KetamaMemcacheClientTest { @Test public void testStitching() throws Exception { for (int i = 0; i < 2; i++) { boolean binary = i == 0; test(4, 100, 20, binary); test(4, 5, 50, binary); test(4, 100, 0, binary); test(4, 100, 1, binary); test(4, 100, 2, binary); test(4, 100, 3, binary); test(4, 100, 4, binary); } } private void test(final int numClients, final int keysFound, final int requestSize, boolean binary) throws InterruptedException, ExecutionException { final Random random = new Random(123717678612L); final ArrayList<AddressAndClient> clients = Lists.newArrayList(); for (int i = 0; i < numClients; i++) { final FakeRawMemcacheClient client = new FakeRawMemcacheClient(); final AddressAndClient aac = new AddressAndClient( HostAndPort.fromString("host" + i + ":11211"), client); clients.add(aac); final MemcacheClient<String> memcacheClient = buildClient(client, binary); for (int j = 0; j < keysFound; j++) { memcacheClient.set("key-" + j, "value-" + j + "-" + i, 1000).get(); } } final KetamaMemcacheClient ketamaMemcacheClient = new KetamaMemcacheClient(clients); final MemcacheClient<String> memcacheClient = buildClient(ketamaMemcacheClient, binary); final List<String> requestedKeys = Lists.newArrayList(); for (int i = 0; i < requestSize; i++) { requestedKeys.add("key-" + random.nextInt(keysFound * 2)); } final List<String> values = memcacheClient.get(requestedKeys).get(); assertEquals(requestSize, values.size()); for (int i = 0; i < requestSize; i++) { final String key = requestedKeys.get(i); final String value = values.get(i); final String keyIndex = Splitter.on('-').splitToList(key).get(1); if (Integer.parseInt(keyIndex) >= keysFound) { assertNull(value); } else { assertNotNull(value); final List<String> parts = Splitter.on('-').splitToList(value); assertEquals(3, parts.size()); assertEquals("value", parts.get(0)); assertEquals(keyIndex, parts.get(1)); } } } private MemcacheClient<String> buildClient(final RawMemcacheClient client, boolean binary) { if (binary) { return new DefaultBinaryMemcacheClient<>(client, new NoopMetrics(), StringTranscoder.UTF8_INSTANCE, Charsets.UTF_8); } else { return new DefaultAsciiMemcacheClient<>(client, new NoopMetrics(), StringTranscoder.UTF8_INSTANCE, Charsets.UTF_8); } } }