/* * 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; import com.google.common.collect.Lists; import org.scassandra.http.client.PreparedStatementPreparation; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.List; import java.util.concurrent.TimeUnit; import static com.datastax.driver.core.Assertions.assertThat; import static com.datastax.driver.core.TestUtils.nonQuietClusterCloseOptions; public class QueryOptionsTest { ScassandraCluster scassandra; QueryOptions queryOptions; SortingLoadBalancingPolicy loadBalancingPolicy; Cluster cluster = null; Session session = null; Host host1, host2, host3; @BeforeMethod(groups = "short") public void beforeMethod() { scassandra = ScassandraCluster.builder().withNodes(3).build(); scassandra.init(); queryOptions = new QueryOptions(); loadBalancingPolicy = new SortingLoadBalancingPolicy(); cluster = Cluster.builder() .addContactPoints(scassandra.address(2).getAddress()) .withPort(scassandra.getBinaryPort()) .withLoadBalancingPolicy(loadBalancingPolicy) .withQueryOptions(queryOptions) .withNettyOptions(nonQuietClusterCloseOptions) .build(); session = cluster.connect(); host1 = TestUtils.findHost(cluster, 1); host2 = TestUtils.findHost(cluster, 2); host3 = TestUtils.findHost(cluster, 3); // Make sure there are no prepares for (int host : Lists.newArrayList(1, 2, 3)) { assertThat(scassandra.node(host).activityClient().retrievePreparedStatementPreparations()).hasSize(0); scassandra.node(host).activityClient().clearAllRecordedActivity(); } } public void validatePrepared(boolean expectAll) { // Prepare the statement String query = "select sansa_stark from the_known_world"; PreparedStatement statement = session.prepare(query); assertThat(cluster.manager.preparedQueries).containsValue(statement); // Ensure prepared properly based on expectation. List<PreparedStatementPreparation> preparationOne = scassandra.node(1).activityClient().retrievePreparedStatementPreparations(); List<PreparedStatementPreparation> preparationTwo = scassandra.node(2).activityClient().retrievePreparedStatementPreparations(); List<PreparedStatementPreparation> preparationThree = scassandra.node(3).activityClient().retrievePreparedStatementPreparations(); assertThat(preparationOne).hasSize(1); assertThat(preparationOne.get(0).getPreparedStatementText()).isEqualTo(query); if (expectAll) { assertThat(preparationTwo).hasSize(1); assertThat(preparationTwo.get(0).getPreparedStatementText()).isEqualTo(query); assertThat(preparationThree).hasSize(1); assertThat(preparationThree.get(0).getPreparedStatementText()).isEqualTo(query); } else { assertThat(preparationTwo).isEmpty(); assertThat(preparationThree).isEmpty(); } } /** * <p> * Validates that statements are only prepared on one node when * {@link QueryOptions#setPrepareOnAllHosts(boolean)} is set to false. * </p> * * @test_category prepared_statements:prepared * @expected_result prepare query only on the first node. * @jira_ticket JAVA-797 * @since 2.0.11, 2.1.8, 2.2.1 */ @Test(groups = "short") public void should_prepare_once_when_prepare_on_all_hosts_false() { queryOptions.setPrepareOnAllHosts(false); validatePrepared(false); } /** * <p> * Validates that statements are prepared on one node when * {@link QueryOptions#setPrepareOnAllHosts(boolean)} is set to true. * </p> * * @test_category prepared_statements:prepared * @expected_result all nodes prepared the query * @jira_ticket JAVA-797 * @since 2.0.11, 2.1.8, 2.2.1 */ @Test(groups = "short") public void should_prepare_everywhere_when_prepare_on_all_hosts_true() { queryOptions.setPrepareOnAllHosts(true); validatePrepared(true); } /** * <p> * Validates that statements are prepared on one node when * {@link QueryOptions#setPrepareOnAllHosts(boolean)} is not set. * </p> * * @test_category prepared_statements:prepared * @expected_result all nodes prepared the query. * @jira_ticket JAVA-797 * @since 2.0.11 */ @Test(groups = "short") public void should_prepare_everywhere_when_not_configured() { validatePrepared(true); } private void valideReprepareOnUp(boolean expectReprepare) { String query = "select sansa_stark from the_known_world"; int maxTries = 3; for (int i = 1; i <= maxTries; i++) { session.prepare(query); List<PreparedStatementPreparation> preparationOne = scassandra.node(1).activityClient().retrievePreparedStatementPreparations(); assertThat(preparationOne).hasSize(1); assertThat(preparationOne.get(0).getPreparedStatementText()).isEqualTo(query); scassandra.node(1).activityClient().clearAllRecordedActivity(); scassandra.node(1).stop(); assertThat(cluster).host(1).goesDownWithin(10, TimeUnit.SECONDS); scassandra.node(1).start(); assertThat(cluster).host(1).comesUpWithin(60, TimeUnit.SECONDS); preparationOne = scassandra.node(1).activityClient().retrievePreparedStatementPreparations(); if (expectReprepare) { // tests fail randomly at this point, probably due to // https://github.com/scassandra/scassandra-server/issues/116 try { assertThat(preparationOne).hasSize(1); assertThat(preparationOne.get(0).getPreparedStatementText()).isEqualTo(query); break; } catch (AssertionError e) { if (i == maxTries) throw e; // retry scassandra.node(1).activityClient().clearAllRecordedActivity(); } } else { assertThat(preparationOne).isEmpty(); break; } } } /** * <p> * Validates that statements are reprepared when a node comes back up when * {@link QueryOptions#setReprepareOnUp(boolean)} is set to true. * </p> * * @test_category prepared_statements:prepared * @expected_result reprepare query on the restarted node. * @jira_ticket JAVA-658 * @since 2.0.11, 2.1.8, 2.2.1 */ @Test(groups = "short") public void should_reprepare_on_up_when_enabled() { queryOptions.setReprepareOnUp(true); valideReprepareOnUp(true); } /** * <p> * Validates that statements are reprepared when a node comes back up with * the default configuration. * </p> * * @test_category prepared_statements:prepared * @expected_result reprepare query on the restarted node. * @jira_ticket JAVA-658 * @since 2.0.11, 2.1.8, 2.2.1 */ @Test(groups = "short") public void should_reprepare_on_up_by_default() { valideReprepareOnUp(true); } /** * <p> * Validates that statements are not reprepared when a node comes back up when * {@link QueryOptions#setReprepareOnUp(boolean)} is set to false. * </p> * * @test_category prepared_statements:prepared * @expected_result do not reprepare query on the restarted node. * @jira_ticket JAVA-658 * @since 2.0.11, 2.1.8, 2.2.1 */ @Test(groups = "short") public void should_not_reprepare_on_up_when_disabled() { queryOptions.setReprepareOnUp(false); valideReprepareOnUp(false); } @AfterMethod(groups = "short", alwaysRun = true) public void afterMethod() { if (cluster != null) cluster.close(); if (scassandra != null) scassandra.stop(); } }