/*
* Copyright 2013 Couchbase, Inc.
*
* 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.couchbase.mock.client;
import com.couchbase.client.CouchbaseClient;
import com.couchbase.client.CouchbaseConnectionFactory;
import com.couchbase.client.CouchbaseConnectionFactoryBuilder;
import com.couchbase.client.vbucket.VBucketNodeLocator;
import junit.framework.TestCase;
import net.spy.memcached.MemcachedNode;
import org.couchbase.mock.Bucket;
import org.couchbase.mock.Bucket.BucketType;
import org.couchbase.mock.BucketConfiguration;
import org.couchbase.mock.CouchbaseMock;
import org.couchbase.mock.memcached.Item;
import org.couchbase.mock.memcached.KeySpec;
import org.couchbase.mock.memcached.MemcachedServer;
import org.couchbase.mock.memcached.VBucketInfo;
import org.couchbase.mock.memcached.client.MemcachedClient;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Base test case which uses a client.
*
* @author Mark Nunberg <mnunberg@haskalah.org>
*/
public abstract class ClientBaseTest extends TestCase {
protected final BucketConfiguration bucketConfiguration = new BucketConfiguration();
protected MockClient mockClient;
protected CouchbaseMock couchbaseMock;
protected final CouchbaseConnectionFactoryBuilder cfb = new CouchbaseConnectionFactoryBuilder();
protected CouchbaseClient client;
protected CouchbaseConnectionFactory connectionFactory;
public ClientBaseTest() {}
protected MemcachedNode getMasterForKey(String key) {
VBucketNodeLocator locator = (VBucketNodeLocator) client.getNodeLocator();
return locator.getPrimary(key);
}
/**
* Gets a key which is valid for a given server
* @param ix The server for which the key should be valid
* @return The key which may map to the server
*/
protected String getValidKeyFor(int ix) {
Random r = new Random();
Bucket bucket = getBucket();
VBucketInfo[] vbi = bucket.getVBucketInfo();
MemcachedServer server = getServer(ix);
while (true) {
String candidate = "Key_" + Integer.toString(r.nextInt());
short vbid = bucket.getVbIndexForKey(candidate);
if (vbid < 0 || vbid >= vbi.length) {
throw new IllegalArgumentException("Can't use this function on memcached buckets!");
}
if (vbi[vbid].getOwner() == server) {
return candidate;
}
}
}
// Don't make the client flood the screen with log messages..
static public void initJCBCEnv() {
System.setProperty("net.spy.log.LoggerImpl", "net.spy.memcached.compat.log.SunLogger");
System.setProperty("cbclient.disableCarrierBootstrap", "true");
Logger.getLogger("net.spy.memcached").setLevel(Level.WARNING);
Logger.getLogger("com.couchbase.client").setLevel(Level.WARNING);
Logger.getLogger("com.couchbase.client.vbucket").setLevel(Level.WARNING);
}
static {
initJCBCEnv();
}
protected void createMock(@NotNull String name, @NotNull String password) throws Exception {
bucketConfiguration.numNodes = 10;
bucketConfiguration.numReplicas = 3;
bucketConfiguration.name = name;
bucketConfiguration.type = BucketType.COUCHBASE;
bucketConfiguration.password = password;
ArrayList<BucketConfiguration> configList = new ArrayList<BucketConfiguration>();
configList.add(bucketConfiguration);
couchbaseMock = new CouchbaseMock(0, configList);
couchbaseMock.start();
couchbaseMock.waitForStartup();
}
protected void createClients() throws Exception {
mockClient = new MockClient(new InetSocketAddress("localhost", 0));
couchbaseMock.startHarakiriMonitor("localhost:" + mockClient.getPort(), false);
mockClient.negotiate();
List<URI> uriList = new ArrayList<URI>();
uriList.add(new URI("http", null, "localhost", couchbaseMock.getHttpPort(), "/pools", "", ""));
connectionFactory = cfb.buildCouchbaseConnection(uriList, bucketConfiguration.name, bucketConfiguration.password);
client = new CouchbaseClient(connectionFactory);
}
@Override
protected void setUp() throws Exception {
super.setUp();
createMock("default", "");
createClients();
}
@Override
protected void tearDown() throws Exception {
if (client != null) {
client.shutdown();
}
if (couchbaseMock != null) {
couchbaseMock.stop();
}
if (mockClient != null) {
mockClient.shutdown();
}
super.tearDown();
}
protected MemcachedClient getBinClient(int index) throws IOException {
MemcachedServer server = getServer(index);
Socket sock = new Socket();
sock.connect(new InetSocketAddress(server.getHostname(), server.getPort()));
return new MemcachedClient(sock);
}
private Bucket getBucket() {
return couchbaseMock.getBuckets().get(bucketConfiguration.name);
}
protected MemcachedClient getBinClient() throws IOException {
return getBinClient(0);
}
protected MemcachedServer getServer(int index) {
return getBucket().getServers()[index];
}
/**
* Gets a valid vBucket ID for a given server. Used to generate a packet that
* will be accepted by it.
* @param on The index of the server
* @return The vBucket
*/
protected short findValidVbucket(int on) {
Bucket bucket = getBucket();
VBucketInfo[] vbi = bucket.getVBucketInfo();
MemcachedServer target = getServer(on);
for (int i = 0; i < vbi.length; i++) {
VBucketInfo cur = vbi[i];
if (cur.getOwner().equals(target)) {
return (short)i;
}
}
return -1;
}
protected Item getItem(String key, short vbId) {
MemcachedServer server = getBucket().getVBucketInfo()[vbId].getOwner();
return server.getStorage().getCached(new KeySpec(key, vbId));
}
protected void removeItem(String key, short vbId) {
MemcachedServer server = getBucket().getVBucketInfo()[vbId].getOwner();
server.getStorage().removeCached(new KeySpec(key, vbId));
}
protected void storeItem(String key, short vbId, String value) {
MemcachedServer server = getBucket().getVBucketInfo()[vbId].getOwner();
server.getStorage().putCached(new Item(new KeySpec(key, vbId), 0, 0, value.getBytes(), null, 0));
}
}