Skip to content

Commit

Permalink
JCBC-154: Merge special release 1.1c branch fixes in for release 1.1.
Browse files Browse the repository at this point in the history
* gerrit/release11c:
  JCBC-130: Add a timeout for unresponsive http connection fetches.
  Correcting view tests with wrong exception handling.
  [Backport] Cancel view requests when the operation is cancelled.
  JCBC-100: [Backport] Add better error handling on view fetches.

Conflicts:
	src/main/java/com/couchbase/client/CouchbaseClient.java
	src/test/java/com/couchbase/client/ViewTest.java

Also, had to add a minor change to ViewNodeTest.java to add a view
since the NoDocsOperationImpl had changed.

Change-Id: I9a1ddd2b57c3a2d5e8801414ab72b4d435c7c5cb
  • Loading branch information
ingenthr committed Dec 3, 2012
2 parents 32c1801 + b8eda75 commit 0646755
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 16 deletions.
2 changes: 2 additions & 0 deletions ivy.xml
Expand Up @@ -58,6 +58,8 @@ SOFTWARE.
conf="common->master" />
<dependency org="org.easymock" name="easymockclassextension"
rev="${easymock-extension.version}" conf="common->master" />
<dependency org="org.mockito" name="mockito-all" rev="${mockito.version}"
conf="common->master" />
<dependency org="cglib" name="cglib" rev="${cglib.version}"
conf="common->master" />
<dependency org="asm" name="asm" rev="${asm.version}"
Expand Down
1 change: 1 addition & 0 deletions ivy/couchbase-client-test.xml
Expand Up @@ -54,5 +54,6 @@
<dependency org="org.easymock" name="easymockclassextension" rev="${easymock-entension.version}" conf="default" />
<dependency org="junit-addons" name="junit-addons" rev="${junit-addons.version}" conf="default" />
<dependency org="spy" name="spymemcached-test" rev="${spymemcached-test.version}" conf="default" />
<dependency org="org.mockito" name="mockito-all" rev="${mockito.version}" conf="default" />
</dependencies>
</ivy-module>
1 change: 1 addition & 0 deletions ivy/libraries.properties
Expand Up @@ -30,6 +30,7 @@ cglib.version=2.2.2
commons-codec.version=1.5
easymock.version=2.4
easymock-extension.version=2.4
mockito.version=1.9.5
httpcore.version=4.1.1
httpcore-nio.version=4.1.1
jettison.version=1.1
Expand Down
Expand Up @@ -71,7 +71,8 @@ public void waitFor() throws InterruptedException {
}
synchronized (this) {
while (!this.completed) {
wait();
wait(30000);
this.completed = true;
}
}
}
Expand Down
153 changes: 153 additions & 0 deletions src/test/java/com/couchbase/client/ViewNodeTest.java
@@ -0,0 +1,153 @@
/**
* Copyright (C) 2009-2012 Couchbase, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALING
* IN THE SOFTWARE.
*/

package com.couchbase.client;

import com.couchbase.client.http.AsyncConnectionManager;
import com.couchbase.client.http.RequeueOpCallback;
import com.couchbase.client.internal.HttpFuture;
import com.couchbase.client.protocol.views.HttpOperation;
import com.couchbase.client.protocol.views.NoDocsOperationImpl;
import com.couchbase.client.protocol.views.View;
import com.couchbase.client.protocol.views.ViewOperation;
import com.couchbase.client.protocol.views.ViewResponse;
import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;
import net.spy.memcached.TestConfig;
import net.spy.memcached.ops.OperationStatus;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpVersion;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.nio.protocol.AsyncNHttpClientHandler;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.nio.util.DirectByteBufferAllocator;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.SyncBasicHttpParams;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.ImmutableHttpProcessor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
import static org.junit.Assert.assertFalse;
import org.junit.Test;
import static org.mockito.Mockito.mock;

