@@ -86,11 +86,14 @@ public void setUpUnitTests() {
8686 cluster = mock (Cluster .class );
8787 Configuration configuration = mock (Configuration .class );
8888 ProtocolOptions protocolOptions = mock (ProtocolOptions .class );
89+ QueryOptions queryOptions = mock (QueryOptions .class );
8990 Metadata metadata = mock (Metadata .class );
9091 childPolicy = mock (LoadBalancingPolicy .class );
9192 when (cluster .getConfiguration ()).thenReturn (configuration );
9293 when (configuration .getCodecRegistry ()).thenReturn (codecRegistry );
9394 when (configuration .getProtocolOptions ()).thenReturn (protocolOptions );
95+ when (configuration .getQueryOptions ()).thenReturn (queryOptions );
96+ when (queryOptions .getConsistencyLevel ()).thenReturn (ConsistencyLevel .ONE );
9497 when (protocolOptions .getProtocolVersion ()).thenReturn (ProtocolVersion .DEFAULT );
9598 when (cluster .getMetadata ()).thenReturn (metadata );
9699 when (host1 .isUp ()).thenReturn (true );
@@ -1107,6 +1110,110 @@ public void should_follow_configuration_on_query_planning(
11071110 .containsExactly (queryPlanForNonLocalConsistencyLevel2 .toArray (new Host [0 ]));
11081111 }
11091112
1113+ /**
1114+ * Ensures that {@link RackAwareRoundRobinPolicy} skips rack prioritization for LWT queries,
1115+ * treating all local DC hosts equally while still prioritizing local DC over remote DC.
1116+ *
1117+ * @test_category load_balancing:rack_aware,lwt
1118+ */
1119+ @ Test (groups = "unit" )
1120+ public void should_skip_rack_prioritization_for_lwt_queries () {
1121+ // given: a policy with 4 local DC hosts (2 in local rack, 2 in remote rack) and 2 remote DC
1122+ // hosts
1123+ // Initialize hosts in a mixed order: remoteRack, localRack, remoteRack, localRack
1124+ // This ensures that when LWT skips rack prioritization, we get a different order
1125+ // than the rack-aware order
1126+ RackAwareRoundRobinPolicy policy =
1127+ new RackAwareRoundRobinPolicy ("localDC" , "localRack" , 1 , false , false , false );
1128+ policy .init (cluster , ImmutableList .of (host3 , host1 , host4 , host2 , host5 , host6 ));
1129+
1130+ // Create a mock LWT statement
1131+ Statement lwtStatement = mock (Statement .class );
1132+ when (lwtStatement .isLWT ()).thenReturn (true );
1133+ when (lwtStatement .getConsistencyLevel ()).thenReturn (ConsistencyLevel .ONE );
1134+
1135+ // when: generating query plans for LWT queries
1136+ policy .index .set (0 );
1137+ List <Host > queryPlan1 = Lists .newArrayList (policy .newQueryPlan ("keyspace" , lwtStatement ));
1138+ List <Host > queryPlan2 = Lists .newArrayList (policy .newQueryPlan ("keyspace" , lwtStatement ));
1139+
1140+ // then: all 4 local DC hosts should appear before any remote DC host (no rack prioritization)
1141+ Assertions .assertThat (queryPlan1 .subList (0 , 4 )).containsOnly (host1 , host2 , host3 , host4 );
1142+ Assertions .assertThat (queryPlan2 .subList (0 , 4 )).containsOnly (host1 , host2 , host3 , host4 );
1143+
1144+ // then: remote DC hosts should appear after all local DC hosts
1145+ Assertions .assertThat (queryPlan1 .subList (4 , 5 )).containsOnly (host5 );
1146+ Assertions .assertThat (queryPlan2 .subList (4 , 5 )).containsOnly (host5 );
1147+
1148+ // then: for LWT queries, order should follow insertion order (host3, host1, host4, host2)
1149+ // not rack-aware order (host1, host2, host3, host4)
1150+ Assertions .assertThat (queryPlan1 ).startsWith (host3 );
1151+ Assertions .assertThat (queryPlan2 ).startsWith (host1 );
1152+ }
1153+
1154+ /**
1155+ * Ensures that {@link RackAwareRoundRobinPolicy} preserves rack-aware routing for non-LWT
1156+ * queries.
1157+ *
1158+ * @test_category load_balancing:rack_aware
1159+ */
1160+ @ Test (groups = "unit" )
1161+ public void should_preserve_rack_aware_routing_for_non_lwt_queries () {
1162+ // given: a policy with 4 local DC hosts (2 in local rack, 2 in remote rack) and 2 remote DC
1163+ // hosts
1164+ // Initialize hosts in a mixed order to ensure rack-aware routing reorganizes them
1165+ RackAwareRoundRobinPolicy policy =
1166+ new RackAwareRoundRobinPolicy ("localDC" , "localRack" , 1 , false , false , false );
1167+ policy .init (cluster , ImmutableList .of (host3 , host1 , host4 , host2 , host5 , host6 ));
1168+
1169+ // Create a normal (non-LWT) statement
1170+ Statement normalStatement = mock (Statement .class );
1171+ when (normalStatement .isLWT ()).thenReturn (false );
1172+ when (normalStatement .getConsistencyLevel ()).thenReturn (ConsistencyLevel .ONE );
1173+
1174+ // when: generating query plans for non-LWT queries
1175+ policy .index .set (0 );
1176+ List <Host > queryPlan1 = Lists .newArrayList (policy .newQueryPlan ("keyspace" , normalStatement ));
1177+ List <Host > queryPlan2 = Lists .newArrayList (policy .newQueryPlan ("keyspace" , normalStatement ));
1178+
1179+ // then: local rack hosts (host1, host2) should appear first regardless of init order
1180+ Assertions .assertThat (queryPlan1 .subList (0 , 2 )).containsOnly (host1 , host2 );
1181+ Assertions .assertThat (queryPlan2 .subList (0 , 2 )).containsOnly (host1 , host2 );
1182+
1183+ // then: remote rack local DC hosts (host3, host4) should appear next
1184+ Assertions .assertThat (queryPlan1 .subList (2 , 4 )).containsOnly (host3 , host4 );
1185+ Assertions .assertThat (queryPlan2 .subList (2 , 4 )).containsOnly (host3 , host4 );
1186+
1187+ // then: remote DC hosts should appear last
1188+ Assertions .assertThat (queryPlan1 .subList (4 , 5 )).containsOnly (host5 );
1189+ Assertions .assertThat (queryPlan2 .subList (4 , 5 )).containsOnly (host5 );
1190+
1191+ // then: query plans should follow round-robin pattern within rack boundaries
1192+ Assertions .assertThat (queryPlan1 ).startsWith (host1 );
1193+ Assertions .assertThat (queryPlan2 ).startsWith (host2 );
1194+ }
1195+
1196+ /**
1197+ * Ensures that {@link RackAwareRoundRobinPolicy} handles null statement correctly.
1198+ *
1199+ * @test_category load_balancing:rack_aware
1200+ */
1201+ @ Test (groups = "unit" )
1202+ public void should_handle_null_statement () {
1203+ // given: a policy with hosts in local and remote DC
1204+ RackAwareRoundRobinPolicy policy =
1205+ new RackAwareRoundRobinPolicy ("localDC" , "localRack" , 1 , false , false , false );
1206+ policy .init (cluster , ImmutableList .of (host1 , host2 , host3 , host4 , host5 , host6 ));
1207+
1208+ // when: generating query plan with null statement
1209+ policy .index .set (0 );
1210+ List <Host > queryPlan = Lists .newArrayList (policy .newQueryPlan ("keyspace" , null ));
1211+
1212+ // then: should use rack-aware routing (default behavior for non-LWT)
1213+ // Local rack hosts should appear first
1214+ Assertions .assertThat (queryPlan .subList (0 , 2 )).containsOnly (host1 , host2 );
1215+ }
1216+
11101217 @ DataProvider (name = "distanceTestCases" )
11111218 public Object [][] distanceTestCases () {
11121219 return new Object [][] {
0 commit comments