/* * Copyright (C) 2012-2015 DataStax 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 com.datastax.driver.core.policies; import com.datastax.driver.core.*; import com.datastax.driver.core.exceptions.DriverException; import com.datastax.driver.core.exceptions.ServerError; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.mockito.Mockito; import org.slf4j.helpers.MessageFormatter; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import static com.datastax.driver.core.Assertions.assertThat; import static com.datastax.driver.core.ConsistencyLevel.LOCAL_ONE; import static com.datastax.driver.core.WriteType.SIMPLE; import static com.datastax.driver.core.policies.LoggingRetryPolicy.*; import static com.datastax.driver.core.policies.RetryPolicy.RetryDecision.ignore; import static com.datastax.driver.core.policies.RetryPolicy.RetryDecision.tryNextHost; import static org.apache.log4j.Level.INFO; import static org.scassandra.http.client.Result.*; /** * Integration tests with LoggingRetryPolicy. */ public class LoggingRetryPolicyIntegrationTest extends AbstractRetryPolicyIntegrationTest { private volatile RetryPolicy.RetryDecision retryDecision; private Logger logger = Logger.getLogger(LoggingRetryPolicy.class.getName()); private MemoryAppender appender; private Level originalLevel; private ConsistencyLevel defaultCL; @BeforeClass(groups = {"short", "unit"}) public void setUpRetryPolicy() { setRetryPolicy(new LoggingRetryPolicy(new CustomRetryPolicy())); } @BeforeMethod(groups = {"short"}) public void storeDefaultCL() { defaultCL = cluster.getConfiguration().getQueryOptions().getConsistencyLevel(); } @BeforeMethod(groups = {"short", "unit"}) public void startCapturingLogs() { originalLevel = logger.getLevel(); logger.setLevel(INFO); logger.addAppender(appender = new MemoryAppender()); } @AfterMethod(groups = {"short", "unit"}) public void stopCapturingLogs() { logger.setLevel(originalLevel); logger.removeAppender(appender); } @Test(groups = "short") public void should_log_ignored_read_timeout() throws InterruptedException { simulateError(1, read_request_timeout); retryDecision = ignore(); query(); String line = appender.waitAndGet(5000); assertThat(line.trim()).isEqualTo(expectedMessage(IGNORING_READ_TIMEOUT, defaultCL, 1, 0, false, 0)); } @Test(groups = "short") public void should_log_retried_read_timeout() throws InterruptedException { simulateError(1, read_request_timeout); retryDecision = tryNextHost(LOCAL_ONE); query(); String line = appender.waitAndGet(5000); assertThat(line.trim()).isEqualTo(expectedMessage(RETRYING_ON_READ_TIMEOUT, "next host", LOCAL_ONE, defaultCL, 1, 0, false, 0)); } @Test(groups = "short") public void should_log_ignored_write_timeout() throws InterruptedException { simulateError(1, write_request_timeout); retryDecision = ignore(); query(); String line = appender.waitAndGet(5000); assertThat(line.trim()).isEqualTo(expectedMessage(IGNORING_WRITE_TIMEOUT, defaultCL, SIMPLE, 1, 0, 0)); } @Test(groups = "short") public void should_log_retried_write_timeout() throws InterruptedException { simulateError(1, write_request_timeout); retryDecision = tryNextHost(LOCAL_ONE); query(); String line = appender.waitAndGet(5000); assertThat(line.trim()).isEqualTo(expectedMessage(RETRYING_ON_WRITE_TIMEOUT, "next host", LOCAL_ONE, defaultCL, SIMPLE, 1, 0, 0)); } @Test(groups = "short") public void should_log_ignored_unavailabe() throws InterruptedException { simulateError(1, unavailable); retryDecision = ignore(); query(); String line = appender.waitAndGet(5000); assertThat(line.trim()).isEqualTo(expectedMessage(IGNORING_UNAVAILABLE, defaultCL, 1, 0, 0)); } @Test(groups = "short") public void should_log_retried_unavailable() throws InterruptedException { simulateError(1, unavailable); retryDecision = tryNextHost(LOCAL_ONE); query(); String line = appender.waitAndGet(5000); assertThat(line.trim()).isEqualTo(expectedMessage(RETRYING_ON_UNAVAILABLE, "next host", LOCAL_ONE, defaultCL, 1, 0, 0)); } @Test(groups = "short") public void should_log_ignored_request_error() throws InterruptedException { simulateError(1, server_error); retryDecision = ignore(); query(); String line = appender.waitAndGet(5000); assertThat(line.trim()).isEqualTo(expectedMessage(IGNORING_REQUEST_ERROR, defaultCL, 0, new ServerError(host1.getSocketAddress(), "Server Error"))); } @Test(groups = "short") public void should_log_retried_request_error() throws InterruptedException { simulateError(1, server_error); retryDecision = tryNextHost(LOCAL_ONE); query(); String line = appender.waitAndGet(5000); assertThat(line.trim()).isEqualTo(expectedMessage(RETRYING_ON_REQUEST_ERROR, "next host", LOCAL_ONE, defaultCL, 0, new ServerError(host1.getSocketAddress(), "Server Error"))); } @Test(groups = "short") public void should_call_init_method_on_inner_policy() { RetryPolicy innerPolicyMock = Mockito.mock(RetryPolicy.class); new LoggingRetryPolicy(innerPolicyMock).init(cluster); Mockito.verify(innerPolicyMock).init(cluster); } @Test(groups = "unit") public void should_call_close_method_on_inner_policy() { RetryPolicy innerPolicyMock = Mockito.mock(RetryPolicy.class); new LoggingRetryPolicy(innerPolicyMock).close(); Mockito.verify(innerPolicyMock).close(); } private String expectedMessage(String template, Object... args) { return MessageFormatter.arrayFormat(template, args).getMessage(); } /** * Dynamically modifiable retry policy. */ class CustomRetryPolicy implements RetryPolicy { @Override public RetryPolicy.RetryDecision onReadTimeout(Statement statement, ConsistencyLevel cl, int requiredResponses, int receivedResponses, boolean dataRetrieved, int nbRetry) { return retryDecision; } @Override public RetryPolicy.RetryDecision onWriteTimeout(Statement statement, ConsistencyLevel cl, WriteType writeType, int requiredAcks, int receivedAcks, int nbRetry) { return retryDecision; } @Override public RetryPolicy.RetryDecision onUnavailable(Statement statement, ConsistencyLevel cl, int requiredReplica, int aliveReplica, int nbRetry) { return retryDecision; } @Override public RetryPolicy.RetryDecision onRequestError(Statement statement, ConsistencyLevel cl, DriverException e, int nbRetry) { return retryDecision; } @Override public void init(Cluster cluster) { // nothing to do } @Override public void close() { // nothing to do } } }