Skip to content

Commit

Permalink
WIP Implement SfTest and sinceVersion
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-pfus committed Jan 26, 2024
1 parent be3825a commit bf77118
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/test/java/net/snowflake/client/SfTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package net.snowflake.client;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SfTest {
String sinceVersion();
}
112 changes: 112 additions & 0 deletions src/test/java/net/snowflake/client/TestSinceConditionRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package net.snowflake.client;

import com.google.common.annotations.VisibleForTesting;
import net.snowflake.client.jdbc.SnowflakeDriver;
import org.junit.Assume;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class TestSinceConditionRule implements MethodRule {
private final Version currentVersion;

public TestSinceConditionRule() {
currentVersion = Version.parse(SnowflakeDriver.implementVersion);
}

public TestSinceConditionRule(Version currentVersion) {
this.currentVersion = currentVersion;
}

@Override
public Statement apply(Statement statement, FrameworkMethod frameworkMethod, Object o) {
SfTest sfTest = Optional.ofNullable(frameworkMethod.getAnnotation(SfTest.class))
.orElseGet(() -> frameworkMethod.getDeclaringClass().getAnnotation(SfTest.class));
if (sfTest == null) {
return statement;
}
Version testSinceVersion = Version.parse(sfTest.sinceVersion());
// when we introduce a new feature we have to separate two cases
// running during old driver test - feature is available since version X
// running during development - feature is available since version X-1
return decideIfShouldBeRun(statement, new IgnoreStatement(sfTest), testSinceVersion, isOldDriverTest());
}

@VisibleForTesting
Statement decideIfShouldBeRun(Statement normalRun, Statement ignoreRun, Version testSinceVersion, boolean oldDriverTest) {
if (oldDriverTest && currentVersion.compareTo(testSinceVersion) > 0) {
return normalRun;
}
if (!oldDriverTest && currentVersion.compareTo(testSinceVersion) >= 0) {
return normalRun;
}
return ignoreRun;
}

private boolean isOldDriverTest() {
return Boolean.TRUE.toString().equals(System.getenv("is_old_driver"));
}

private class IgnoreStatement extends Statement {
private SfTest sfTest;

private IgnoreStatement(SfTest sfTest) {
this.sfTest = sfTest;
}

@Override
public void evaluate() {
Assume.assumeTrue(
"Test ignored, as available since "
+ sfTest.sinceVersion()
+ ", current version "
+ currentVersion,
false);
}
}

static class Version implements Comparable<Version> {
private final int major;
private final int minor;
private final int patch;

Version(int major, int minor, int patch) {
this.major = major;
this.minor = minor;
this.patch = patch;
}

static Version parse(String str) {
if (str == null) {
return null;
}
List<Integer> split =
Arrays.stream(str.split("\\.")).map(Integer::valueOf).collect(Collectors.toList());
if (split.size() != 3) {
throw new ExceptionInInitializerError(str + " should be in a form of x.y.z");
}
return new Version(split.get(0), split.get(1), split.get(2));
}

@Override
public int compareTo(Version o) {
if (major != o.major) {
return major - o.major;
} else if (minor != o.minor) {
return minor - o.minor;
} else {
return patch - o.patch;
}
}

@Override
public String toString() {
return String.format("%d.%d.%d", major, minor, patch);
}
}
}
90 changes: 90 additions & 0 deletions src/test/java/net/snowflake/client/TestSinceConditionRuleTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package net.snowflake.client;

import junit.framework.TestCase;
import org.junit.AfterClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
import org.mockito.Mockito;

import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItem;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.Mockito.mock;

@RunWith(Parameterized.class)
@SfTest(sinceVersion = "5.6.7")
public class TestSinceConditionRuleTest {
private static final Statement normalRun = mock(Statement.class);
private static final Statement ignoreRun = mock(Statement.class);

@Rule
public final TestSinceConditionRule testSinceConditionRule = new TestSinceConditionRule(TestSinceConditionRule.Version.parse("2.3.4"));

@Rule
public final TestWatcher testWatcher = new TestWatcher() {
@Override
protected void succeeded(Description description) {
succeededTests.add(description.getMethodName());
}
};

private static List<String> succeededTests = new ArrayList<>();

@AfterClass
public static void afterAll() {
assertThat(succeededTests, hasItem("testDecidingIfTestShouldBeRun[0]"));
}

@Parameterized.Parameters
public static Object[][] parameters() {
return new Object[][]{
{TestSinceConditionRule.Version.parse("1.2.3"), true, normalRun},
{TestSinceConditionRule.Version.parse("2.3.3"), true, normalRun},
{TestSinceConditionRule.Version.parse("2.3.3"), true, normalRun},
{TestSinceConditionRule.Version.parse("2.3.4"), false, normalRun},
{TestSinceConditionRule.Version.parse("2.3.4"), true, ignoreRun},
{TestSinceConditionRule.Version.parse("2.3.5"), true, ignoreRun},
{TestSinceConditionRule.Version.parse("2.3.5"), false, ignoreRun},
{TestSinceConditionRule.Version.parse("3.0.0"), true, ignoreRun},
{TestSinceConditionRule.Version.parse("3.0.0"), false, ignoreRun},
};
}

private final TestSinceConditionRule.Version version;
private final boolean oldDriverTest;
private final Statement result;

public TestSinceConditionRuleTest(TestSinceConditionRule.Version version, boolean oldDriverTest, Statement result) {
this.version = version;
this.oldDriverTest = oldDriverTest;
this.result = result;
}

@Test
@SfTest(sinceVersion = "1.0.0")
public void testDecidingIfTestShouldBeRun() {
assertEquals(result, testSinceConditionRule.decideIfShouldBeRun(normalRun, ignoreRun, version, oldDriverTest));
}

@SfTest(sinceVersion = "1000.1000.1000")
@Test
public void testShouldNeverStart() {
throw new AssertionError("should never start this test");
}

@Test
public void testShouldNeverStartBecauseClassVersionIsTooHigh() {
throw new AssertionError("should never start this test");
}
}
1 change: 1 addition & 0 deletions src/test/java/net/snowflake/client/jdbc/ConnectionIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import net.snowflake.client.ConditionalIgnoreRule.ConditionalIgnore;
import net.snowflake.client.RunningNotOnTestaccount;
import net.snowflake.client.RunningOnGithubAction;
import net.snowflake.client.SfTest;
import net.snowflake.client.TestUtil;
import net.snowflake.client.category.TestCategoryConnection;
import net.snowflake.client.core.SFSession;
Expand Down

0 comments on commit bf77118

Please sign in to comment.