package org.infinispan.it.compatibility;
import static org.testng.AssertJUnit.assertEquals;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.charset.Charset;
import java.util.Arrays;
import org.infinispan.client.hotrod.Flag;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.commons.marshall.StringMarshaller;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.test.AbstractInfinispanTest;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* Tests compatibility of Memcached, using a different client to SpyMemcached,
* and Hot Rod.
*
* @author Galder ZamarreƱo
* @since 5.3
*/
@Test(groups = "functional", testName = "it.compatibility.CustomMemcachedHotRodTest")
public class CustomMemcachedHotRodTest extends AbstractInfinispanTest {
final static String CACHE_NAME = "memcachedCache";
CompatibilityCacheFactory<String, String> cacheFactory;
@BeforeClass
protected void setup() throws Exception {
cacheFactory = new CompatibilityCacheFactory<String, String>(
CACHE_NAME, new StringMarshaller(Charset.forName("UTF-8")), CacheMode.LOCAL).setup();
}
@AfterClass
protected void teardown() {
CompatibilityCacheFactory.killCacheFactories(cacheFactory);
}
public void testHotRodPutMemcachedGet() throws IOException {
final String key = "1";
// 1. Put with Hot Rod
RemoteCache<String, String> remote = cacheFactory.getHotRodCache();
assertEquals(null, remote.withFlags(Flag.FORCE_RETURN_VALUE).put(key, "v1"));
// 2. Read with Memcached
MemcachedClient memcached =
new MemcachedClient("localhost", cacheFactory.getMemcachedPort());
try {
assertEquals("v1".getBytes(), memcached.getBytes(key));
} finally {
memcached.close();
}
}
public void testMemcachedPutGet() throws IOException {
final String key = "1";
MemcachedClient memcached =
new MemcachedClient("localhost", cacheFactory.getMemcachedPort());
try {
memcached.set(key, "v1");
assertEquals("v1", memcached.get(key));
} finally {
memcached.close();
}
}
/**
* Alternative Memcached client to SpyMemcached.
*
* @author Martin Gencur
*/
static class MemcachedClient {
private static final int DEFAULT_TIMEOUT = 10000;
private static final String DEFAULT_ENCODING = "UTF-8";
private String encoding;
private Socket socket;
private PrintWriter out;
private InputStream input;
public MemcachedClient(String host, int port) throws IOException {
this(DEFAULT_ENCODING, host, port, DEFAULT_TIMEOUT);
}
public MemcachedClient(String enc, String host, int port, int timeout) throws IOException {
encoding = enc;
socket = new Socket(host, port);
socket.setSoTimeout(timeout);
out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), encoding));
input = socket.getInputStream();
}
public String get(String key) throws IOException {
byte[] data = getBytes(key);
return (data == null) ? null : new String(data, encoding);
}
public byte[] getBytes(String key) throws IOException {
writeln("get " + key);
flush();
String valueStr = readln();
if (valueStr.startsWith("VALUE")) {
String[] value = valueStr.split(" ");
assertEquals(key, value[1]);
int size = new Integer(value[3]);
byte[] ret = read(size);
assertEquals('\r', read());
assertEquals('\n', read());
assertEquals("END", readln());
return ret;
} else {
return null;
}
}
public void set(String key, String value) throws IOException {
writeln("set " + key + " 0 0 " + value.getBytes(encoding).length);
writeln(value);
flush();
assertEquals("STORED", readln());
}
private byte[] read(int len) throws IOException {
try {
byte[] ret = new byte[len];
input.read(ret, 0, len);
return ret;
} catch (SocketTimeoutException ste) {
return null;
}
}
private byte read() throws IOException {
try {
return (byte) input.read();
} catch (SocketTimeoutException ste) {
return -1;
}
}
private String readln() throws IOException {
byte[] buf = new byte[512];
int maxlen = 512;
int read = 0;
buf[read] = read();
while (buf[read] != '\n') {
read++;
if (read == maxlen) {
maxlen += 512;
buf = Arrays.copyOf(buf, maxlen);
}
buf[read] = read();
}
if (read == 0) {
return "";
}
if (buf[read - 1] == '\r') {
read--;
}
buf = Arrays.copyOf(buf, read);
return new String(buf, encoding);
}
private void writeln(String str) {
out.print(str + "\r\n");
}
private void flush() {
out.flush();
}
public void close() throws IOException {
socket.close();
}
}
}