[jsemver] 44/95: Create SemVer Expression parser
Alexandre Viau
reazem-guest at moszumanska.debian.org
Mon Feb 16 14:58:29 UTC 2015
This is an automated email from the git hooks/post-receive script.
reazem-guest pushed a commit to branch master
in repository jsemver.
commit 388f94915f928b97fdefb2e6f8d4749bb4504585
Author: Zafar Khaja <zafarkhaja at gmail.com>
Date: Sun Nov 10 23:47:51 2013 +0400
Create SemVer Expression parser
---
README.md | 90 ++++++---
.../java/com/github/zafarkhaja/semver/Version.java | 19 ++
.../zafarkhaja/semver/expr/ExpressionParser.java | 222 +++++++++++++++++++++
.../com/github/zafarkhaja/semver/VersionTest.java | 7 +
.../semver/expr/ExpressionParserTest.java | 205 +++++++++++++++++++
5 files changed, 516 insertions(+), 27 deletions(-)
diff --git a/README.md b/README.md
index 38b9cbc..e5a1251 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,10 @@
Java SemVer v0.7.0 (SemVer 2) [](https://travis-ci.org/zafarkhaja/java-semver)
-==================
+=============================
Java SemVer is a Java implementation of the Semantic Versioning Specification
(http://semver.org/).
-
-Versioning
-----------
+### Versioning ###
Java SemVer is versioned according to the SemVer Specification.
**NOTE**: The current release of the Java SemVer library has a major version of
@@ -19,13 +17,13 @@ Usage
Below are some common use cases for the Java SemVer library.
### Creating Versions ###
-Java SemVer library is composed of one small package which contains a few
-classes. All the classes but one are package-private and are not accessible
-outside the package. The only public class is `Version` which acts as a
-_facade_ for the client code. By design, the `Version` class is made immutable
-by making its constructor package-private, so that it can not be subclassed or
-directly instantiated. Instead of public constructor, the `Version` class
-provides a _static factory method_, `Version.valueOf(String value)`.
+The main class of the Java SemVer library is `Version` which implements the
+Facade design pattern. By design, the `Version` class is made immutable by
+making its constructors package-private, so that it can not be subclassed or
+directly instantiated. Instead of public constructors, the `Version` class
+provides few _static factory methods_.
+
+One of the methods is the `Version.valueOf` method.
```java
import com.github.zafarkhaja.semver.Version;
@@ -43,6 +41,17 @@ String build = v.getBuildMetadata(); // "build.1"
String str = v.toString(); // "1.0.0-rc.1+build.1"
```
+The other static factory method is `Version.forIntegers` which is also
+overloaded to allow fewer arguments.
+
+```java
+import com.github.zafarkhaja.semver.Version;
+
+Version v1 = Version.forIntegers(1);
+Version v2 = Version.forIntegers(1, 2);
+Version v3 = Version.forIntegers(1, 2, 3);
+```
+
Another way to create a `Version` is to use a _builder_ class `Version.Builder`.
```java
@@ -76,15 +85,15 @@ import com.github.zafarkhaja.semver.Version;
Version v1 = Version.valueOf("1.2.3");
-// Incrementing major version
+// Incrementing the major version
Version v2 = v1.incrementMajorVersion(); // "2.0.0"
Version v2 = v1.incrementMajorVersion("alpha"); // "2.0.0-alpha"
-// Incrementing minor version
+// Incrementing the minor version
Version v3 = v1.incrementMinorVersion(); // "1.3.0"
Version v3 = v1.incrementMinorVersion("alpha"); // "1.3.0-alpha"
-// Incrementing patch version
+// Incrementing the patch version
Version v4 = v1.incrementPatchVersion(); // "1.2.4"
Version v4 = v1.incrementPatchVersion("alpha"); // "1.2.4-alpha"
@@ -92,30 +101,32 @@ Version v4 = v1.incrementPatchVersion("alpha"); // "1.2.4-alpha"
String str = v1.toString(); // "1.2.3"
```
-There are also incrementor methods for pre-release version and build metadata.
+There are also incrementor methods for the pre-release version and the build
+metadata.
```java
import com.github.zafarkhaja.semver.Version;
-// Incrementing pre-release version
+// Incrementing the pre-release version
Version v1 = Version.valueOf("1.2.3-rc"); // considered as "rc.0"
Version v2 = v1.incrementPreReleaseVersion(); // "1.2.3-rc.1"
Version v3 = v2.incrementPreReleaseVersion(); // "1.2.3-rc.2"
-// Incrementing build metadata
+// Incrementing the build metadata
Version v1 = Version.valueOf("1.2.3-rc+build"); // considered as "build.0"
Version v2 = v1.incrementBuildMetadata(); // "1.2.3-rc+build.1"
Version v3 = v2.incrementBuildMetadata(); // "1.2.3-rc+build.2"
```
-When incrementing normal or pre-release versions build metadata is always dropped.
+When incrementing the normal or pre-release versions the build metadata is
+always dropped.
```java
import com.github.zafarkhaja.semver.Version;
Version v1 = Version.valueOf("1.2.3-beta+build");
-// Incrementing normal version
+// Incrementing the normal version
Version v2 = v1.incrementMajorVersion(); // "2.0.0"
Version v2 = v1.incrementMajorVersion("alpha"); // "2.0.0-alpha"
@@ -125,7 +136,7 @@ Version v3 = v1.incrementMinorVersion("alpha"); // "1.3.0-alpha"
Version v4 = v1.incrementPatchVersion(); // "1.2.4"
Version v4 = v1.incrementPatchVersion("alpha"); // "1.2.4-alpha"
-// Incrementing pre-release version
+// Incrementing the pre-release version
Version v2 = v1.incrementPreReleaseVersion(); // "1.2.3-beta.1"
```
**NOTE**: The discussion page https://github.com/mojombo/semver/issues/60 might
@@ -134,8 +145,8 @@ incrementor methods.
### Comparing Versions ###
Comparing versions with Java SemVer is easy. The `Version` class implements the
-`Comparable` interface, it also overrides the `Object.equals(Object obj)` method
-and provides some more methods for convenient comparing.
+`Comparable` interface, it also overrides the `Object.equals` method and provides
+some more methods for convenient comparing.
```java
import com.github.zafarkhaja.semver.Version;
@@ -152,7 +163,7 @@ boolean result = v1.lessThan(v2); // true
boolean result = v1.lessThanOrEqualTo(v2); // true
```
-When determining version precedence build metadata is ignored (SemVer p.10).
+When determining version precedence the build metadata is ignored (SemVer p.10).
```java
import com.github.zafarkhaja.semver.Version;
@@ -164,9 +175,9 @@ int result = v1.compareTo(v2); // = 0
boolean result = v1.equals(v2); // true
```
-Sometimes, however, you might want to compare versions with build metadata in
-mind. For such cases Java SemVer provides a _comparator_ `Version.BUILD_AWARE_ORDER`
-and a convenience method `Version.compareWithBuildsTo(Version other)`.
+Sometimes, however, you might want to compare versions with the build metadata
+in mind. For such cases Java SemVer provides a _comparator_ `Version.BUILD_AWARE_ORDER`
+and a convenience method `Version.compareWithBuildsTo`.
```java
import com.github.zafarkhaja.semver.Version;
@@ -181,9 +192,34 @@ boolean result = v1.equals(v2); // false
```
+SemVer Expressions API (Ranges)
+----------------------
+Since version 0.7.0 Java SemVer supports the SemVer Expressions API which is
+implemented as an external DSL. The BNF grammar for the SemVer Expressions DSL
+can be found in the corresponding issue
+"[Implement the SemVer Expressions API](https://github.com/zafarkhaja/java-semver/issues/1)".
+
+The entry point for the API is the `Version.satisfies` method.
+
+```java
+import com.github.zafarkhaja.semver.Version;
+
+Version v = Version.valueOf("1.0.0-beta");
+boolean result = v.satisfies(">=1.0.0 & <2.0.0"); // false
+```
+
+Below are examples of some common use cases, as well as syntactic sugar and some
+other interesting capabilities of the SemVer Expressions DSL.
+* Wildcard - `1.*` which is equivalent to `>=1.0.0 & <2.0.0`
+* Tilde operator - `~1.5` which is equivalent to `>=1.5.0 & <2.0.0`
+* Range - `1.0-2.0` which is equivalent to `>=1.0.0 & <=2.0.0`
+* Negation operator - `!(1.*)` which is equivalent to `<1.0.0 & >=2.0.0`
+* Short notation - `1` which is equivalent to `=1.0.0`
+* Parenthesized expression - `~1.3 | (1.4.* & !=1.4.5) | ~2`
+
+
TODO
----
-* [Implement ranges](https://github.com/zafarkhaja/java-semver/issues/1)
* [Write doc comments for all API classes and methods](https://github.com/zafarkhaja/java-semver/issues/2)
diff --git a/src/main/java/com/github/zafarkhaja/semver/Version.java b/src/main/java/com/github/zafarkhaja/semver/Version.java
index 40e1839..30a2db1 100644
--- a/src/main/java/com/github/zafarkhaja/semver/Version.java
+++ b/src/main/java/com/github/zafarkhaja/semver/Version.java
@@ -23,6 +23,8 @@
*/
package com.github.zafarkhaja.semver;
+import com.github.zafarkhaja.semver.expr.Expression;
+import com.github.zafarkhaja.semver.expr.ExpressionParser;
import java.util.Comparator;
/**
@@ -116,6 +118,23 @@ public class Version implements Comparable<Version> {
return VersionParser.parseValidSemVer(version);
}
+ public static Version forIntegers(int major) {
+ return new Version(new NormalVersion(major, 0, 0));
+ }
+
+ public static Version forIntegers(int major, int minor) {
+ return new Version(new NormalVersion(major, minor, 0));
+ }
+
+ public static Version forIntegers(int major, int minor, int patch) {
+ return new Version(new NormalVersion(major, minor, patch));
+ }
+
+ public boolean satisfies(String expr) {
+ Parser<Expression> parser = ExpressionParser.newInstance();
+ return parser.parse(expr).interpret(this);
+ }
+
public Version incrementMajorVersion() {
return new Version(normal.incrementMajor());
}
diff --git a/src/main/java/com/github/zafarkhaja/semver/expr/ExpressionParser.java b/src/main/java/com/github/zafarkhaja/semver/expr/ExpressionParser.java
new file mode 100644
index 0000000..e403bb2
--- /dev/null
+++ b/src/main/java/com/github/zafarkhaja/semver/expr/ExpressionParser.java
@@ -0,0 +1,222 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2013 Zafar Khaja <zafarkhaja at gmail.com>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.github.zafarkhaja.semver.expr;
+
+import com.github.zafarkhaja.semver.Parser;
+import com.github.zafarkhaja.semver.Version;
+import com.github.zafarkhaja.semver.expr.Lexer.Token;
+import com.github.zafarkhaja.semver.util.Stream;
+import com.github.zafarkhaja.semver.util.Stream.ElementType;
+import java.util.EnumSet;
+import java.util.Iterator;
+import static com.github.zafarkhaja.semver.expr.Lexer.Token.Type.*;
+
+/**
+ *
+ * @author Zafar Khaja <zafarkhaja at gmail.com>
+ */
+public class ExpressionParser implements Parser<Expression> {
+
+ private final Lexer lexer;
+ private Stream<Token> tokens;
+
+ ExpressionParser(Lexer lexer) {
+ this.lexer = lexer;
+ }
+
+ public static Parser<Expression> newInstance() {
+ return new ExpressionParser(new Lexer());
+ }
+
+ @Override
+ public Expression parse(String input) {
+ tokens = lexer.tokenize(input);
+ return parseSemVerExpression();
+ }
+
+ private Expression parseSemVerExpression() {
+ Expression expr;
+ if (tokens.positiveLookahead(NOT)) {
+ tokens.consume();
+ tokens.consume(LEFT_PAREN);
+ expr = new Not(parseSemVerExpression());
+ tokens.consume(RIGHT_PAREN);
+ } else if (tokens.positiveLookahead(LEFT_PAREN)) {
+ tokens.consume(LEFT_PAREN);
+ expr = parseSemVerExpression();
+ tokens.consume(RIGHT_PAREN);
+ } else {
+ expr = parseExpression();
+ }
+ return parseBooleanExpression(expr);
+ }
+
+ private Expression parseBooleanExpression(Expression expr) {
+ if (tokens.positiveLookahead(AND)) {
+ tokens.consume();
+ expr = new And(expr, parseSemVerExpression());
+ } else if (tokens.positiveLookahead(OR)) {
+ tokens.consume();
+ expr = new Or(expr, parseSemVerExpression());
+ }
+ return expr;
+ }
+
+ private Expression parseExpression() {
+ if (tokens.positiveLookahead(TILDE)) {
+ return parseTildeExpression();
+ } else if (isVersionExpression()) {
+ return parseVersionExpression();
+ } else if (isRangeExpression()) {
+ return parseRangeExpression();
+ }
+ return parseComparisonExpression();
+ }
+
+ private Expression parseComparisonExpression() {
+ Token token = tokens.lookahead();
+ Expression expr;
+ switch (token.type) {
+ case EQUAL:
+ tokens.consume();
+ expr = new Equal(parseVersion());
+ break;
+ case NOT_EQUAL:
+ tokens.consume();
+ expr = new NotEqual(parseVersion());
+ break;
+ case GREATER:
+ tokens.consume();
+ expr = new Greater(parseVersion());
+ break;
+ case GREATER_EQUAL:
+ tokens.consume();
+ expr = new GreaterOrEqual(parseVersion());
+ break;
+ case LESS:
+ tokens.consume();
+ expr = new Less(parseVersion());
+ break;
+ case LESS_EQUAL:
+ tokens.consume();
+ expr = new LessOrEqual(parseVersion());
+ break;
+ default:
+ expr = new Equal(parseVersion());
+ }
+ return expr;
+ }
+
+ private Expression parseTildeExpression() {
+ tokens.consume(TILDE);
+ int major = intOf(tokens.consume(NUMERIC).lexeme);
+ if (!tokens.positiveLookahead(DOT)) {
+ return new GreaterOrEqual(versionOf(major, 0, 0));
+ }
+ tokens.consume(DOT);
+ int minor = intOf(tokens.consume(NUMERIC).lexeme);
+ if (!tokens.positiveLookahead(DOT)) {
+ return new And(
+ new GreaterOrEqual(versionOf(major, minor, 0)),
+ new Less(versionOf(major + 1, 0, 0))
+ );
+ }
+ tokens.consume(DOT);
+ int patch = intOf(tokens.consume(NUMERIC).lexeme);
+ return new And(
+ new GreaterOrEqual(versionOf(major, minor, patch)),
+ new Less(versionOf(major, minor + 1, 0))
+ );
+ }
+
+ private boolean isVersionExpression() {
+ return isVersionFollowedBy(STAR);
+ }
+
+ private Expression parseVersionExpression() {
+ int major = intOf(tokens.consume(NUMERIC).lexeme);
+ tokens.consume(DOT);
+ if (tokens.positiveLookahead(STAR)) {
+ tokens.consume();
+ return new And(
+ new GreaterOrEqual(versionOf(major, 0, 0)),
+ new Less(versionOf(major + 1, 0, 0))
+ );
+ }
+ int minor = intOf(tokens.consume(NUMERIC).lexeme);
+ tokens.consume(DOT);
+ tokens.consume(STAR);
+ return new And(
+ new GreaterOrEqual(versionOf(major, minor, 0)),
+ new Less(versionOf(major, minor + 1, 0))
+ );
+ }
+
+ private boolean isRangeExpression() {
+ return isVersionFollowedBy(HYPHEN);
+ }
+
+ private Expression parseRangeExpression() {
+ Expression ge = new GreaterOrEqual(parseVersion());
+ tokens.consume(HYPHEN);
+ Expression le = new LessOrEqual(parseVersion());
+ return new And(ge, le);
+ }
+
+ private Version parseVersion() {
+ int major = intOf(tokens.consume(NUMERIC).lexeme);
+ int minor = 0;
+ if (tokens.positiveLookahead(DOT)) {
+ tokens.consume();
+ minor = intOf(tokens.consume(NUMERIC).lexeme);
+ }
+ int patch = 0;
+ if (tokens.positiveLookahead(DOT)) {
+ tokens.consume();
+ patch = intOf(tokens.consume(NUMERIC).lexeme);
+ }
+ return versionOf(major, minor, patch);
+ }
+
+ private boolean isVersionFollowedBy(ElementType<Token> type) {
+ EnumSet<Token.Type> expected = EnumSet.of(NUMERIC, DOT);
+ Iterator<Token> it = tokens.iterator();
+ Token lookahead = null;
+ while (it.hasNext()) {
+ lookahead = it.next();
+ if (!expected.contains(lookahead.type)) {
+ break;
+ }
+ }
+ return type.isMatchedBy(lookahead);
+ }
+
+ private Version versionOf(int major, int minor, int patch) {
+ return Version.forIntegers(major, minor, patch);
+ }
+
+ private int intOf(String value) {
+ return Integer.parseInt(value);
+ }
+}
diff --git a/src/test/java/com/github/zafarkhaja/semver/VersionTest.java b/src/test/java/com/github/zafarkhaja/semver/VersionTest.java
index af65488..e993fa9 100644
--- a/src/test/java/com/github/zafarkhaja/semver/VersionTest.java
+++ b/src/test/java/com/github/zafarkhaja/semver/VersionTest.java
@@ -305,6 +305,13 @@ public class VersionTest {
assertTrue(0 == v1.compareTo(v2));
assertTrue(0 > v1.compareWithBuildsTo(v2));
}
+
+ @Test
+ public void shouldCheckIfVersionSatisfiesExpression() {
+ Version v = Version.valueOf("2.0.0-beta");
+ assertTrue(v.satisfies("~1.0"));
+ assertFalse(v.satisfies(">=2.0 & <3.0"));
+ }
}
public static class EqualsMethodTest {
diff --git a/src/test/java/com/github/zafarkhaja/semver/expr/ExpressionParserTest.java b/src/test/java/com/github/zafarkhaja/semver/expr/ExpressionParserTest.java
new file mode 100644
index 0000000..e8cdd65
--- /dev/null
+++ b/src/test/java/com/github/zafarkhaja/semver/expr/ExpressionParserTest.java
@@ -0,0 +1,205 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2013 Zafar Khaja <zafarkhaja at gmail.com>.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.github.zafarkhaja.semver.expr;
+
+import com.github.zafarkhaja.semver.Version;
+import com.github.zafarkhaja.semver.util.UnexpectedElementTypeException;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Zafar Khaja <zafarkhaja at gmail.com>
+ */
+public class ExpressionParserTest {
+
+ @Test
+ public void shouldParseEqualComparisonExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression eq = parser.parse("=1.0.0");
+ assertTrue(eq.interpret(Version.valueOf("1.0.0")));
+ }
+
+ @Test
+ public void shouldParseEqualComparisonExpressionIfOnlyVersionGiven() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression eq = parser.parse("1.0.0");
+ assertTrue(eq.interpret(Version.valueOf("1.0.0")));
+ }
+
+ @Test
+ public void shouldParseNotEqualComparisonExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression ne = parser.parse("!=1.0.0");
+ assertTrue(ne.interpret(Version.valueOf("1.2.3")));
+ }
+
+ @Test
+ public void shouldParseGreaterComparisonExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression gt = parser.parse(">1.0.0");
+ assertTrue(gt.interpret(Version.valueOf("1.2.3")));
+ }
+
+ @Test
+ public void shouldParseGreaterOrEqualComparisonExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression ge = parser.parse(">=1.0.0");
+ assertTrue(ge.interpret(Version.valueOf("1.0.0")));
+ assertTrue(ge.interpret(Version.valueOf("1.2.3")));
+ }
+
+ @Test
+ public void shouldParseLessComparisonExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression lt = parser.parse("<1.2.3");
+ assertTrue(lt.interpret(Version.valueOf("1.0.0")));
+ }
+
+ @Test
+ public void shouldParseLessOrEqualComparisonExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression le = parser.parse("<=1.2.3");
+ assertTrue(le.interpret(Version.valueOf("1.0.0")));
+ assertTrue(le.interpret(Version.valueOf("1.2.3")));
+ }
+
+ @Test
+ public void shouldParseTildeExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression expr1 = parser.parse("~1");
+ assertTrue(expr1.interpret(Version.valueOf("1.2.3")));
+ assertTrue(expr1.interpret(Version.valueOf("3.2.1")));
+ Expression expr2 = parser.parse("~1.2");
+ assertTrue(expr2.interpret(Version.valueOf("1.2.3")));
+ assertFalse(expr2.interpret(Version.valueOf("2.0.0")));
+ Expression expr3 = parser.parse("~1.2.3");
+ assertTrue(expr3.interpret(Version.valueOf("1.2.3")));
+ assertFalse(expr3.interpret(Version.valueOf("1.3.0")));
+ }
+
+ @Test
+ public void shouldParseShortFormOfVersion() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression expr1 = parser.parse("1");
+ assertTrue(expr1.interpret(Version.valueOf("1.0.0")));
+ Expression expr2 = parser.parse("2.0");
+ assertTrue(expr2.interpret(Version.valueOf("2.0.0")));
+ }
+
+ @Test
+ public void shouldParseVersionExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression expr1 = parser.parse("1.*");
+ assertTrue(expr1.interpret(Version.valueOf("1.2.3")));
+ assertFalse(expr1.interpret(Version.valueOf("3.2.1")));
+ Expression expr2 = parser.parse("1.2.*");
+ assertTrue(expr2.interpret(Version.valueOf("1.2.3")));
+ assertFalse(expr2.interpret(Version.valueOf("1.3.2")));
+ }
+
+ @Test
+ public void shouldParseRangeExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression range = parser.parse("1.0.0 - 2.0.0");
+ assertTrue(range.interpret(Version.valueOf("1.2.3")));
+ assertFalse(range.interpret(Version.valueOf("3.2.1")));
+ }
+
+ @Test
+ public void shouldParseAndBooleanExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression and = parser.parse(">=1.0.0 & <2.0.0");
+ assertTrue(and.interpret(Version.valueOf("1.2.3")));
+ assertFalse(and.interpret(Version.valueOf("3.2.1")));
+ }
+
+ @Test
+ public void shouldParseOrBooleanExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression or = parser.parse("1.* | =2.0.0");
+ assertTrue(or.interpret(Version.valueOf("1.2.3")));
+ assertFalse(or.interpret(Version.valueOf("2.1.0")));
+ }
+
+ @Test
+ public void shouldParseParenthesizedExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression expr = parser.parse("(1)");
+ assertTrue(expr.interpret(Version.valueOf("1.0.0")));
+ assertFalse(expr.interpret(Version.valueOf("2.0.0")));
+ }
+
+ @Test
+ public void shouldParseExpressionWithMultipleParentheses() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression expr = parser.parse("((1))");
+ assertTrue(expr.interpret(Version.valueOf("1.0.0")));
+ assertFalse(expr.interpret(Version.valueOf("2.0.0")));
+ }
+
+ @Test
+ public void shouldParseNotExpression() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression not1 = parser.parse("!(1)");
+ assertTrue(not1.interpret(Version.valueOf("2.0.0")));
+ assertFalse(not1.interpret(Version.valueOf("1.0.0")));
+ Expression not2 = parser.parse("0.* & !(>=1 & <2)");
+ assertTrue(not2.interpret(Version.valueOf("0.5.0")));
+ assertFalse(not2.interpret(Version.valueOf("1.0.1")));
+ Expression not3 = parser.parse("!(>=1 & <2) & >=2");
+ assertTrue(not3.interpret(Version.valueOf("2.0.0")));
+ assertFalse(not3.interpret(Version.valueOf("1.2.3")));
+ }
+
+ @Test
+ public void shouldRespectPrecedenceWhenUsedWithParentheses() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression expr1 = parser.parse("(~1.0 & <2.0) | >2.0");
+ assertTrue(expr1.interpret(Version.valueOf("2.5.0")));
+ Expression expr2 = parser.parse("~1.0 & (<2.0 | >2.0)");
+ assertFalse(expr2.interpret(Version.valueOf("2.5.0")));
+ }
+
+ @Test
+ public void shouldParseComplexExpressions() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ Expression expr = parser.parse(
+ "((>=1.0.1 & <2) | (>=3.0 & <4)) & ((1-1.5) & (~1.5))"
+ );
+ assertTrue(expr.interpret(Version.valueOf("1.5.0")));
+ assertFalse(expr.interpret(Version.valueOf("2.5.0")));
+ }
+
+ @Test
+ public void shouldRaiseErrorIfClosingParenthesisIsMissing() {
+ ExpressionParser parser = new ExpressionParser(new Lexer());
+ try {
+ parser.parse("((>=1.0.1 & < 2)");
+ } catch (UnexpectedElementTypeException e) {
+ return;
+ }
+ fail("Should raise error if closing parenthesis is missing");
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jsemver.git
More information about the pkg-java-commits
mailing list