Package feign

Source Code of feign.LoggerTest$DontRetryModule

/*
* Copyright 2013 Netflix, 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 feign;

import com.google.common.base.Joiner;
import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.MockWebServer;
import dagger.Provides;
import feign.codec.Decoder;
import feign.codec.Encoder;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import javax.inject.Named;
import javax.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

import static feign.Util.UTF_8;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

@Test
public class LoggerTest {

  Logger logger = new Logger() {
    @Override protected void log(String configKey, String format, Object... args) {
      messages.add(methodTag(configKey) + String.format(format, args));
    }
  };

  List<String> messages = new ArrayList<String>();

  @BeforeMethod void clear() {
    messages.clear();
  }

  interface SendsStuff {

    @RequestLine("POST /")
    @Headers("Content-Type: application/json")
    @Body("%7B\"customer_name\": \"{customer_name}\", \"user_name\": \"{user_name}\", \"password\": \"{password}\"%7D")
    String login(
        @Named("customer_name") String customer,
        @Named("user_name") String user, @Named("password") String password);
  }

  @DataProvider(name = "levelToOutput")
  public Object[][] levelToOutput() {
    Object[][] data = new Object[4][2];
    data[0][0] = Logger.Level.NONE;
    data[0][1] = Arrays.<String>asList();
    data[1][0] = Logger.Level.BASIC;
    data[1][1] = Arrays.asList(
        "\\[SendsStuff#login\\] ---> POST http://localhost:[0-9]+/ HTTP/1.1",
        "\\[SendsStuff#login\\] <--- HTTP/1.1 200 OK \\([0-9]+ms\\)"
    );
    data[2][0] = Logger.Level.HEADERS;
    data[2][1] = Arrays.asList(
        "\\[SendsStuff#login\\] ---> POST http://localhost:[0-9]+/ HTTP/1.1",
        "\\[SendsStuff#login\\] Content-Type: application/json",
        "\\[SendsStuff#login\\] Content-Length: 80",
        "\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
        "\\[SendsStuff#login\\] <--- HTTP/1.1 200 OK \\([0-9]+ms\\)",
        "\\[SendsStuff#login\\] Content-Length: 3",
        "\\[SendsStuff#login\\] <--- END HTTP \\(3-byte body\\)"
    );
    data[3][0] = Logger.Level.FULL;
    data[3][1] = Arrays.asList(
        "\\[SendsStuff#login\\] ---> POST http://localhost:[0-9]+/ HTTP/1.1",
        "\\[SendsStuff#login\\] Content-Type: application/json",
        "\\[SendsStuff#login\\] Content-Length: 80",
        "\\[SendsStuff#login\\] ",
        "\\[SendsStuff#login\\] \\{\"customer_name\": \"netflix\", \"user_name\": \"denominator\", \"password\": \"password\"\\}",
        "\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
        "\\[SendsStuff#login\\] <--- HTTP/1.1 200 OK \\([0-9]+ms\\)",
        "\\[SendsStuff#login\\] Content-Length: 3",
        "\\[SendsStuff#login\\] ",
        "\\[SendsStuff#login\\] foo",
        "\\[SendsStuff#login\\] <--- END HTTP \\(3-byte body\\)"
    );
    return data;
  }

  @Test(dataProvider = "levelToOutput")
  public void levelEmits(final Logger.Level logLevel, List<String> expectedMessages) throws IOException, InterruptedException {
    final MockWebServer server = new MockWebServer();
    server.enqueue(new MockResponse().setBody("foo"));
    server.play();

    try {
      SendsStuff api = Feign.create(SendsStuff.class, "http://localhost:" + server.getUrl("").getPort(),
          new DefaultModule(logger, logLevel));

      api.login("netflix", "denominator", "password");

      assertEquals(messages.size(), expectedMessages.size());
      for (int i = 0; i < messages.size(); i++) {
        assertTrue(messages.get(i).matches(expectedMessages.get(i)), messages.get(i));
      }

      assertEquals(new String(server.takeRequest().getBody(), UTF_8),
          "{\"customer_name\": \"netflix\", \"user_name\": \"denominator\", \"password\": \"password\"}");
    } finally {
      server.shutdown();
    }
  }

  static @dagger.Module(injects = Feign.class, overrides = true, addsTo = Feign.Defaults.class) class DefaultModule {
    final Logger logger;
    final Logger.Level logLevel;

    DefaultModule(Logger logger, Logger.Level logLevel) {
      this.logger = logger;
      this.logLevel = logLevel;
    }

    @Provides Decoder defaultDecoder() {
      return new Decoder.Default();
    }

    @Provides Encoder defaultEncoder() {
      return new Encoder.Default();
    }

    @Provides @Singleton Logger logger() {
      return logger;
    }

    @Provides @Singleton Logger.Level level() {
      return logLevel;
    }
  }

  @DataProvider(name = "levelToReadTimeoutOutput")
  public Object[][] levelToReadTimeoutOutput() {
    Object[][] data = new Object[4][2];
    data[0][0] = Logger.Level.NONE;
    data[0][1] = Arrays.<String>asList();
    data[1][0] = Logger.Level.BASIC;
    data[1][1] = Arrays.asList(
        "\\[SendsStuff#login\\] ---> POST http://localhost:[0-9]+/ HTTP/1.1",
        "\\[SendsStuff#login\\] <--- HTTP/1.1 200 OK \\([0-9]+ms\\)",
        "\\[SendsStuff#login\\] <--- ERROR SocketTimeoutException: Read timed out \\([0-9]+ms\\)"
    );
    data[2][0] = Logger.Level.HEADERS;
    data[2][1] = Arrays.asList(
        "\\[SendsStuff#login\\] ---> POST http://localhost:[0-9]+/ HTTP/1.1",
        "\\[SendsStuff#login\\] Content-Type: application/json",
        "\\[SendsStuff#login\\] Content-Length: 80",
        "\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
        "\\[SendsStuff#login\\] <--- HTTP/1.1 200 OK \\([0-9]+ms\\)",
        "\\[SendsStuff#login\\] Content-Length: 3",
        "\\[SendsStuff#login\\] <--- ERROR SocketTimeoutException: Read timed out \\([0-9]+ms\\)"
    );
    data[3][0] = Logger.Level.FULL;
    data[3][1] = Arrays.asList(
        "\\[SendsStuff#login\\] ---> POST http://localhost:[0-9]+/ HTTP/1.1",
        "\\[SendsStuff#login\\] Content-Type: application/json",
        "\\[SendsStuff#login\\] Content-Length: 80",
        "\\[SendsStuff#login\\] ",
        "\\[SendsStuff#login\\] \\{\"customer_name\": \"netflix\", \"user_name\": \"denominator\", \"password\": \"password\"\\}",
        "\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
        "\\[SendsStuff#login\\] <--- HTTP/1.1 200 OK \\([0-9]+ms\\)",
        "\\[SendsStuff#login\\] Content-Length: 3",
        "\\[SendsStuff#login\\] ",
        "\\[SendsStuff#login\\] <--- ERROR SocketTimeoutException: Read timed out \\([0-9]+ms\\)",
        "\\[SendsStuff#login\\] java.net.SocketTimeoutException: Read timed out.*",
        "\\[SendsStuff#login\\] <--- END ERROR"
    );
    return data;
  }

  @dagger.Module(overrides = true, library = true)
  static class LessReadTimeoutModule {
    @Provides Request.Options lessReadTimeout() {
      return new Request.Options(10 * 1000, 50);
    }
  }

  @Test(dataProvider = "levelToReadTimeoutOutput")
  public void readTimeoutEmits(final Logger.Level logLevel, List<String> expectedMessages) throws IOException, InterruptedException {
    final MockWebServer server = new MockWebServer();
    server.enqueue(new MockResponse().setBytesPerSecond(1).setBody("foo"));
    server.play();


    try {
      SendsStuff api = Feign.create(SendsStuff.class, "http://localhost:" + server.getUrl("").getPort(),
          new LessReadTimeoutModule(), new DefaultModule(logger, logLevel));

      api.login("netflix", "denominator", "password");

      fail();
    } catch (FeignException e) {

      assertMessagesMatch(expectedMessages);

      assertEquals(new String(server.takeRequest().getBody(), UTF_8),
          "{\"customer_name\": \"netflix\", \"user_name\": \"denominator\", \"password\": \"password\"}");
    } finally {
      server.shutdown();
    }
  }

  @DataProvider(name = "levelToUnknownHostOutput")
  public Object[][] levelToUnknownHostOutput() {
    Object[][] data = new Object[4][2];
    data[0][0] = Logger.Level.NONE;
    data[0][1] = Arrays.<String>asList();
    data[1][0] = Logger.Level.BASIC;
    data[1][1] = Arrays.asList(
        "\\[SendsStuff#login\\] ---> POST http://robofu.abc/ HTTP/1.1",
        "\\[SendsStuff#login\\] <--- ERROR UnknownHostException: robofu.abc \\([0-9]+ms\\)"
    );
    data[2][0] = Logger.Level.HEADERS;
    data[2][1] = Arrays.asList(
        "\\[SendsStuff#login\\] ---> POST http://robofu.abc/ HTTP/1.1",
        "\\[SendsStuff#login\\] Content-Type: application/json",
        "\\[SendsStuff#login\\] Content-Length: 80",
        "\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
        "\\[SendsStuff#login\\] <--- ERROR UnknownHostException: robofu.abc \\([0-9]+ms\\)"
    );
    data[3][0] = Logger.Level.FULL;
    data[3][1] = Arrays.asList(
        "\\[SendsStuff#login\\] ---> POST http://robofu.abc/ HTTP/1.1",
        "\\[SendsStuff#login\\] Content-Type: application/json",
        "\\[SendsStuff#login\\] Content-Length: 80",
        "\\[SendsStuff#login\\] ",
        "\\[SendsStuff#login\\] \\{\"customer_name\": \"netflix\", \"user_name\": \"denominator\", \"password\": \"password\"\\}",
        "\\[SendsStuff#login\\] ---> END HTTP \\(80-byte body\\)",
        "\\[SendsStuff#login\\] <--- ERROR UnknownHostException: robofu.abc \\([0-9]+ms\\)",
        "\\[SendsStuff#login\\] java.net.UnknownHostException: robofu.abc.*",
        "\\[SendsStuff#login\\] <--- END ERROR"
    );
    return data;
  }

  @dagger.Module(overrides = true, library = true)
  static class DontRetryModule {
    @Provides Retryer retryer() {
      return new Retryer() {
        @Override public void continueOrPropagate(RetryableException e) {
          throw e;
        }
      };
    }
  }

  @Test(dataProvider = "levelToUnknownHostOutput")
  public void unknownHostEmits(final Logger.Level logLevel, List<String> expectedMessages) throws IOException, InterruptedException {

    try {
      SendsStuff api = Feign.create(SendsStuff.class, "http://robofu.abc",
          new DontRetryModule(), new DefaultModule(logger, logLevel));

      api.login("netflix", "denominator", "password");

      fail();
    } catch (FeignException e) {
      assertMessagesMatch(expectedMessages);
    }
  }

  @dagger.Module(overrides = true, library = true)
  static class RetryOnceModule {
    @Provides Retryer retryer() {
      return new Retryer() {
        boolean retried;

        @Override public void continueOrPropagate(RetryableException e) {
          if (!retried) {
            retried = true;
            return;
          }
          throw e;
        }
      };
    }
  }

  public void retryEmits() throws IOException, InterruptedException {

    try {
      SendsStuff api = Feign.create(SendsStuff.class, "http://robofu.abc",
          new RetryOnceModule(), new DefaultModule(logger, Logger.Level.BASIC));

      api.login("netflix", "denominator", "password");

      fail();
    } catch (FeignException e) {
      assertMessagesMatch(Arrays.asList(
          "\\[SendsStuff#login\\] ---> POST http://robofu.abc/ HTTP/1.1",
          "\\[SendsStuff#login\\] <--- ERROR UnknownHostException: robofu.abc \\([0-9]+ms\\)",
          "\\[SendsStuff#login\\] ---> RETRYING",
          "\\[SendsStuff#login\\] ---> POST http://robofu.abc/ HTTP/1.1",
          "\\[SendsStuff#login\\] <--- ERROR UnknownHostException: robofu.abc \\([0-9]+ms\\)"
      ));
    }
  }

  private void assertMessagesMatch(List<String> expectedMessages) {
    assertEquals(messages.size(), expectedMessages.size());
    for (int i = 0; i < messages.size(); i++) {
      assertTrue(Pattern.compile(expectedMessages.get(i), Pattern.DOTALL).matcher(messages.get(i)).matches(),
          "Didn't match at message " + (i + 1) + ":\n" + Joiner.on('\n').join(messages));
    }
  }
}
TOP

Related Classes of feign.LoggerTest$DontRetryModule

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.