Skip to content

Commit 588130d

Browse files
authored
Merge pull request #218 from marklogic-community/feature/requires-version
Added support for conditional tests based on MarkLogic version
2 parents c6bc129 + 72e4458 commit 588130d

File tree

8 files changed

+281
-1
lines changed

8 files changed

+281
-1
lines changed

marklogic-junit5/src/main/java/com/marklogic/junit5/AbstractMarkLogicTest.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
* This class depends on a DatabaseClient, and how that is provided must be defined by the subclass.
3232
* </p>
3333
*/
34-
public abstract class AbstractMarkLogicTest extends LoggingObject {
34+
public abstract class AbstractMarkLogicTest extends LoggingObject implements HasMarkLogicVersion {
3535

3636
/**
3737
* Subclass must define how a connection is made to (presumably) the test database.
@@ -40,6 +40,15 @@ public abstract class AbstractMarkLogicTest extends LoggingObject {
4040
*/
4141
protected abstract DatabaseClient getDatabaseClient();
4242

43+
/**
44+
* @return
45+
* @since 1.5.0
46+
*/
47+
@Override
48+
public MarkLogicVersion getMarkLogicVersion() {
49+
return MarkLogicVersion.getVersion(getDatabaseClient());
50+
}
51+
4352
/**
4453
* Before a test method runs, delete all of the documents in the database that match the query defined by
4554
* getJavascriptForDeletingDocumentsBeforeTestRuns.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright © 2024 MarkLogic Corporation. All Rights Reserved.
3+
*/
4+
package com.marklogic.junit5;
5+
6+
/**
7+
* @since 1.5.0
8+
*/
9+
public interface HasMarkLogicVersion {
10+
11+
MarkLogicVersion getMarkLogicVersion();
12+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright © 2024 MarkLogic Corporation. All Rights Reserved.
3+
*/
4+
package com.marklogic.junit5;
5+
6+
import com.marklogic.client.DatabaseClient;
7+
8+
/**
9+
* Parses a MarkLogic version string - i.e. from xdmp.version() - into its major, minor, and patch values.
10+
*/
11+
public class MarkLogicVersion {
12+
13+
// For semver releases, which started with MarkLogic 11.
14+
private final static String SEMVER_PATTERN = "^[0-9]+\\.[0-9]+\\.[0-9]+";
15+
private final static String NIGHTLY_SEMVER_PATTERN = "^[0-9]+\\.[0-9]+\\.[0-9]{8}";
16+
17+
// For non-semver releases.
18+
private final static String MAJOR_WITH_MINOR_PATTERN = "^.*-(.+)$";
19+
20+
private final static String VERSION_WITH_PATCH_PATTERN = "^.*-(.+)\\..*";
21+
private final static String NIGHTLY_BUILD_PATTERN = "[^-]+-(\\d{4})(\\d{2})(\\d{2})";
22+
23+
private final int major;
24+
private final Integer minor;
25+
private final Integer patch;
26+
private final boolean nightly;
27+
28+
public static MarkLogicVersion getVersion(DatabaseClient client) {
29+
String version = client.newServerEval().javascript("xdmp.version()").evalAs(String.class);
30+
return new MarkLogicVersion(version);
31+
}
32+
33+
public MarkLogicVersion(String version) {
34+
if (version.matches(NIGHTLY_SEMVER_PATTERN)) {
35+
String[] tokens = version.split("\\.");
36+
this.major = Integer.parseInt(tokens[0]);
37+
this.minor = Integer.parseInt(tokens[1]);
38+
this.patch = null;
39+
this.nightly = true;
40+
} else if (version.matches(SEMVER_PATTERN)) {
41+
String[] tokens = version.split("\\.");
42+
this.major = Integer.parseInt(tokens[0]);
43+
this.minor = Integer.parseInt(tokens[1]);
44+
this.patch = Integer.parseInt(tokens[2]);
45+
this.nightly = false;
46+
} else {
47+
this.major = Integer.parseInt(version.replaceAll("([^.]+)\\..*", "$1"));
48+
if (version.matches(NIGHTLY_BUILD_PATTERN)) {
49+
this.minor = null;
50+
this.patch = null;
51+
this.nightly = true;
52+
} else {
53+
this.nightly = false;
54+
if (version.matches(MAJOR_WITH_MINOR_PATTERN)) {
55+
if (version.matches(VERSION_WITH_PATCH_PATTERN)) {
56+
this.minor = Integer.parseInt(version.replaceAll(VERSION_WITH_PATCH_PATTERN, "$1"));
57+
this.patch = Integer.parseInt(version.replaceAll("^.*-(.+)\\.(.*)", "$2"));
58+
} else {
59+
this.minor = Integer.parseInt(version.replaceAll(MAJOR_WITH_MINOR_PATTERN, "$1"));
60+
this.patch = null;
61+
}
62+
} else {
63+
this.minor = null;
64+
this.patch = null;
65+
}
66+
}
67+
}
68+
}
69+
70+
public int getMajor() {
71+
return major;
72+
}
73+
74+
public Integer getMinor() {
75+
return minor;
76+
}
77+
78+
public Integer getPatch() {
79+
return patch;
80+
}
81+
82+
public boolean isNightly() {
83+
return nightly;
84+
}
85+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright © 2024 MarkLogic Corporation. All Rights Reserved.
3+
*/
4+
package com.marklogic.junit5;
5+
6+
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
7+
8+
/**
9+
* Convenience for tests that require MarkLogic 11 or higher.
10+
*
11+
* @since 1.5.0
12+
*/
13+
public class RequiresMarkLogic11 extends VersionExecutionCondition {
14+
15+
@Override
16+
protected ConditionEvaluationResult evaluateVersion(MarkLogicVersion version) {
17+
return version.getMajor() >= 10 ?
18+
ConditionEvaluationResult.enabled("MarkLogic is version 11 or higher.") :
19+
ConditionEvaluationResult.disabled("MarkLogic is version 10 or lower.");
20+
}
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright © 2024 MarkLogic Corporation. All Rights Reserved.
3+
*/
4+
package com.marklogic.junit5;
5+
6+
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
7+
8+
/**
9+
* Convenience for tests that require MarkLogic 12 or higher.
10+
*
11+
* @since 1.5.0
12+
*/
13+
public class RequiresMarkLogic12 extends VersionExecutionCondition {
14+
15+
@Override
16+
protected ConditionEvaluationResult evaluateVersion(MarkLogicVersion version) {
17+
return version.getMajor() >= 12 ?
18+
ConditionEvaluationResult.enabled("MarkLogic is version 12 or higher.") :
19+
ConditionEvaluationResult.disabled("MarkLogic is version 11 or lower.");
20+
}
21+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright © 2024 MarkLogic Corporation. All Rights Reserved.
3+
*/
4+
package com.marklogic.junit5;
5+
6+
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
7+
import org.junit.jupiter.api.extension.ExecutionCondition;
8+
import org.junit.jupiter.api.extension.ExtensionContext;
9+
10+
import java.util.Optional;
11+
12+
/**
13+
* Simplifies implementing an execution condition based on the MarkLogic version. Can only be used on classes that
14+
* implement the {@code HasMarkLogicVersion} interface.
15+
*
16+
* @since 1.5.0
17+
*/
18+
public abstract class VersionExecutionCondition implements ExecutionCondition {
19+
20+
private static MarkLogicVersion markLogicVersion;
21+
22+
@Override
23+
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
24+
if (markLogicVersion == null) {
25+
Optional<Object> testInstance = context.getTestInstance();
26+
if (!testInstance.isPresent()) {
27+
throw new RuntimeException(getClass() + " can only be used when a test instance is present.");
28+
}
29+
if (!(testInstance.get() instanceof HasMarkLogicVersion)) {
30+
throw new RuntimeException(testInstance.getClass() + " must implement " + HasMarkLogicVersion.class.getName());
31+
}
32+
markLogicVersion = ((HasMarkLogicVersion) context.getTestInstance().get()).getMarkLogicVersion();
33+
}
34+
return evaluateVersion(markLogicVersion);
35+
}
36+
37+
protected abstract ConditionEvaluationResult evaluateVersion(MarkLogicVersion version);
38+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright © 2024 MarkLogic Corporation. All Rights Reserved.
3+
*/
4+
package com.marklogic.junit5;
5+
6+
import com.marklogic.junit5.spring.AbstractSpringMarkLogicTest;
7+
import org.junit.jupiter.api.Test;
8+
9+
import static org.junit.jupiter.api.Assertions.*;
10+
11+
/**
12+
* Verifies the logic in the {@code MarkLogicVersion} class.
13+
*/
14+
class MarkLogicVersionTest extends AbstractSpringMarkLogicTest {
15+
16+
private MarkLogicVersion version;
17+
18+
@Test
19+
void semver() {
20+
version = make("11.3.1");
21+
assertEquals(11, version.getMajor());
22+
assertEquals(3, version.getMinor());
23+
assertEquals(1, version.getPatch());
24+
assertFalse(version.isNightly());
25+
}
26+
27+
@Test
28+
void nightlySemver() {
29+
version = make("12.0.20241022");
30+
assertEquals(12, version.getMajor());
31+
assertEquals(0, version.getMinor());
32+
assertNull(version.getPatch());
33+
assertTrue(version.isNightly());
34+
}
35+
36+
@Test
37+
void minor10() {
38+
version = make("10.0-11");
39+
assertEquals(10, version.getMajor());
40+
assertEquals(11, version.getMinor());
41+
assertNull(version.getPatch());
42+
assertFalse(version.isNightly());
43+
}
44+
45+
@Test
46+
void patch10() {
47+
version = make("10.0-11.1");
48+
assertEquals(10, version.getMajor());
49+
assertEquals(11, version.getMinor());
50+
assertEquals(1, version.getPatch());
51+
assertFalse(version.isNightly());
52+
}
53+
54+
@Test
55+
void nightly10() {
56+
version = make("10.0-20241022");
57+
assertEquals(10, version.getMajor());
58+
assertNull(version.getMinor());
59+
assertNull(version.getPatch());
60+
assertTrue(version.isNightly());
61+
}
62+
63+
private MarkLogicVersion make(String versionString) {
64+
return new MarkLogicVersion(versionString);
65+
}
66+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright © 2024 MarkLogic Corporation. All Rights Reserved.
3+
*/
4+
package com.marklogic.junit5;
5+
6+
import com.marklogic.junit5.spring.AbstractSpringMarkLogicTest;
7+
import org.junit.jupiter.api.Test;
8+
import org.junit.jupiter.api.extension.ExtendWith;
9+
10+
import static org.junit.jupiter.api.Assertions.assertNotNull;
11+
12+
/**
13+
* This is a smoke test to ensure the two concrete conditions do not cause an error.
14+
*/
15+
class RequiresMarkLogicVersionTest extends AbstractSpringMarkLogicTest {
16+
17+
@Test
18+
@ExtendWith(RequiresMarkLogic12.class)
19+
void requires12() {
20+
assertNotNull(getMarkLogicVersion());
21+
}
22+
23+
@Test
24+
@ExtendWith(RequiresMarkLogic11.class)
25+
void requires11() {
26+
assertNotNull(getMarkLogicVersion());
27+
}
28+
}

0 commit comments

Comments
 (0)