yifan-c commented on code in PR #14: URL: https://github.com/apache/cassandra-analytics/pull/14#discussion_r1330682548
########## cassandra-analytics-integration-tests/src/test/java/org/apache/cassandra/testing/TestVersionSupplier.java: ########## @@ -0,0 +1,41 @@ +/* + * 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.testing; + +import java.util.Arrays; +import java.util.stream.Stream; + +/** + * Generates the list of versions we're going to test against. + * We will run the same module (trunk for example) against multiple versions of Cassandra. + * This is due to releases that don't add new features that would affect the sidecar, + * but we still want to test those versions specifically to avoid the chance of regressions. + * + * <p>Ideally, we'd probably have concurrent runs of the test infrastructure each running tests against one specific + * version of C*, but this will require some additional work in the dtest framework so for now we run one at a time. + */ +public class TestVersionSupplier +{ + Stream<TestVersion> testVersions() + { + // By default, we test 2 versions that will exercise oldest and newest supported versions + String versions = System.getProperty("cassandra.sidecar.versions_to_test", "4.1"); Review Comment: The comment says there are 2 versions. The code next line has a single version as the default. ########## scripts/build-dtest-jars.sh: ########## @@ -0,0 +1,69 @@ +#!/bin/bash +# +# 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. +# + +if [ "${SKIP_DTEST_JAR_BUILD}" == "true" ]; then Review Comment: Can we have the same script as in sidecar? https://github.com/apache/cassandra-sidecar/blob/trunk/scripts/build-dtest-jars.sh It builds with specific SHAs to be deterministic. ########## scripts/build-sidecar.sh: ########## @@ -0,0 +1,48 @@ +#!/bin/bash +# +# 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. +# + +set -ex +if [ "${SKIP_SIDECAR_BUILD}" == "true" ]; then + echo "Skipping Sidecar Build because SKIP_SIDECAR_BUILD was set to 'true'" +else + SCRIPT_DIR=$( dirname -- "$( readlink -f -- "$0"; )"; ) + SIDECAR_REPO="${SIDECAR_REPO:-https://github.com/apache/cassandra-sidecar.git}" + SIDECAR_BRANCH="${SIDECAR_BRANCH:-trunk}" + SIDECAR_JAR_DIR="$(dirname "${SCRIPT_DIR}/")/dependencies" + SIDECAR_BUILD_DIR="${SIDECAR_JAR_DIR}/sidecar-build" + JAVA_MAJOR_VERISON="$(javap -verbose java.lang.String | grep "major version" | cut -d " " -f5)" + echo $JAVA_MAJOR_VERISON + if [ "${JAVA_MAJOR_VERISON}" == "52" ]; then Review Comment: I find version string is not as easy to tell. Can you checkout the approach that Cassandra takes to find the jdk version? https://github.com/apache/cassandra/blob/98a055e51c8eb6b788d3d0fe94f3d2576ab14d39/bin/cassandra.in.sh#L118-L133 ########## cassandra-analytics-integration-tests/src/test/java/org/apache/cassandra/testing/SimpleCassandraVersion.java: ########## @@ -0,0 +1,172 @@ +/* + * 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.testing; + +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Implements versioning used in Cassandra and CQL. + * <p> + * Note: The following code uses a slight variation from the semver document (http://semver.org). + * </p> + * <p> + * The rules here are a bit different than normal semver comparison. For simplicity, + * an alpha version of 4.0 or a snapshot is equal to 4.0. This allows us to test sidecar + * against alpha versions of a release. + * <p> + * While it's possible to implement full version comparison, it's likely not very useful + * This is because the main testing we are going to do will be against release versions - something like 4.0. + * We want to list an adapter as being compatible with 4.0 - and that should include 4.0 alpha, etc. + */ +public class SimpleCassandraVersion implements Comparable<SimpleCassandraVersion> +{ + /** + * note: 3rd group matches to words but only allows number and checked after regexp test. + * this is because 3rd and the last can be identical. + **/ + private static final String VERSION_REGEXP = "(\\d+)\\.(\\d+)(?:\\.(\\w+))?(\\-[.\\w]+)?([.+][.\\w]+)?"; + + private static final Pattern PATTERN = Pattern.compile(VERSION_REGEXP); + private static final String SNAPSHOT = "-SNAPSHOT"; + + public final int major; + public final int minor; + public final int patch; + + /** + * Parse a version from a string. + * + * @param version the string to parse + * @return the {@link SimpleCassandraVersion} parsed from the {@code version} string + * @throws IllegalArgumentException if the provided string does not + * represent a version + */ + public static SimpleCassandraVersion create(String version) + { + String stripped = version.toUpperCase().replace(SNAPSHOT, ""); + Matcher matcher = PATTERN.matcher(stripped); + if (!matcher.matches()) + { + throw new IllegalArgumentException("Invalid Cassandra version value: " + version); + } + + try + { + int major = Integer.parseInt(matcher.group(1)); + int minor = Integer.parseInt(matcher.group(2)); + int patch = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 0; + + return SimpleCassandraVersion.create(major, minor, patch); + } + catch (NumberFormatException e) + { + throw new IllegalArgumentException("Invalid Cassandra version value: " + version, e); + } + } + + public static SimpleCassandraVersion create(int major, int minor, int patch) + { + if (major < 0 || minor < 0 || patch < 0) + { + throw new IllegalArgumentException(); + } + return new SimpleCassandraVersion(major, minor, patch); + } + + + public SimpleCassandraVersion(int major, int minor, int patch) + { + this.major = major; + this.minor = minor; + this.patch = patch; + } + + + public int compareTo(SimpleCassandraVersion other) + { + if (major < other.major) + { + return -1; + } + if (major > other.major) + { + return 1; + } + + if (minor < other.minor) + { + return -1; + } + if (minor > other.minor) + { + return 1; + } + + if (patch < other.patch) + { + return -1; + } + if (patch > other.patch) + { + return 1; + } + return 0; + } + + @Override + public boolean equals(Object o) + { + if (!(o instanceof SimpleCassandraVersion)) + { + return false; + } + SimpleCassandraVersion that = (SimpleCassandraVersion) o; + return major == that.major + && minor == that.minor + && patch == that.patch; + } + + /** + * Returns true if this > v2 + * + * @param v2 the version to compare + * @return the result of the comparison + */ + public boolean isGreaterThan(SimpleCassandraVersion v2) + { + return compareTo(v2) > 0; + } + + @Override + public int hashCode() + { + return Objects.hash(major, minor, patch); + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append(major).append('.').append(minor).append('.').append(patch); + + return sb.toString(); Review Comment: nit: just concatenate the fields, so there is a singe line. ########## cassandra-analytics-integration-tests/src/test/java/org/apache/cassandra/sidecar/testing/IntegrationTestBase.java: ########## @@ -0,0 +1,234 @@ +/* + * 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.sidecar.testing; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.google.common.collect.ImmutableMap; +import com.google.common.util.concurrent.Uninterruptibles; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.datastax.driver.core.KeyspaceMetadata; +import com.datastax.driver.core.Session; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.util.Modules; +import io.vertx.core.Vertx; +import io.vertx.core.http.HttpServer; +import io.vertx.ext.web.client.WebClient; +import io.vertx.junit5.VertxTestContext; +import org.apache.cassandra.sidecar.MainModule; +import org.apache.cassandra.sidecar.cluster.InstancesConfig; +import org.apache.cassandra.sidecar.cluster.instance.InstanceMetadata; +import org.apache.cassandra.sidecar.common.data.QualifiedTableName; +import org.apache.cassandra.sidecar.common.dns.DnsResolver; +import org.apache.cassandra.testing.AbstractCassandraTestContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Base class for integration test. + * Start an in-jvm dtest cluster at the beginning of each test, and + * teardown the cluster after each test. + */ +public abstract class IntegrationTestBase +{ + private static final int MAX_KEYSPACE_TABLE_WAIT_ATTEMPTS = 100; // 100ms between, so 10 seconds + protected Logger logger = LoggerFactory.getLogger(this.getClass()); + protected Vertx vertx; + protected HttpServer server; + + protected static final String TEST_KEYSPACE = "testkeyspace"; + private static final String TEST_TABLE_PREFIX = "testtable"; + + protected static final int DEFAULT_RF = 3; + private static final AtomicInteger TEST_TABLE_ID = new AtomicInteger(0); + protected CassandraSidecarTestContext sidecarTestContext; + + @BeforeEach + void setup(AbstractCassandraTestContext cassandraTestContext) throws InterruptedException + { + sidecarTestContext = CassandraSidecarTestContext.from(cassandraTestContext, DnsResolver.DEFAULT); + Injector injector = Guice.createInjector(Modules + .override(new MainModule()) + .with(new IntegrationTestModule(this.sidecarTestContext))); + server = injector.getInstance(HttpServer.class); + vertx = injector.getInstance(Vertx.class); + + VertxTestContext context = new VertxTestContext(); + server.listen(0, context.succeeding(p -> { + if (sidecarTestContext.isClusterBuilt()) + { + healthCheck(sidecarTestContext.instancesConfig()); + } + sidecarTestContext.registerInstanceConfigListener(IntegrationTestBase::healthCheck); + context.completeNow(); + })); + + context.awaitCompletion(5, TimeUnit.SECONDS); + } + + @AfterEach + void tearDown() throws InterruptedException + { + final CountDownLatch closeLatch = new CountDownLatch(1); + server.close(res -> closeLatch.countDown()); + vertx.close(); + if (closeLatch.await(60, TimeUnit.SECONDS)) + { + logger.info("Close event received before timeout."); + } + else + { + logger.error("Close event timed out."); + } + sidecarTestContext.close(); + } + + protected void testWithClient(VertxTestContext context, Consumer<WebClient> tester) throws Exception + { + WebClient client = WebClient.create(vertx); + + tester.accept(client); + + // wait until the test completes + assertThat(context.awaitCompletion(30, TimeUnit.SECONDS)).isTrue(); + } + + protected void createTestKeyspace() + { + createTestKeyspace(ImmutableMap.of("datacenter1", 1)); + } + + protected void createTestKeyspace(Map<String, Integer> rf) + { + Session session = maybeGetSession(); + session.execute("CREATE KEYSPACE " + TEST_KEYSPACE + + " WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', " + generateRfString(rf) + " };"); + } + + private String generateRfString(Map<String, Integer> dcToRf) + { + return dcToRf.entrySet().stream().map(e -> String.format("'%s':%d", e.getKey(), e.getValue())) + .collect(Collectors.joining(",")); + } + + protected QualifiedTableName createTestTable(String createTableStatement) + { + Session session = maybeGetSession(); + QualifiedTableName tableName = uniqueTestTableFullName(); + session.execute(String.format(createTableStatement, tableName)); + return tableName; + } + + protected Session maybeGetSession() + { + Session session = sidecarTestContext.session(); + assertThat(session).isNotNull(); + return session; + } + + private static QualifiedTableName uniqueTestTableFullName() + { + return new QualifiedTableName(TEST_KEYSPACE, TEST_TABLE_PREFIX + TEST_TABLE_ID.getAndIncrement()); + } + + public List<Path> findChildFile(CassandraSidecarTestContext context, String hostname, String target) + { + InstanceMetadata instanceConfig = context.instancesConfig().instanceFromHost(hostname); + List<String> parentDirectories = instanceConfig.dataDirs(); + + return parentDirectories.stream().flatMap(s -> findChildFile(Paths.get(s), target).stream()) + .collect(Collectors.toList()); + } + + private List<Path> findChildFile(Path path, String target) + { + try (Stream<Path> walkStream = Files.walk(path)) + { + return walkStream.filter(p -> p.toString().endsWith(target) + || p.toString().contains("/" + target + "/")) + .collect(Collectors.toList()); + } + catch (IOException e) + { + return Collections.emptyList(); + } + } + + private static void healthCheck(InstancesConfig instancesConfig) + { + instancesConfig.instances() + .forEach(instanceMetadata -> instanceMetadata.delegate().healthCheck()); + } + + /** + * Waits for the specified keyspace/table to be available. + * Emperically, this loop usually executes either zero or one time before completing. + * However, we set a fairly high number of retries to account for variability in build machines. + * + * @param keyspaceName the keyspace for which to wait + * @param tableName the table in the keyspace for which to wait + */ + protected void waitForKeyspaceAndTable(String keyspaceName, String tableName) + { + int numInstances = sidecarTestContext.instancesConfig().instances().size(); + int retries = MAX_KEYSPACE_TABLE_WAIT_ATTEMPTS; + boolean sidecarMissingSchema = true; + while (sidecarMissingSchema && retries-- > 0) + { + sidecarMissingSchema = false; + for (int i = 0; i < numInstances; i++) + { + KeyspaceMetadata keyspace = sidecarTestContext.session(i) + .getCluster() + .getMetadata() + .getKeyspace(keyspaceName); + sidecarMissingSchema |= (keyspace == null || keyspace.getTable(tableName) == null); + } + if (sidecarMissingSchema) + { + logger.info("Keyspace/table {}/{} not yet available - waiting...", keyspaceName, tableName); + Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS); Review Comment: Nit: define a constant for the wait time too, and place it next to `MAX_KEYSPACE_TABLE_WAIT_ATTEMPTS`, so that the comment is more straightforward. ########## cassandra-analytics-integration-tests/src/test/java/org/apache/cassandra/testing/ConfigurableCassandraTestContext.java: ########## @@ -0,0 +1,73 @@ +/* + * 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.testing; + +import java.io.IOException; +import java.util.function.Consumer; + +import org.apache.cassandra.distributed.UpgradeableCluster; + +/** + * A Cassandra Test Context implementation that allows advanced cluster configuration before cluster creation + * by providing access to the cluster builder. + */ +public class ConfigurableCassandraTestContext extends AbstractCassandraTestContext +{ + public static final String BUILT_CLUSTER_CANNOT_BE_CONFIGURED_ERROR = + "Cannot configure a cluster after it is built. Please set the buildCluster annotation attribute to false, " + + "and do not call `getCluster` before calling this method."; + + private final UpgradeableCluster.Builder builder; + + public ConfigurableCassandraTestContext(SimpleCassandraVersion version, + UpgradeableCluster.Builder builder, + CassandraIntegrationTest annotation) + { + super(version, annotation); + this.builder = builder; + } + + public UpgradeableCluster configureCluster(Consumer<UpgradeableCluster.Builder> configurator) throws IOException + { + if (cluster != null) + { + throw new IllegalStateException(BUILT_CLUSTER_CANNOT_BE_CONFIGURED_ERROR); + } + configurator.accept(builder); + cluster = builder.createWithoutStarting(); + return cluster; + } + + public UpgradeableCluster configureAndStartCluster(Consumer<UpgradeableCluster.Builder> configurator) + throws IOException + { + cluster = configureCluster(configurator); + cluster.startup(); + return cluster; + } + + @Override + public String toString() + { + return "ConfigurableCassandraTestContext{" + + ", version=" + version Review Comment: unexpected comma right after `{` ########## config/checkstyle/checkstyle.xml: ########## @@ -203,15 +203,15 @@ <!-- Checks for class design. --> <!-- See https://checkstyle.org/config_design.html --> <module name="DesignForExtension" /> - <module name="FinalClass" /> +<!-- <module name="FinalClass" />--> <module name="HideUtilityClassConstructor" /> <module name="InterfaceIsType" /> - <module name="VisibilityModifier"> - <property name="packageAllowed" value="true" /> - <property name="protectedAllowed" value="true" /> - <property name="allowPublicFinalFields" value="true" /> - <property name="allowPublicImmutableFields" value="true" /> - </module> +<!-- <module name="VisibilityModifier">--> +<!-- <property name="packageAllowed" value="true" />--> +<!-- <property name="protectedAllowed" value="true" />--> +<!-- <property name="allowPublicFinalFields" value="true" />--> +<!-- <property name="allowPublicImmutableFields" value="true" />--> +<!-- </module>--> Review Comment: Are those commented out rules to be reverted? ########## scripts/build-sidecar.sh: ########## @@ -0,0 +1,48 @@ +#!/bin/bash +# +# 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. +# + +set -ex +if [ "${SKIP_SIDECAR_BUILD}" == "true" ]; then Review Comment: Alternative to "skip", using "clean" better adhere to the semantics of build tools. (Basically, the opposite). For example, w/o the "clean" flag, it doesn't rebuild from scratch. ########## scripts/build-sidecar.sh: ########## @@ -0,0 +1,48 @@ +#!/bin/bash +# +# 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. +# + +set -ex +if [ "${SKIP_SIDECAR_BUILD}" == "true" ]; then + echo "Skipping Sidecar Build because SKIP_SIDECAR_BUILD was set to 'true'" +else + SCRIPT_DIR=$( dirname -- "$( readlink -f -- "$0"; )"; ) + SIDECAR_REPO="${SIDECAR_REPO:-https://github.com/apache/cassandra-sidecar.git}" + SIDECAR_BRANCH="${SIDECAR_BRANCH:-trunk}" Review Comment: Instead of using trunk:head, can we also build with a specific SHA? ########## cassandra-analytics-integration-tests/src/test/java/org/apache/cassandra/testing/SimpleCassandraVersion.java: ########## @@ -0,0 +1,172 @@ +/* + * 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.testing; + +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Implements versioning used in Cassandra and CQL. + * <p> + * Note: The following code uses a slight variation from the semver document (http://semver.org). + * </p> + * <p> + * The rules here are a bit different than normal semver comparison. For simplicity, + * an alpha version of 4.0 or a snapshot is equal to 4.0. This allows us to test sidecar + * against alpha versions of a release. + * <p> + * While it's possible to implement full version comparison, it's likely not very useful + * This is because the main testing we are going to do will be against release versions - something like 4.0. + * We want to list an adapter as being compatible with 4.0 - and that should include 4.0 alpha, etc. + */ +public class SimpleCassandraVersion implements Comparable<SimpleCassandraVersion> +{ + /** + * note: 3rd group matches to words but only allows number and checked after regexp test. + * this is because 3rd and the last can be identical. + **/ + private static final String VERSION_REGEXP = "(\\d+)\\.(\\d+)(?:\\.(\\w+))?(\\-[.\\w]+)?([.+][.\\w]+)?"; + + private static final Pattern PATTERN = Pattern.compile(VERSION_REGEXP); + private static final String SNAPSHOT = "-SNAPSHOT"; + + public final int major; + public final int minor; + public final int patch; + + /** + * Parse a version from a string. + * + * @param version the string to parse + * @return the {@link SimpleCassandraVersion} parsed from the {@code version} string + * @throws IllegalArgumentException if the provided string does not + * represent a version + */ + public static SimpleCassandraVersion create(String version) + { + String stripped = version.toUpperCase().replace(SNAPSHOT, ""); + Matcher matcher = PATTERN.matcher(stripped); + if (!matcher.matches()) + { + throw new IllegalArgumentException("Invalid Cassandra version value: " + version); + } + + try + { + int major = Integer.parseInt(matcher.group(1)); + int minor = Integer.parseInt(matcher.group(2)); + int patch = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : 0; + + return SimpleCassandraVersion.create(major, minor, patch); + } + catch (NumberFormatException e) + { + throw new IllegalArgumentException("Invalid Cassandra version value: " + version, e); + } + } + + public static SimpleCassandraVersion create(int major, int minor, int patch) + { + if (major < 0 || minor < 0 || patch < 0) + { + throw new IllegalArgumentException(); + } + return new SimpleCassandraVersion(major, minor, patch); + } + + + public SimpleCassandraVersion(int major, int minor, int patch) + { + this.major = major; + this.minor = minor; + this.patch = patch; + } + + + public int compareTo(SimpleCassandraVersion other) + { + if (major < other.major) + { + return -1; + } + if (major > other.major) + { + return 1; + } + + if (minor < other.minor) + { + return -1; + } + if (minor > other.minor) + { + return 1; + } + + if (patch < other.patch) + { + return -1; + } + if (patch > other.patch) + { + return 1; + } + return 0; Review Comment: nit: a more succinct version ```suggestion if (major != other.major) { return major - other.major; } else if (minor != other.minor) { return minor - other.minor; } else { return patch - other.patch; } ``` ########## scripts/build-sidecar.sh: ########## @@ -0,0 +1,48 @@ +#!/bin/bash +# +# 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. +# + +set -ex +if [ "${SKIP_SIDECAR_BUILD}" == "true" ]; then + echo "Skipping Sidecar Build because SKIP_SIDECAR_BUILD was set to 'true'" +else + SCRIPT_DIR=$( dirname -- "$( readlink -f -- "$0"; )"; ) + SIDECAR_REPO="${SIDECAR_REPO:-https://github.com/apache/cassandra-sidecar.git}" + SIDECAR_BRANCH="${SIDECAR_BRANCH:-trunk}" + SIDECAR_JAR_DIR="$(dirname "${SCRIPT_DIR}/")/dependencies" + SIDECAR_BUILD_DIR="${SIDECAR_JAR_DIR}/sidecar-build" + JAVA_MAJOR_VERISON="$(javap -verbose java.lang.String | grep "major version" | cut -d " " -f5)" + echo $JAVA_MAJOR_VERISON + if [ "${JAVA_MAJOR_VERISON}" == "52" ]; then + SIDECAR_BUILD_VERSION="1.0.0-jdk8-analytics" Review Comment: nit: how about naming the versions as `1.0.0-jdk8-analytics-dev` and `1.0.0-analytics-dev` respectively? ########## cassandra-analytics-integration-tests/src/test/java/org/apache/cassandra/testing/CassandraTestContext.java: ########## @@ -0,0 +1,51 @@ +/* + * 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.testing; + +import org.apache.cassandra.distributed.UpgradeableCluster; + +/** + * Passed to integration tests. + * See {@link CassandraIntegrationTest} for the required annotation + * See {@link CassandraTestTemplate} for the Test Template + */ +public class CassandraTestContext extends AbstractCassandraTestContext +{ + + public CassandraTestContext(SimpleCassandraVersion version, + UpgradeableCluster cluster, + CassandraIntegrationTest annotation) + { + super(version, cluster, annotation); + } + + @Override + public String toString() + { + return "CassandraTestContext{" + + ", version=" + version Review Comment: unwanted heading `,` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
