package glaze; import static glaze.Glaze.Get; import static glaze.Glaze.Post; import static glaze.test.http.Condition.when; import static glaze.test.http.Expressions.any; import static org.apache.http.entity.ContentType.APPLICATION_JSON; import glaze.Glaze; import glaze.client.Response; import glaze.client.async.AsyncClient; import glaze.client.async.DefaultAsyncClient; import glaze.spi.Registry; import glaze.test.data.Card; import glaze.test.data.Member; import glaze.test.http.BaseHttpTest; import glaze.test.http.Condition; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; import org.apache.http.HttpException; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.concurrent.FutureCallback; import org.apache.http.entity.ContentType; import org.apache.http.nio.IOControl; import org.apache.http.nio.client.methods.AsyncByteConsumer; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.testng.Assert; import org.testng.annotations.Test; public class TestAsync extends BaseHttpTest { private class CounterCallback<T> implements FutureCallback<T> { final AtomicInteger counter; public CounterCallback() { counter = new AtomicInteger(); } @Override public void cancelled() { // } @Override public void completed(T response) { counter.incrementAndGet(); } @Override public void failed(Exception arg0) { // } } @Test(timeOut = 5000) public void postJson() throws InterruptedException, ExecutionException { server.expect(Condition.when("POST").path("/scott").respond("{\"id\":\"scott\"}", ContentType.APPLICATION_JSON)); server.expect(Condition.when("POST").path("/tiger").respond("{\"id\":\"tiger\"}", ContentType.APPLICATION_JSON)); Card in = new Card("Hello", "world", "0989080"); try { Future<Member> scott = Post(baseUrl + "/scott").bean(in).as(APPLICATION_JSON).mapAsync(Member.class); Future<Member> tiger = Post(baseUrl + "/tiger", APPLICATION_JSON).bean(in).mapAsync(Member.class, new BasicHttpContext()); Assert.assertEquals(scott.get().id, "scott"); Assert.assertEquals(tiger.get().id, "tiger"); } finally { Registry.lookup(AsyncClient.class).reset(); } } @Test(timeOut = 5000) public void postJsonCallback() throws InterruptedException, ExecutionException { server.expect(Condition.when("POST").path("/scott").respond("{\"id\":\"scott\"}", ContentType.APPLICATION_JSON)); server.expect(Condition.when("POST").path("/tiger").respond("{\"id\":\"tiger\"}", ContentType.APPLICATION_JSON)); Card in = new Card("Hello", "world", "0989080"); AsyncClient client = new DefaultAsyncClient(); try { CounterCallback<Member> callback = new CounterCallback<Member>(); Future<Member> scott = Post(baseUrl + "/scott").bean(in).as(APPLICATION_JSON).mapAsync(client, Member.class, callback); Future<Member> tiger = Post(baseUrl + "/tiger", APPLICATION_JSON).bean(in).mapAsync(client, Member.class, new BasicHttpContext(), callback); Assert.assertEquals(scott.get().id, "scott"); Assert.assertEquals(tiger.get().id, "tiger"); Assert.assertEquals(callback.counter.get(), 2); } finally { client.shutdown(); } } @Test(timeOut = 5000) public void send() throws InterruptedException, ExecutionException { server.expect(when(any()).path("/areq").respond("OK")); AsyncClient client = new DefaultAsyncClient(); try { List<Future<Response>> futures = new ArrayList<Future<Response>>(); futures.add(Glaze.Post(baseUrl + "/areq").bean("hello").as(ContentType.DEFAULT_TEXT).sendAsync(client)); futures.add(Glaze.Get(baseUrl + "/areq").sendAsync(client, new BasicHttpContext())); futures.add(Glaze.Put(baseUrl + "/areq").bean("hello").as(ContentType.DEFAULT_TEXT).sendAsync(client, new BasicHttpContext())); futures.add(Glaze.Head(baseUrl + "/areq").sendAsync(client)); futures.add(Glaze.Delete(baseUrl + "/areq").sendAsync(client)); for (Future<Response> resp : futures) { Assert.assertEquals(resp.get().status(), HttpStatus.SC_OK); } } finally { client.shutdown(); } } @Test(timeOut = 5000) public void sendCallback() throws InterruptedException, ExecutionException { server.expect(when(any()).path("/areq").respond("OK")); AsyncClient client = new DefaultAsyncClient(); try { List<Future<Response>> futures = new ArrayList<Future<Response>>(); CounterCallback<Response> callback = new CounterCallback<Response>(); futures.add(Glaze.Put(baseUrl + "/areq").bean("hello").as(ContentType.DEFAULT_TEXT).sendAsync(client, new BasicHttpContext(), callback)); futures.add(Glaze.Head(baseUrl + "/areq").sendAsync(client, new BasicHttpContext(), callback)); futures.add(Glaze.Delete(baseUrl + "/areq").sendAsync(client, callback)); for (Future<Response> resp : futures) { Assert.assertEquals(resp.get().status(), HttpStatus.SC_OK); } Assert.assertEquals(callback.counter.get(), 3); } finally { client.shutdown(); } } @Test(timeOut = 5000) public void stream() throws InterruptedException, ExecutionException { server.expect(Condition.when("GET").path("/stream").respond("Michael bytes", ContentType.APPLICATION_JSON)); try { Future<String> ok = Get(baseUrl + "/stream").withConsumer(new AsyncByteConsumer<String>() { private String ok; @Override protected String buildResult(HttpContext ctx) throws Exception { return ok; } @Override protected void onByteReceived(ByteBuffer bytes, IOControl control) throws IOException { ok = ""; byte[] bb = bytes.array(); for (byte b : bb) { if (b > 0) ok += (char) b; } } @Override protected void onResponseReceived(HttpResponse response) throws HttpException, IOException { // } }).executeAsync(); Assert.assertEquals(ok.get(), "Michael bytes"); } finally { Registry.lookup(AsyncClient.class).reset(); } } }