From 41a669a100646abbcccc2f41bdfe0a11db648b1b Mon Sep 17 00:00:00 2001 From: Mick Semb Wever Date: Tue, 16 May 2023 16:04:39 +0200 Subject: [PATCH] Deduplicate the MixedMode* upgrade jvm-dtests Also update method parameters to be clearer in how we declare testcase applicability patch by Mick Semb Wever; reviewed by David Capwell for CASSANDRA-18506 --- .../MixedModeAvailabilityTestBase.java | 19 +-- .../MixedModeAvailabilityV30AllOneTest.java | 2 +- .../MixedModeAvailabilityV30OneAllTest.java | 2 +- ...edModeAvailabilityV30QuorumQuorumTest.java | 2 +- .../MixedModeAvailabilityV3XAllOneTest.java | 32 ----- .../MixedModeAvailabilityV3XOneAllTest.java | 32 ----- ...edModeAvailabilityV3XQuorumQuorumTest.java | 32 ----- .../upgrade/MixedModeConsistencyTestBase.java | 124 ------------------ .../upgrade/MixedModeConsistencyV30Test.java | 102 +++++++++++++- .../upgrade/MixedModeConsistencyV3XTest.java | 33 ----- .../distributed/upgrade/UpgradeTestBase.java | 55 +++++--- 11 files changed, 145 insertions(+), 290 deletions(-) delete mode 100644 test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XAllOneTest.java delete mode 100644 test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XOneAllTest.java delete mode 100644 test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XQuorumQuorumTest.java delete mode 100644 test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyTestBase.java delete mode 100644 test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyV3XTest.java diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityTestBase.java b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityTestBase.java index 1ca23ae80e..49f327b026 100644 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityTestBase.java +++ b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityTestBase.java @@ -23,7 +23,6 @@ import java.util.concurrent.RejectedExecutionException; import org.junit.Test; -import com.vdurmont.semver4j.Semver; import org.apache.cassandra.distributed.api.ConsistencyLevel; import org.apache.cassandra.distributed.api.ICoordinator; import org.apache.cassandra.exceptions.ReadFailureException; @@ -51,13 +50,11 @@ public abstract class MixedModeAvailabilityTestBase extends UpgradeTestBase private static final String INSERT = withKeyspace("INSERT INTO %s.t (k, c, v) VALUES (?, ?, ?)"); private static final String SELECT = withKeyspace("SELECT * FROM %s.t WHERE k = ?"); - private final Semver initial; private final ConsistencyLevel writeConsistencyLevel; private final ConsistencyLevel readConsistencyLevel; - public MixedModeAvailabilityTestBase(Semver initial, ConsistencyLevel writeConsistencyLevel, ConsistencyLevel readConsistencyLevel) + public MixedModeAvailabilityTestBase(ConsistencyLevel writeConsistencyLevel, ConsistencyLevel readConsistencyLevel) { - this.initial = initial; this.writeConsistencyLevel = writeConsistencyLevel; this.readConsistencyLevel = readConsistencyLevel; } @@ -65,32 +62,30 @@ public abstract class MixedModeAvailabilityTestBase extends UpgradeTestBase @Test public void testAvailabilityCoordinatorNotUpgraded() throws Throwable { - testAvailability(false, initial, writeConsistencyLevel, readConsistencyLevel); + testAvailability(false, writeConsistencyLevel, readConsistencyLevel); } @Test public void testAvailabilityCoordinatorUpgraded() throws Throwable { - testAvailability(true, initial, writeConsistencyLevel, readConsistencyLevel); + testAvailability(true, writeConsistencyLevel, readConsistencyLevel); } - protected static void testAvailability(Semver initial, - ConsistencyLevel writeConsistencyLevel, + protected static void testAvailability(ConsistencyLevel writeConsistencyLevel, ConsistencyLevel readConsistencyLevel) throws Throwable { - testAvailability(true, initial, writeConsistencyLevel, readConsistencyLevel); - testAvailability(false, initial, writeConsistencyLevel, readConsistencyLevel); + testAvailability(true, writeConsistencyLevel, readConsistencyLevel); + testAvailability(false, writeConsistencyLevel, readConsistencyLevel); } private static void testAvailability(boolean upgradedCoordinator, - Semver initial, ConsistencyLevel writeConsistencyLevel, ConsistencyLevel readConsistencyLevel) throws Throwable { new TestCase() .nodes(NUM_NODES) .nodesToUpgrade(upgradedCoordinator ? 1 : 2) - .upgradesToCurrentFrom(initial) + .upgradesToCurrentFrom(v30) .withConfig(config -> config.set("read_request_timeout_in_ms", SECONDS.toMillis(5)) .set("write_request_timeout_in_ms", SECONDS.toMillis(5))) // use retry of 10ms so that each check is consistent diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30AllOneTest.java b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30AllOneTest.java index 96dc4547dc..47ef8da9f1 100644 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30AllOneTest.java +++ b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30AllOneTest.java @@ -27,6 +27,6 @@ public class MixedModeAvailabilityV30AllOneTest extends MixedModeAvailabilityTes { public MixedModeAvailabilityV30AllOneTest() { - super(v30, ConsistencyLevel.ALL, ConsistencyLevel.ONE); + super(ConsistencyLevel.ALL, ConsistencyLevel.ONE); } } diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30OneAllTest.java b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30OneAllTest.java index be5154979e..fec9230e12 100644 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30OneAllTest.java +++ b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30OneAllTest.java @@ -27,6 +27,6 @@ public class MixedModeAvailabilityV30OneAllTest extends MixedModeAvailabilityTes { public MixedModeAvailabilityV30OneAllTest() { - super(v30, ConsistencyLevel.ONE, ConsistencyLevel.ALL); + super(ConsistencyLevel.ONE, ConsistencyLevel.ALL); } } diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30QuorumQuorumTest.java b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30QuorumQuorumTest.java index 8df53d187e..5e71a34fbb 100644 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30QuorumQuorumTest.java +++ b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV30QuorumQuorumTest.java @@ -27,6 +27,6 @@ public class MixedModeAvailabilityV30QuorumQuorumTest extends MixedModeAvailabil { public MixedModeAvailabilityV30QuorumQuorumTest() { - super(v30, ConsistencyLevel.QUORUM, ConsistencyLevel.QUORUM); + super(ConsistencyLevel.QUORUM, ConsistencyLevel.QUORUM); } } diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XAllOneTest.java b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XAllOneTest.java deleted file mode 100644 index 955e0ba082..0000000000 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XAllOneTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cassandra.distributed.upgrade; - -import org.apache.cassandra.distributed.api.ConsistencyLevel; - -/** - * {@link MixedModeAvailabilityTestBase} for upgrades from v3X with ALL-ONE write-read consistency. - */ -public class MixedModeAvailabilityV3XAllOneTest extends MixedModeAvailabilityTestBase -{ - public MixedModeAvailabilityV3XAllOneTest() - { - super(v3X, ConsistencyLevel.ALL, ConsistencyLevel.ONE); - } -} diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XOneAllTest.java b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XOneAllTest.java deleted file mode 100644 index 59554d15c9..0000000000 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XOneAllTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cassandra.distributed.upgrade; - -import org.apache.cassandra.distributed.api.ConsistencyLevel; - -/** - * {@link MixedModeAvailabilityTestBase} for upgrades from v3X with ONE-ALL write-read consistency. - */ -public class MixedModeAvailabilityV3XOneAllTest extends MixedModeAvailabilityTestBase -{ - public MixedModeAvailabilityV3XOneAllTest() - { - super(v3X, ConsistencyLevel.ONE, ConsistencyLevel.ALL); - } -} diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XQuorumQuorumTest.java b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XQuorumQuorumTest.java deleted file mode 100644 index e65f4f46d8..0000000000 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeAvailabilityV3XQuorumQuorumTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cassandra.distributed.upgrade; - -import org.apache.cassandra.distributed.api.ConsistencyLevel; - -/** - * {@link MixedModeAvailabilityTestBase} for upgrades from v3X with QUORUM-QUORUM write-read consistency. - */ -public class MixedModeAvailabilityV3XQuorumQuorumTest extends MixedModeAvailabilityTestBase -{ - public MixedModeAvailabilityV3XQuorumQuorumTest() - { - super(v3X, ConsistencyLevel.QUORUM, ConsistencyLevel.QUORUM); - } -} diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyTestBase.java b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyTestBase.java deleted file mode 100644 index 519625e761..0000000000 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyTestBase.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cassandra.distributed.upgrade; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import com.vdurmont.semver4j.Semver; - -import org.apache.cassandra.distributed.UpgradeableCluster; -import org.apache.cassandra.distributed.api.ConsistencyLevel; -import org.apache.cassandra.distributed.api.IUpgradeableInstance; - -import static java.lang.String.format; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.apache.cassandra.distributed.api.ConsistencyLevel.ALL; -import static org.apache.cassandra.distributed.api.ConsistencyLevel.ONE; -import static org.apache.cassandra.distributed.api.ConsistencyLevel.QUORUM; -import static org.apache.cassandra.distributed.shared.AssertUtils.assertRows; -import static org.apache.cassandra.distributed.shared.AssertUtils.row; - -public class MixedModeConsistencyTestBase extends UpgradeTestBase -{ - protected static void testConsistency(Semver initial) throws Throwable - { - List testers = new ArrayList<>(); - testers.addAll(Tester.create(1, ALL)); - testers.addAll(Tester.create(2, ALL, QUORUM)); - testers.addAll(Tester.create(3, ALL, QUORUM, ONE)); - - new TestCase() - .nodes(3) - .nodesToUpgrade(1) - .upgradesToCurrentFrom(initial) - .withConfig(config -> config.set("read_request_timeout_in_ms", SECONDS.toMillis(30)) - .set("write_request_timeout_in_ms", SECONDS.toMillis(30))) - .setup(cluster -> { - Tester.createTable(cluster); - for (Tester tester : testers) - tester.writeRows(cluster); - }).runAfterNodeUpgrade((cluster, node) -> { - for (Tester tester : testers) - tester.readRows(cluster); - }).run(); - } - - private static class Tester - { - private final int numWrittenReplicas; - private final ConsistencyLevel readConsistencyLevel; - private final UUID partitionKey; - - private Tester(int numWrittenReplicas, ConsistencyLevel readConsistencyLevel) - { - this.numWrittenReplicas = numWrittenReplicas; - this.readConsistencyLevel = readConsistencyLevel; - partitionKey = UUID.randomUUID(); - } - - private static List create(int numWrittenReplicas, ConsistencyLevel... readConsistencyLevels) - { - return Stream.of(readConsistencyLevels) - .map(readConsistencyLevel -> new Tester(numWrittenReplicas, readConsistencyLevel)) - .collect(Collectors.toList()); - } - - private static void createTable(UpgradeableCluster cluster) - { - cluster.schemaChange(withKeyspace("CREATE TABLE %s.t (k uuid, c int, v int, PRIMARY KEY (k, c))")); - } - - private void writeRows(UpgradeableCluster cluster) - { - String query = withKeyspace("INSERT INTO %s.t (k, c, v) VALUES (?, ?, ?)"); - for (int i = 1; i <= numWrittenReplicas; i++) - { - IUpgradeableInstance node = cluster.get(i); - node.executeInternal(query, partitionKey, 1, 10); - node.executeInternal(query, partitionKey, 2, 20); - node.executeInternal(query, partitionKey, 3, 30); - } - } - - private void readRows(UpgradeableCluster cluster) - { - String query = withKeyspace("SELECT * FROM %s.t WHERE k = ?"); - int coordinator = 1; - try - { - for (coordinator = 1; coordinator <= cluster.size(); coordinator++) - { - assertRows(cluster.coordinator(coordinator).execute(query, readConsistencyLevel, partitionKey), - row(partitionKey, 1, 10), - row(partitionKey, 2, 20), - row(partitionKey, 3, 30)); - } - } - catch (Throwable t) - { - String format = "Unexpected error reading rows with %d written replicas, CL=%s and coordinator=%s"; - throw new AssertionError(format(format, numWrittenReplicas, readConsistencyLevel, coordinator), t); - } - } - } -} diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyV30Test.java b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyV30Test.java index 2712a46040..5ee80151a6 100644 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyV30Test.java +++ b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyV30Test.java @@ -18,16 +18,108 @@ package org.apache.cassandra.distributed.upgrade; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.junit.Test; -/** - * {@link MixedModeConsistencyTestBase} for upgrades from v30. - */ -public class MixedModeConsistencyV30Test extends MixedModeConsistencyTestBase +import org.apache.cassandra.distributed.UpgradeableCluster; +import org.apache.cassandra.distributed.api.ConsistencyLevel; +import org.apache.cassandra.distributed.api.IUpgradeableInstance; + +import static java.lang.String.format; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.apache.cassandra.distributed.api.ConsistencyLevel.ALL; +import static org.apache.cassandra.distributed.api.ConsistencyLevel.ONE; +import static org.apache.cassandra.distributed.api.ConsistencyLevel.QUORUM; +import static org.apache.cassandra.distributed.shared.AssertUtils.assertRows; +import static org.apache.cassandra.distributed.shared.AssertUtils.row; + +public class MixedModeConsistencyV30Test extends UpgradeTestBase { @Test public void testConsistency() throws Throwable { - testConsistency(v30); + List testers = new ArrayList<>(); + testers.addAll(Tester.create(1, ALL)); + testers.addAll(Tester.create(2, ALL, QUORUM)); + testers.addAll(Tester.create(3, ALL, QUORUM, ONE)); + + new TestCase() + .nodes(3) + .nodesToUpgrade(1) + .upgradesToCurrentFrom(v30) + .withConfig(config -> config.set("read_request_timeout_in_ms", SECONDS.toMillis(30)) + .set("write_request_timeout_in_ms", SECONDS.toMillis(30))) + .setup(cluster -> { + Tester.createTable(cluster); + for (Tester tester : testers) + tester.writeRows(cluster); + }).runAfterNodeUpgrade((cluster, node) -> { + for (Tester tester : testers) + tester.readRows(cluster); + }).run(); + } + + private static class Tester + { + private final int numWrittenReplicas; + private final ConsistencyLevel readConsistencyLevel; + private final UUID partitionKey; + + private Tester(int numWrittenReplicas, ConsistencyLevel readConsistencyLevel) + { + this.numWrittenReplicas = numWrittenReplicas; + this.readConsistencyLevel = readConsistencyLevel; + partitionKey = UUID.randomUUID(); + } + + private static List create(int numWrittenReplicas, ConsistencyLevel... readConsistencyLevels) + { + return Stream.of(readConsistencyLevels) + .map(readConsistencyLevel -> new Tester(numWrittenReplicas, readConsistencyLevel)) + .collect(Collectors.toList()); + } + + private static void createTable(UpgradeableCluster cluster) + { + cluster.schemaChange(withKeyspace("CREATE TABLE %s.t (k uuid, c int, v int, PRIMARY KEY (k, c))")); + } + + private void writeRows(UpgradeableCluster cluster) + { + String query = withKeyspace("INSERT INTO %s.t (k, c, v) VALUES (?, ?, ?)"); + for (int i = 1; i <= numWrittenReplicas; i++) + { + IUpgradeableInstance node = cluster.get(i); + node.executeInternal(query, partitionKey, 1, 10); + node.executeInternal(query, partitionKey, 2, 20); + node.executeInternal(query, partitionKey, 3, 30); + } + } + + private void readRows(UpgradeableCluster cluster) + { + String query = withKeyspace("SELECT * FROM %s.t WHERE k = ?"); + int coordinator = 1; + try + { + for (coordinator = 1; coordinator <= cluster.size(); coordinator++) + { + assertRows(cluster.coordinator(coordinator).execute(query, readConsistencyLevel, partitionKey), + row(partitionKey, 1, 10), + row(partitionKey, 2, 20), + row(partitionKey, 3, 30)); + } + } + catch (Throwable t) + { + String format = "Unexpected error reading rows with %d written replicas, CL=%s and coordinator=%s"; + throw new AssertionError(format(format, numWrittenReplicas, readConsistencyLevel, coordinator), t); + } + } } } diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyV3XTest.java b/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyV3XTest.java deleted file mode 100644 index d39ea56039..0000000000 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/MixedModeConsistencyV3XTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.cassandra.distributed.upgrade; - -import org.junit.Test; - -/** - * {@link MixedModeConsistencyTestBase} for upgrades from v3X. - */ -public class MixedModeConsistencyV3XTest extends MixedModeConsistencyTestBase -{ - @Test - public void testConsistency() throws Throwable - { - testConsistency(v3X); - } -} diff --git a/test/distributed/org/apache/cassandra/distributed/upgrade/UpgradeTestBase.java b/test/distributed/org/apache/cassandra/distributed/upgrade/UpgradeTestBase.java index e44ecc721a..3f8f4d47c8 100644 --- a/test/distributed/org/apache/cassandra/distributed/upgrade/UpgradeTestBase.java +++ b/test/distributed/org/apache/cassandra/distributed/upgrade/UpgradeTestBase.java @@ -176,26 +176,26 @@ public class UpgradeTestBase extends DistributedTestBase return this; } - /** performs all supported upgrade paths that exist in between from and end on CURRENT (inclusive) + /** performs all supported upgrade paths that exist in between lowerBound and end on CURRENT (inclusive) * {@code upgradesToCurrentFrom(3.0); // produces: 3.0 -> CURRENT, 3.11 -> CURRENT, …} **/ - public TestCase upgradesToCurrentFrom(Semver from) + public TestCase upgradesToCurrentFrom(Semver lowerBound) { - return upgradesTo(from, CURRENT); + return upgradesTo(lowerBound, CURRENT); } /** * performs all supported upgrade paths to the "to" target; example * {@code upgradesTo(3.0, 4.0); // produces: 3.0 -> 4.0, 3.11 -> 4.0} */ - public TestCase upgradesTo(Semver from, Semver to) + public TestCase upgradesTo(Semver lowerBound, Semver to) { List upgrade = new ArrayList<>(); NavigableSet vertices = sortedVertices(SUPPORTED_UPGRADE_PATHS); - for (Semver start : vertices.subSet(from, true, to, false)) + for (Semver start : vertices.subSet(lowerBound, true, to, false)) { // only include pairs that are allowed, and start or end on CURRENT - if (SUPPORTED_UPGRADE_PATHS.hasEdge(start, to) && contains(start, to, CURRENT)) + if (SUPPORTED_UPGRADE_PATHS.hasEdge(start, to) && edgeTouchesTarget(start, to, CURRENT)) upgrade.add(new TestVersions(versions.getLatest(start), Collections.singletonList(versions.getLatest(to)))); } logger.info("Adding upgrades of\n{}", upgrade.stream().map(TestVersions::toString).collect(Collectors.joining("\n"))); @@ -207,14 +207,14 @@ public class UpgradeTestBase extends DistributedTestBase * performs all supported upgrade paths from the "from" target; example * {@code upgradesFrom(4.0, 4.2); // produces: 4.0 -> 4.1, 4.0 -> 4.2} */ - public TestCase upgradesFrom(Semver from, Semver to) + public TestCase upgradesFrom(Semver from, Semver upperBound) { List upgrade = new ArrayList<>(); NavigableSet vertices = sortedVertices(SUPPORTED_UPGRADE_PATHS); - for (Semver end : vertices.subSet(from, false, to, true)) + for (Semver end : vertices.subSet(from, false, upperBound, true)) { // only include pairs that are allowed, and start or end on CURRENT - if (SUPPORTED_UPGRADE_PATHS.hasEdge(from, end) && contains(from, end, CURRENT)) + if (SUPPORTED_UPGRADE_PATHS.hasEdge(from, end) && edgeTouchesTarget(from, end, CURRENT)) upgrade.add(new TestVersions(versions.getLatest(from), Collections.singletonList(versions.getLatest(end)))); } logger.info("Adding upgrades of\n{}", upgrade.stream().map(TestVersions::toString).collect(Collectors.joining("\n"))); @@ -226,20 +226,41 @@ public class UpgradeTestBase extends DistributedTestBase * performs all supported upgrade paths that exist in between from and to that include the current version. * This call is equivalent to calling {@code upgradesTo(from, CURRENT).upgradesFrom(CURRENT, to)}. **/ - public TestCase upgrades(Semver from, Semver to) + public TestCase upgrades(Semver lowerBound, Semver upperBound) { - Assume.assumeTrue("Unable to do upgrades(" + from + ", " + to + "); does not contain CURRENT=" + CURRENT, contains(from, to, CURRENT)); - if (from.compareTo(CURRENT) < 0) - upgradesTo(from, CURRENT); - if (CURRENT.compareTo(to) < 0) - upgradesFrom(CURRENT, to); + Assume.assumeTrue("Unable to do any upgrades in bounds (" + lowerBound + ", " + upperBound + "); does not cover CURRENT=" + CURRENT, rangeCoversTarget(lowerBound, upperBound, CURRENT)); + if (lowerBound.compareTo(CURRENT) < 0) + upgradesTo(lowerBound, CURRENT); + if (CURRENT.compareTo(upperBound) < 0) + upgradesFrom(CURRENT, upperBound); return this; } - private static boolean contains(Semver from, Semver to, Semver target) + private static boolean rangeCoversTarget(Semver lowerBound, Semver upperBound, Semver target) { // target >= from && target <= to - return target.compareTo(from) >= 0 && target.compareTo(to) <= 0; + return target.isGreaterThanOrEqualTo(lowerBound) && target.isLowerThanOrEqualTo(upperBound); + } + + /** returns true if the target version has the same major and minor as either the from or the to version **/ + private static boolean edgeTouchesTarget(Semver from, Semver to, Semver target) + { + switch (from.diff(target)) + { + default: + return true; + case MAJOR: + case MINOR: + // fall through + } + switch (to.diff(target)) + { + default: + return true; + case MAJOR: + case MINOR: + return false; + } } /** Will test this specific upgrade path **/