Package test.r2.integ

Source Code of test.r2.integ.TestHttpClient

/*
   Copyright (c) 2012 LinkedIn Corp.

   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.
*/

/**
* $Id: $
*/

package test.r2.integ;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.testng.Assert;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;

import com.linkedin.common.callback.Callback;
import com.linkedin.common.callback.FutureCallback;
import com.linkedin.common.util.None;
import com.linkedin.data.ByteString;
import com.linkedin.r2.message.RequestContext;
import com.linkedin.r2.message.rest.RestRequest;
import com.linkedin.r2.message.rest.RestRequestBuilder;
import com.linkedin.r2.message.rest.RestResponse;
import com.linkedin.r2.transport.common.Client;
import com.linkedin.r2.transport.common.bridge.client.TransportClient;
import com.linkedin.r2.transport.common.bridge.client.TransportClientAdapter;
import com.linkedin.r2.transport.http.client.HttpClientFactory;
import com.linkedin.r2.transport.http.client.TestServer;

/**
* @author Steven Ihde
* @version $Revision: $
*/

public class TestHttpClient
{
  private HttpClientFactory _clientFactory;
  private TestServer _testServer;

  @BeforeSuite
  private void init() throws Exception
  {
    _testServer = new TestServer();
    _clientFactory = new HttpClientFactory();
  }

  @AfterSuite
  private void cleanup() throws Exception
  {
    final FutureCallback<None> callback = new FutureCallback<None>();
    _clientFactory.shutdown(callback);
    callback.get();

    _testServer.shutdown();
  }

  @Test
  public void testClient() throws Exception
  {
    final TransportClient transportClient = _clientFactory.getClient(new HashMap<String, String>());
    final Client client = new TransportClientAdapter(transportClient);

    RestRequestBuilder rb = new RestRequestBuilder(_testServer.getRequestURI());
    rb.setMethod("GET");
    RestRequest request = rb.build();
    Future<RestResponse> f = client.restRequest(request);

    // This will block
    RestResponse response = f.get();
    final ByteString entity = response.getEntity();
    if (entity != null) {
      System.out.println(entity.asString("UTF-8"));
    } else {
      System.out.println("NOTHING!");
    }

    assertEquals(response.getStatus(), 200);

    final FutureCallback<None> callback = new FutureCallback<None>();
    client.shutdown(callback);
    callback.get();
  }

  @Test
  public void testRequestContextReuse() throws Exception
  {
    final Integer REQUEST_TIMEOUT = 1000;
    final TransportClient transportClient =
        _clientFactory.getClient(Collections.singletonMap(HttpClientFactory.HTTP_REQUEST_TIMEOUT,
                                                          Integer.toString(REQUEST_TIMEOUT)));
    final Client client = new TransportClientAdapter(transportClient);

    RestRequestBuilder rb = new RestRequestBuilder(_testServer.getRequestURI());
    rb.setMethod("GET");
    RestRequest request = rb.build();

    final RequestContext context = new RequestContext();
    Future<RestResponse> f = client.restRequest(request, context);
    Future<RestResponse> f2 = client.restRequest(request, context);

    // This will block
    RestResponse response = f.get(REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);
    assertEquals(response.getStatus(), 200);

    response = f2.get(REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);
    assertEquals(response.getStatus(), 200);

    final Integer iterations = 5;
    final CountDownLatch latch = new CountDownLatch(iterations);
    //Test that sending multiple requests with the same request context works correctly, without
    //modifying the original request context.
    for (int i=0; i<iterations; ++i)
    {
      client.restRequest(request, context, new Callback<RestResponse>()
      {
        @Override
        public void onError(Throwable e)
        {
          Assert.fail("Expected success, received: " + e);
          latch.countDown();
        }

        @Override
        public void onSuccess(RestResponse result)
        {
          Assert.assertEquals(result.getStatus(), 200);
          latch.countDown();
        }
      });
    }
    latch.await(REQUEST_TIMEOUT, TimeUnit.MILLISECONDS);

    Assert.assertTrue(context.getLocalAttrs().isEmpty());

    final FutureCallback<None> callback = new FutureCallback<None>();
    client.shutdown(callback);
    callback.get();
  }