/**
* Tests the ViewNodes for their correct behavior.
*/
public class ViewNodeTest {

@Test
public void testUnresponsiveViewNode() throws IOReactorException {
AsyncConnectionManager mgr = createConMgr(TestConfig.IPV4_ADDR, 8091);
InetSocketAddress addr = new InetSocketAddress(TestConfig.IPV4_ADDR, 8091);
ViewNode viewNode = new ViewNode(addr, mgr, 0, 0, 0, "", "");

assertFalse("View node has write ops.", viewNode.hasWriteOps());

HttpOperation operation = createHttpOperation();
viewNode.writeOp(operation);
}


private HttpOperation createHttpOperation() {
View view = new View("a", "b", "c", true, true);
final CountDownLatch couchLatch = new CountDownLatch(1);
final HttpFuture<ViewResponse> crv =
new HttpFuture<ViewResponse>(couchLatch, 60000);
final HttpRequest request = new BasicHttpRequest("GET", "/pools", HttpVersion.HTTP_1_1);
return new NoDocsOperationImpl(
request,
view,
new ViewOperation.ViewCallback() {
private ViewResponse vr = null;

@Override
public void receivedStatus(OperationStatus status) {
crv.set(vr, status);
}

@Override
public void complete() {
couchLatch.countDown();
}

@Override
public void gotData(ViewResponse response) {
vr = response;
}
}
);
}


private AsyncConnectionManager createConMgr(String host, int port) throws IOReactorException {
HttpHost target = new HttpHost(host, port);
int maxConnections = 1;

HttpParams params = new SyncBasicHttpParams();
params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000)
.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
.setParameter(CoreProtocolPNames.USER_AGENT, "Couchbase Java Client 1.1");

HttpProcessor httpproc = new ImmutableHttpProcessor(
new HttpRequestInterceptor[] {
new RequestContent(),
new RequestTargetHost(),
new RequestConnControl(),
new RequestUserAgent(),
new RequestExpectContinue(),
}
);


AsyncNHttpClientHandler protocolHandler = new AsyncNHttpClientHandler(
httpproc,
new ViewNode.MyHttpRequestExecutionHandler(),
new DefaultConnectionReuseStrategy(),
new DirectByteBufferAllocator(), params
);

protocolHandler.setEventListener(new ViewNode.EventLogger());
RequeueOpCallback callback = mock(RequeueOpCallback.class);
AsyncConnectionManager manager = new AsyncConnectionManager(
target,
maxConnections,
protocolHandler,
params,
callback
);

return manager;
}

}
42 changes: 27 additions & 15 deletions src/test/java/com/couchbase/client/ViewTest.java
Expand Up @@ -74,7 +74,9 @@
import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

/**
* A CouchbaseClientTest.
Expand All @@ -96,6 +98,9 @@ public class ViewTest {
public static final String VIEW_NAME_OBSERVE = "view_staletest";
public static final String VIEW_NAME_BINARY = "view_binary";

@Rule
public ExpectedException exception = ExpectedException.none();

static {
ITEMS = new HashMap<String, Object>();
int d = 0;
Expand Down Expand Up @@ -639,21 +644,6 @@ public void gotData(ViewResponse response) {
op.handleResponse(response);
}

@Test(expected = InvalidViewException.class)
public void testInvalidViewHandling() {
String designDoc = "invalid_design";
String viewName = "invalid_view";
View view = client.getView(designDoc, viewName);
assertNull(view);
}

@Test(expected = InvalidViewException.class)
public void testInvalidDesignDocHandling() {
String designDoc = "invalid_design";
List<View> views = client.getViews(designDoc);
assertNull(views);
}

/**
* This test case acts as an integration test to verify that adding
* data with the given integrity constraints in combination with the
Expand Down Expand Up @@ -830,5 +820,27 @@ public void testDesignDocumentDeletion() throws InterruptedException {
}
assertTrue(success);
}

public void testInvalidViewHandling() {
String designDoc = "invalid_design";
String viewName = "invalid_view";

exception.expect(InvalidViewException.class);
exception.expectMessage("Could not load view \""
+ viewName + "\" for design doc \"" + designDoc + "\"");
View view = client.getView(designDoc, viewName);
assertNull(view);
}

@Test
public void testInvalidDesignDocHandling() {
String designDoc = "invalid_design";

exception.expect(InvalidViewException.class);
exception.expectMessage("Could not load views for design doc \""
+ designDoc + "\"");
List<View> views = client.getViews(designDoc);
assertNull(views);
}

}

0 comments on commit 0646755

Please sign in to comment.