  // Disabled this test for now because due to VMWare/Solaris x86 bugs, ScheduledExecutor
  // does not work correctly on the hudson builds.  Reenable it when we move our Hudson jobs
  // to a correctly functioning operating system.
  @Test(enabled=false)
  public void testFailBackoff() throws Exception
  {
    final int WARM_UP = 10;
    final int N = 5;
    final int REQUEST_TIMEOUT = 1000;

    // Specify the get timeout; we know the max rate will be half the get timeout
    final TransportClient transportClient =
        new HttpClientFactory().getClient(Collections.singletonMap(HttpClientFactory.HTTP_REQUEST_TIMEOUT,
                                                                   Integer.toString(REQUEST_TIMEOUT)));
    final Client client = new TransportClientAdapter(transportClient);

    final ServerSocket ss = new ServerSocket();
    ss.bind(null);
    final CountDownLatch latch = new CountDownLatch(N + WARM_UP);
    Thread t = new Thread(new Runnable()
    {
      @Override
      public void run()
      {
        try
        {
          for (;;)
          {
          Socket s = ss.accept();
          s.close();
          latch.countDown();
          System.err.println("!!! Got a connect, " + latch.getCount() + " to go!");
          }
        }
        catch (IOException e)
        {
          e.printStackTrace();
        }
      }
    });
    t.start();


    RestRequest r = new RestRequestBuilder(URI.create("http://localhost:" + ss.getLocalPort() + "/")).setMethod("GET").build();

    // First ensure a bunch fail to get the rate limiting going
    List<FutureCallback<RestResponse>> callbacks = dispatchRequests(client, r, WARM_UP);
    for (FutureCallback<RestResponse> callback : callbacks)
    {
      try
      {
        callback.get();
      }
      catch (Exception e)
      {
        // ignore
      }
    }

    // Now we should be rate limited


    long start = System.currentTimeMillis();
    System.err.println("Starting at " + start);
    dispatchRequests(client, r, N);
    long lowTolerance = N * REQUEST_TIMEOUT / 2 * 4 / 5;
    long highTolerance = N * REQUEST_TIMEOUT / 2 * 5 / 4;
    Assert.assertTrue(latch.await(highTolerance, TimeUnit.MILLISECONDS), "Should have finished within " + highTolerance + "ms");
    long elapsed = System.currentTimeMillis() - start;
    Assert.assertTrue(elapsed > lowTolerance, "Should have finished after " + lowTolerance + "ms (took " + elapsed +")");
  }

  private List<FutureCallback<RestResponse>> dispatchRequests(Client client, RestRequest r, int n)
  {
    List<FutureCallback<RestResponse>> callbacks = new ArrayList<FutureCallback<RestResponse>>(n);
    for (int i = 0; i < n; i++)
    {
      FutureCallback<RestResponse> callback = new FutureCallback<RestResponse>();
      callbacks.add(callback);
      client.restRequest(r, callback);
    }
    return callbacks;
  }

  @Test
  public void testSimpleURI() throws Exception
  {
    final TransportClient transportClient = _clientFactory.getClient(new HashMap<String, String>());
    final Client client = new TransportClientAdapter(transportClient);

    // Note no trailing slash; the point of the test is to ensure this URI will
    // send a Request-URI of "/".
    URI uri = URI.create("http://localhost:" + _testServer.getPort());
    RestRequestBuilder rb = new RestRequestBuilder(uri);
    rb.setMethod("GET");
    RestRequest request = rb.build();
    Future<RestResponse> f = client.restRequest(request);

    // This will block
    RestResponse response = f.get();

    assertEquals(response.getStatus(), 200);

    String requestString = _testServer.getLastRequest();
    assertTrue(requestString.startsWith("GET / HTTP"), "Request '" + requestString +
            "' should have started with 'GET / HTTP'");

    final FutureCallback<None> callback = new FutureCallback<None>();
    client.shutdown(callback);
    callback.get();
  }
}
TOP

Related Classes of test.r2.integ.TestHttpClient

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.