[jsemver] 40/95: Implement a Parser instead of RegExp
Alexandre Viau
reazem-guest at moszumanska.debian.org
Mon Feb 16 14:58:28 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 78266dc1ca42ebd3324d1cf5ce9a141728f5c095
Author: Zafar Khaja <zafarkhaja at gmail.com>
Date: Mon Oct 14 22:46:46 2013 +0400
Implement a Parser instead of RegExp
This commit also updates the code to comply with the SemVer 2.0.0.
---
README.md | 7 +-
.../github/zafarkhaja/semver/GrammarException.java | 35 +++
.../github/zafarkhaja/semver/MetadataVersion.java | 54 ++--
.../github/zafarkhaja/semver/NormalVersion.java | 18 --
.../java/com/github/zafarkhaja/semver/Parser.java | 32 +++
.../github/zafarkhaja/semver/ParserException.java | 39 +++
.../semver/UnexpectedCharacterException.java | 51 ++++
.../java/com/github/zafarkhaja/semver/Version.java | 81 ++----
.../github/zafarkhaja/semver/VersionParser.java | 309 +++++++++++++++++++++
.../zafarkhaja/semver/MetadataVersionTest.java | 127 +++++----
.../zafarkhaja/semver/NormalVersionTest.java | 12 +-
.../semver/VersionParserCharStreamTest.java | 118 ++++++++
.../zafarkhaja/semver/VersionParserCharTest.java | 84 ++++++
.../zafarkhaja/semver/VersionParserTest.java | 115 ++++++++
.../com/github/zafarkhaja/semver/VersionTest.java | 13 +-
15 files changed, 919 insertions(+), 176 deletions(-)
diff --git a/README.md b/README.md
index 36242ab..38b9cbc 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,9 @@
-Java SemVer v0.7.0 [![Build Status](https://travis-ci.org/zafarkhaja/java-semver.png)](https://travis-ci.org/zafarkhaja/java-semver)
+Java SemVer v0.7.0 (SemVer 2) [![Build Status](https://travis-ci.org/zafarkhaja/java-semver.png)](https://travis-ci.org/zafarkhaja/java-semver)
==================
Java SemVer is a Java implementation of the Semantic Versioning Specification
(http://semver.org/).
-**NOTE**: The current version of the Java SemVer corresponds to the Semantic
-Versioning 2.0.0-rc.2.
-
Versioning
----------
@@ -132,7 +129,7 @@ Version v4 = v1.incrementPatchVersion("alpha"); // "1.2.4-alpha"
Version v2 = v1.incrementPreReleaseVersion(); // "1.2.3-beta.1"
```
**NOTE**: The discussion page https://github.com/mojombo/semver/issues/60 might
-be of good use in better understanding some of the decisions made regarding the
+be of good use in better understanding some of the decisions made regarding the
incrementor methods.
### Comparing Versions ###
diff --git a/src/main/java/com/github/zafarkhaja/semver/GrammarException.java b/src/main/java/com/github/zafarkhaja/semver/GrammarException.java
new file mode 100644
index 0000000..93ca594
--- /dev/null
+++ b/src/main/java/com/github/zafarkhaja/semver/GrammarException.java
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Zafar Khaja <zafarkhaja at gmail.com>
+ */
+public class GrammarException extends ParserException {
+
+ GrammarException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/github/zafarkhaja/semver/MetadataVersion.java b/src/main/java/com/github/zafarkhaja/semver/MetadataVersion.java
index f6f9d30..83b46ab 100644
--- a/src/main/java/com/github/zafarkhaja/semver/MetadataVersion.java
+++ b/src/main/java/com/github/zafarkhaja/semver/MetadataVersion.java
@@ -24,8 +24,6 @@
package com.github.zafarkhaja.semver;
import java.util.Arrays;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/**
*
@@ -33,27 +31,14 @@ import java.util.regex.Pattern;
*/
class MetadataVersion implements Comparable<MetadataVersion> {
- private final String value;
+ private final String[] idents;
- static final String FORMAT = "([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)";
- private static final Pattern PATTERN = Pattern.compile("^" + FORMAT + "$");
-
- MetadataVersion(String value) {
- if (value == null) {
- throw new NullPointerException("Metadata version MUST NOT be NULL");
- }
- Matcher matcher = PATTERN.matcher(value);
- if (!matcher.matches()) {
- throw new IllegalArgumentException(
- "Metadata version MUST consist of dot separated identifiers [0-9A-Za-z-]"
- );
- }
- this.value = matcher.group(0);
+ MetadataVersion(String[] identifiers) {
+ idents = identifiers;
}
MetadataVersion increment() {
- String[] ids = value.split("\\.");
-
+ String[] ids = idents;
String lastId = ids[ids.length - 1];
if (isInt(lastId)) {
int intId = Integer.parseInt(lastId);
@@ -62,7 +47,7 @@ class MetadataVersion implements Comparable<MetadataVersion> {
ids = Arrays.copyOf(ids, ids.length + 1);
ids[ids.length - 1] = String.valueOf(1);
}
- return new MetadataVersion(joinIdentifiers(ids));
+ return new MetadataVersion(ids);
}
@Override
@@ -78,31 +63,32 @@ class MetadataVersion implements Comparable<MetadataVersion> {
@Override
public int hashCode() {
- return value.hashCode();
+ return Arrays.hashCode(idents);
}
@Override
public String toString() {
- return value;
+ StringBuilder sb = new StringBuilder();
+ for (String id : idents) {
+ sb.append(id).append(".");
+ }
+ return sb.deleteCharAt(sb.lastIndexOf(".")).toString();
}
@Override
public int compareTo(MetadataVersion other) {
- String[] thisIds = value.split("\\.");
- String[] otherIds = other.value.split("\\.");
-
- int result = compareIdentifierArrays(thisIds, otherIds);
+ int result = compareIdentifierArrays(other.idents);
if (result == 0) {
- result = thisIds.length - otherIds.length;
+ result = idents.length - other.idents.length;
}
return result;
}
- private int compareIdentifierArrays(String[] ids1, String[] ids2) {
+ private int compareIdentifierArrays(String[] otherIdents) {
int result = 0;
- int length = getLeastCommonArrayLength(ids1, ids2);
+ int length = getLeastCommonArrayLength(idents, otherIdents);
for (int i = 0; i < length; i++) {
- result = compareIdentifiers(ids1[i], ids2[i]);
+ result = compareIdentifiers(idents[i], otherIdents[i]);
if (result != 0) {
break;
}
@@ -130,12 +116,4 @@ class MetadataVersion implements Comparable<MetadataVersion> {
}
return true;
}
-
- private String joinIdentifiers(String[] ids) {
- StringBuilder sb = new StringBuilder();
- for (String id : ids) {
- sb.append(id).append(".");
- }
- return sb.deleteCharAt(sb.lastIndexOf(".")).toString();
- }
}
diff --git a/src/main/java/com/github/zafarkhaja/semver/NormalVersion.java b/src/main/java/com/github/zafarkhaja/semver/NormalVersion.java
index 87a1510..7779b64 100644
--- a/src/main/java/com/github/zafarkhaja/semver/NormalVersion.java
+++ b/src/main/java/com/github/zafarkhaja/semver/NormalVersion.java
@@ -23,9 +23,6 @@
*/
package com.github.zafarkhaja.semver;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
/**
*
* @author Zafar Khaja <zafarkhaja at gmail.com>
@@ -36,9 +33,6 @@ class NormalVersion implements Comparable<NormalVersion> {
private final int minor;
private final int patch;
- static final String FORMAT = "(\\d+)\\.(\\d+)\\.(\\d+)";
- private static final Pattern PATTERN = Pattern.compile("^" + FORMAT + "$");
-
NormalVersion(int major, int minor, int patch) {
if (major < 0 || minor < 0 || patch < 0) {
throw new IllegalArgumentException(
@@ -50,18 +44,6 @@ class NormalVersion implements Comparable<NormalVersion> {
this.patch = patch;
}
- static NormalVersion valueOf(String value) {
- Matcher matcher = PATTERN.matcher(value);
- if (!matcher.matches()) {
- throw new IllegalArgumentException("Illegal normal version format");
- }
- return new NormalVersion(
- Integer.parseInt(matcher.group(1)),
- Integer.parseInt(matcher.group(2)),
- Integer.parseInt(matcher.group(3))
- );
- }
-
int getMajor() {
return major;
}
diff --git a/src/main/java/com/github/zafarkhaja/semver/Parser.java b/src/main/java/com/github/zafarkhaja/semver/Parser.java
new file mode 100644
index 0000000..32d7571
--- /dev/null
+++ b/src/main/java/com/github/zafarkhaja/semver/Parser.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Zafar Khaja <zafarkhaja at gmail.com>
+ */
+public interface Parser<T> {
+ T parse(String input);
+}
diff --git a/src/main/java/com/github/zafarkhaja/semver/ParserException.java b/src/main/java/com/github/zafarkhaja/semver/ParserException.java
new file mode 100644
index 0000000..469c060
--- /dev/null
+++ b/src/main/java/com/github/zafarkhaja/semver/ParserException.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+/**
+ *
+ * @author Zafar Khaja <zafarkhaja at gmail.com>
+ */
+public class ParserException extends RuntimeException {
+
+ ParserException(String message) {
+ super(message);
+ }
+
+ ParserException() {
+
+ }
+}
diff --git a/src/main/java/com/github/zafarkhaja/semver/UnexpectedCharacterException.java b/src/main/java/com/github/zafarkhaja/semver/UnexpectedCharacterException.java
new file mode 100644
index 0000000..f52fda0
--- /dev/null
+++ b/src/main/java/com/github/zafarkhaja/semver/UnexpectedCharacterException.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import com.github.zafarkhaja.semver.VersionParser.CharStream.CharType;
+import java.util.Arrays;
+
+/**
+ *
+ * @author Zafar Khaja <zafarkhaja at gmail.com>
+ */
+public class UnexpectedCharacterException extends ParserException {
+
+ private final char unexpected;
+ private final CharType[] expected;
+
+ UnexpectedCharacterException(char chr, CharType... expected) {
+ unexpected = chr;
+ this.expected = expected;
+ }
+
+ @Override
+ public String toString() {
+ String message = "Unexpected character '" + unexpected + "'";
+ if (expected.length > 0) {
+ message += ", expecting '" + Arrays.toString(expected) + "'";
+ }
+ return message;
+ }
+}
diff --git a/src/main/java/com/github/zafarkhaja/semver/Version.java b/src/main/java/com/github/zafarkhaja/semver/Version.java
index f18ad70..2970399 100644
--- a/src/main/java/com/github/zafarkhaja/semver/Version.java
+++ b/src/main/java/com/github/zafarkhaja/semver/Version.java
@@ -24,8 +24,6 @@
package com.github.zafarkhaja.semver;
import java.util.Comparator;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/**
*
@@ -40,64 +38,40 @@ public class Version implements Comparable<Version> {
private static final String PRE_RELEASE_PREFIX = "-";
private static final String BUILD_PREFIX = "+";
- private static final Pattern SEMVER_PATTERN;
-
- static {
- StringBuilder sb = new StringBuilder();
- sb.append("^")
- .append("(?<normal>")
- .append(NormalVersion.FORMAT)
- .append(")")
- .append("(?:")
- .append(PRE_RELEASE_PREFIX)
- .append("(?<preRelease>")
- .append(MetadataVersion.FORMAT)
- .append(")")
- .append(")?").append("(?:")
- .append("\\").append(BUILD_PREFIX)
- .append("(?<build>")
- .append(MetadataVersion.FORMAT)
- .append(")")
- .append(")?")
- .append("$");
-
- SEMVER_PATTERN = Pattern.compile(sb.toString());
- }
-
public static class Builder {
private String normal;
private String preRelease;
private String build;
- public Builder(String normal) {
- if (normal == null) {
+ public Builder(String normalVersion) {
+ if (normalVersion == null) {
throw new NullPointerException(
"Normal version MUST NOT be NULL"
);
}
- this.normal = normal;
+ normal = normalVersion;
}
- public void setPreReleaseVersion(String preRelease) {
- this.preRelease = preRelease;
+ public void setPreReleaseVersion(String preReleaseVersion) {
+ preRelease = preReleaseVersion;
}
- public void setBuildMetadata(String build) {
- this.build = build;
+ public void setBuildMetadata(String buildMetadata) {
+ build = buildMetadata;
}
public Version build() {
MetadataVersion preReleaseVersion = null;
if (preRelease != null) {
- preReleaseVersion = new MetadataVersion(preRelease);
+ preReleaseVersion = VersionParser.parsePreRelease(preRelease);
}
MetadataVersion buildMetadata = null;
if (build != null) {
- buildMetadata = new MetadataVersion(build);
+ buildMetadata = VersionParser.parseBuild(build);
}
return new Version(
- NormalVersion.valueOf(normal),
+ VersionParser.parseVersionCore(normal),
preReleaseVersion,
buildMetadata
);
@@ -123,7 +97,7 @@ public class Version implements Comparable<Version> {
result = v1.build.compareTo(v2.build);
} else if (v1.build == null ^ v2.build == null) {
/**
- * Build versions satisfy and have a higher precedence
+ * Build versions should have a higher precedence
* than the associated normal version.
*/
result = (v1.build == null) ? -1 : 1;
@@ -150,16 +124,8 @@ public class Version implements Comparable<Version> {
this.build = build;
}
- public static Version valueOf(String value) {
- Matcher matcher = SEMVER_PATTERN.matcher(value);
- if (!matcher.matches()) {
- throw new IllegalArgumentException("Illegal version format");
- }
-
- Builder builder = new Builder(matcher.group("normal"));
- builder.setPreReleaseVersion(matcher.group("preRelease"));
- builder.setBuildMetadata(matcher.group("build"));
- return builder.build();
+ public static Version valueOf(String version) {
+ return VersionParser.parseValidSemVer(version);
}
public Version incrementMajorVersion() {
@@ -169,7 +135,7 @@ public class Version implements Comparable<Version> {
public Version incrementMajorVersion(String preRelease) {
return new Version(
normal.incrementMajor(),
- new MetadataVersion(preRelease)
+ VersionParser.parsePreRelease(preRelease)
);
}
@@ -180,7 +146,7 @@ public class Version implements Comparable<Version> {
public Version incrementMinorVersion(String preRelease) {
return new Version(
normal.incrementMinor(),
- new MetadataVersion(preRelease)
+ VersionParser.parsePreRelease(preRelease)
);
}
@@ -191,7 +157,7 @@ public class Version implements Comparable<Version> {
public Version incrementPatchVersion(String preRelease) {
return new Version(
normal.incrementPatch(),
- new MetadataVersion(preRelease)
+ VersionParser.parsePreRelease(preRelease)
);
}
@@ -210,11 +176,18 @@ public class Version implements Comparable<Version> {
}
public Version setPreReleaseVersion(String preRelease) {
- return new Version(normal, new MetadataVersion(preRelease));
+ return new Version(
+ normal,
+ VersionParser.parsePreRelease(preRelease)
+ );
}
public Version setBuildMetadata(String build) {
- return new Version(normal, preRelease, new MetadataVersion(build));
+ return new Version(
+ normal,
+ preRelease,
+ VersionParser.parseBuild(build)
+ );
}
public int getMajorVersion() {
@@ -308,8 +281,8 @@ public class Version implements Comparable<Version> {
result = preRelease.compareTo(other.preRelease);
} else if (preRelease == null ^ other.preRelease == null) {
/**
- * Pre-release versions satisfy but have a lower precedence
- * than the associated normal version. (SemVer p.9)
+ * Pre-release versions have a lower precedence than
+ * the associated normal version. (SemVer p.9)
*/
result = (preRelease == null) ? 1 : -1;
}
diff --git a/src/main/java/com/github/zafarkhaja/semver/VersionParser.java b/src/main/java/com/github/zafarkhaja/semver/VersionParser.java
new file mode 100644
index 0000000..516cee4
--- /dev/null
+++ b/src/main/java/com/github/zafarkhaja/semver/VersionParser.java
@@ -0,0 +1,309 @@
+/*
+ * 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;
+
+import com.github.zafarkhaja.semver.VersionParser.CharStream;
+import java.util.ArrayList;
+import java.util.List;
+import static com.github.zafarkhaja.semver.VersionParser.Char.*;
+
+/**
+ *
+ * @author Zafar Khaja <zafarkhaja at gmail.com>
+ */
+class VersionParser implements Parser<Version> {
+
+ static class CharStream {
+
+ static interface CharType {
+ boolean isMatchedBy(char chr);
+ }
+
+ private final char[] data;
+
+ private int offset = 0;
+
+ static final char EOL = (char) -1;
+
+ CharStream(String input) {
+ data = input.toCharArray();
+ }
+
+ char consume() {
+ if (offset + 1 <= data.length) {
+ return data[offset++];
+ }
+ return EOL;
+ }
+
+ char consume(CharType... expected) {
+ char la = lookahead(1);
+ for (CharType charType : expected) {
+ if (charType.isMatchedBy(la)) {
+ return consume();
+ }
+ }
+ throw new UnexpectedCharacterException(la, expected);
+ }
+
+ char lookahead() {
+ return lookahead(1);
+ }
+
+ char lookahead(int pos) {
+ int idx = offset + pos - 1;
+ if (idx < data.length) {
+ return data[idx];
+ }
+ return EOL;
+ }
+
+ boolean positiveLookahead(CharType... expected) {
+ char la = lookahead(1);
+ for (CharType charType : expected) {
+ if (charType.isMatchedBy(la)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean positiveLookaheadBefore(CharType before, CharType... expected) {
+ char la;
+ for (int i = 1; i <= data.length; i++) {
+ la = lookahead(i);
+ if (before.isMatchedBy(la)) {
+ break;
+ }
+ for (CharType charType : expected) {
+ if (charType.isMatchedBy(la)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ char[] toArray() {
+ return data.clone();
+ }
+ }
+
+ static enum Char implements CharStream.CharType {
+
+ DIGIT {
+ @Override
+ public boolean isMatchedBy(char chr) {
+ return chr >= '0' && chr <= '9';
+ }
+ },
+ LETTER {
+ @Override
+ public boolean isMatchedBy(char chr) {
+ return (chr >= 'a' && chr <= 'z')
+ || (chr >= 'A' && chr <= 'Z');
+ }
+ },
+ DOT {
+ @Override
+ public boolean isMatchedBy(char chr) {
+ return chr == '.';
+ }
+ },
+ HYPHEN {
+ @Override
+ public boolean isMatchedBy(char chr) {
+ return chr == '-';
+ }
+ },
+ PLUS {
+ @Override
+ public boolean isMatchedBy(char chr) {
+ return chr == '+';
+ }
+ },
+ EOL {
+ @Override
+ public boolean isMatchedBy(char chr) {
+ return chr == CharStream.EOL;
+ }
+ };
+ }
+
+ private final CharStream chars;
+
+ VersionParser(String input) {
+ chars = new CharStream(input);
+ }
+
+ @Override
+ public Version parse(String input) {
+ return parseValidSemVer();
+ }
+
+ static Version parseValidSemVer(String version) {
+ VersionParser parser = new VersionParser(version);
+ return parser.parseValidSemVer();
+ }
+
+ static NormalVersion parseVersionCore(String versionCore) {
+ VersionParser parser = new VersionParser(versionCore);
+ return parser.parseVersionCore();
+ }
+
+ static MetadataVersion parsePreRelease(String preRelease) {
+ VersionParser parser = new VersionParser(preRelease);
+ return parser.parsePreRelease();
+ }
+
+ static MetadataVersion parseBuild(String build) {
+ VersionParser parser = new VersionParser(build);
+ return parser.parseBuild();
+ }
+
+ private Version parseValidSemVer() {
+ NormalVersion normalVersion = parseVersionCore();
+ MetadataVersion preReleaseVersion = null;
+ MetadataVersion buildMetadata = null;
+ if (chars.positiveLookahead(HYPHEN)) {
+ chars.consume();
+ preReleaseVersion = parsePreRelease();
+ }
+ if (chars.positiveLookahead(PLUS)) {
+ chars.consume();
+ buildMetadata = parseBuild();
+ }
+ return new Version(
+ normalVersion,
+ preReleaseVersion,
+ buildMetadata
+ );
+ }
+
+ private NormalVersion parseVersionCore() {
+ int major = Integer.parseInt(numericIdentifier());
+ chars.consume(DOT);
+ int minor = Integer.parseInt(numericIdentifier());
+ chars.consume(DOT);
+ int patch = Integer.parseInt(numericIdentifier());
+ return new NormalVersion(major, minor, patch);
+ }
+
+ private MetadataVersion parsePreRelease() {
+ Char end = closestEndpoint(PLUS, EOL);
+ Char before = closestEndpoint(DOT, end);
+ List<String> idents = new ArrayList<String>();
+ while (!chars.positiveLookahead(end)) {
+ if (before == DOT) {
+ checkForEmptyIdentifier();
+ }
+ if (chars.positiveLookaheadBefore(before, LETTER, HYPHEN)) {
+ idents.add(alphanumericIdentifier());
+ } else {
+ idents.add(numericIdentifier());
+ }
+ if (before == DOT) {
+ chars.consume();
+ }
+ before = closestEndpoint(DOT, end);
+ }
+ return new MetadataVersion(
+ idents.toArray(new String[idents.size()])
+ );
+ }
+
+ private MetadataVersion parseBuild() {
+ Char end = EOL;
+ Char before = closestEndpoint(DOT, end);
+ List<String> idents = new ArrayList<String>();
+ while (!chars.positiveLookahead(end)) {
+ if (before == DOT) {
+ checkForEmptyIdentifier();
+ }
+ if (chars.positiveLookaheadBefore(before, LETTER, HYPHEN)) {
+ idents.add(alphanumericIdentifier());
+ } else {
+ idents.add(digits());
+ }
+ if (before == DOT) {
+ chars.consume();
+ }
+ before = closestEndpoint(DOT, end);
+ }
+ return new MetadataVersion(
+ idents.toArray(new String[idents.size()])
+ );
+ }
+
+ private String numericIdentifier() {
+ checkForLeadingZeroes();
+ StringBuilder sb = new StringBuilder();
+ sb.append(chars.consume(DIGIT));
+ while (chars.positiveLookahead(DIGIT)) {
+ sb.append(chars.consume());
+ }
+ return sb.toString();
+ }
+
+ private String alphanumericIdentifier() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(chars.consume(DIGIT, LETTER, HYPHEN));
+ while (chars.positiveLookahead(DIGIT, LETTER, HYPHEN)) {
+ sb.append(chars.consume());
+ }
+ return sb.toString();
+ }
+
+ private String digits() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(chars.consume(DIGIT));
+ while (chars.positiveLookahead(DIGIT)) {
+ sb.append(chars.consume());
+ }
+ return sb.toString();
+ }
+
+ private Char closestEndpoint(Char tryThis, Char orThis) {
+ if (chars.positiveLookaheadBefore(orThis, tryThis)) {
+ return tryThis;
+ }
+ return orThis;
+ }
+
+ private void checkForLeadingZeroes() {
+ char la1 = chars.lookahead(1);
+ char la2 = chars.lookahead(2);
+ if (la1 == '0' && DIGIT.isMatchedBy(la2)) {
+ throw new GrammarException(
+ "Numeric identifier MUST NOT contain leading zeroes"
+ );
+ }
+ }
+
+ private void checkForEmptyIdentifier() {
+ if (DOT.isMatchedBy(chars.lookahead(1))) {
+ throw new GrammarException("Identifiers MUST NOT be empty");
+ }
+ }
+}
diff --git a/src/test/java/com/github/zafarkhaja/semver/MetadataVersionTest.java b/src/test/java/com/github/zafarkhaja/semver/MetadataVersionTest.java
index 9214dc3..a679f76 100644
--- a/src/test/java/com/github/zafarkhaja/semver/MetadataVersionTest.java
+++ b/src/test/java/com/github/zafarkhaja/semver/MetadataVersionTest.java
@@ -23,10 +23,10 @@
*/
package com.github.zafarkhaja.semver;
-import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
+import static org.junit.Assert.*;
/**
*
@@ -38,78 +38,87 @@ public class MetadataVersionTest {
public static class CoreFunctionalityTest {
@Test
- public void mustConsistOfDotSeparatedIdentifiersOfAlphaNumericsAndHyphen() {
- String[] invalidVersions = {
- null,
- "",
- "123!",
- "1a:2b:3c",
- "123,abc,123",
- };
- for (String ver : invalidVersions) {
- try {
- MetadataVersion v = new MetadataVersion(ver);
- } catch (Exception e) {
- continue;
- }
- fail("Metadata version MUST consist of dot separated identifiers [0-9A-Za-z-]");
- }
- }
-
- @Test
public void mustCompareEachIdentifierSeparately() {
- MetadataVersion v1 = new MetadataVersion("beta.2.abc");
- MetadataVersion v2 = new MetadataVersion("beta.1.edf");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"beta", "2", "abc"}
+ );
+ MetadataVersion v2 = new MetadataVersion(
+ new String[] {"beta", "1", "edf"}
+ );
assertTrue(0 < v1.compareTo(v2));
}
@Test
public void shouldCompareIdentifiersCountIfCommonIdentifiersAreEqual() {
- MetadataVersion v1 = new MetadataVersion("beta.abc");
- MetadataVersion v2 = new MetadataVersion("beta.abc.def");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"beta", "abc"}
+ );
+ MetadataVersion v2 = new MetadataVersion(
+ new String[] {"beta", "abc", "def"}
+ );
assertTrue(0 > v1.compareTo(v2));
}
@Test
public void shouldComapareDigitsOnlyIdentifiersNumerically() {
- MetadataVersion v1 = new MetadataVersion("alpha.123");
- MetadataVersion v2 = new MetadataVersion("alpha.321");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
+ MetadataVersion v2 = new MetadataVersion(
+ new String[] {"alpha", "321"}
+ );
assertTrue(0 > v1.compareTo(v2));
}
@Test
public void shouldCompareMixedIdentifiersLexicallyInAsciiSortOrder() {
- MetadataVersion v1 = new MetadataVersion("beta.abc");
- MetadataVersion v2 = new MetadataVersion("beta.111");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"beta", "abc"}
+ );
+ MetadataVersion v2 = new MetadataVersion(
+ new String[] {"beta", "111"}
+ );
assertTrue(0 < v1.compareTo(v2));
}
@Test
public void shouldOverrideEqualsMethod() {
- MetadataVersion v1 = new MetadataVersion("alpha.123");
- MetadataVersion v2 = new MetadataVersion("alpha.123");
- MetadataVersion v3 = new MetadataVersion("alpha.321");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
+ MetadataVersion v2 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
+ MetadataVersion v3 = new MetadataVersion(
+ new String[] {"alpha", "321"}
+ );
assertTrue(v1.equals(v2));
assertFalse(v1.equals(v3));
}
@Test
public void shouldProvideIncrementMethod() {
- MetadataVersion v1 = new MetadataVersion("alpha.1");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"alpha", "1"}
+ );
MetadataVersion v2 = v1.increment();
assertEquals("alpha.2", v2.toString());
}
@Test
public void shouldAppendOneAsLastIdentifierIfLastOneIsAlphaNumericWhenIncrementing() {
- MetadataVersion v1 = new MetadataVersion("alpha");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"alpha"}
+ );
MetadataVersion v2 = v1.increment();
assertEquals("alpha.1", v2.toString());
}
@Test
public void shouldBeImmutable() {
- MetadataVersion v1 = new MetadataVersion("alpha.1");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"alpha", "1"}
+ );
MetadataVersion v2 = v1.increment();
assertNotSame(v1, v2);
}
@@ -119,23 +128,35 @@ public class MetadataVersionTest {
@Test
public void shouldBeReflexive() {
- MetadataVersion v = new MetadataVersion("alpha.123");
+ MetadataVersion v = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
assertTrue(v.equals(v));
}
@Test
public void shouldBeSymmetric() {
- MetadataVersion v1 = new MetadataVersion("alpha.123");
- MetadataVersion v2 = new MetadataVersion("alpha.123");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
+ MetadataVersion v2 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
assertTrue(v1.equals(v2));
assertTrue(v2.equals(v1));
}
@Test
public void shouldBeTransitive() {
- MetadataVersion v1 = new MetadataVersion("alpha.123");
- MetadataVersion v2 = new MetadataVersion("alpha.123");
- MetadataVersion v3 = new MetadataVersion("alpha.123");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
+ MetadataVersion v2 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
+ MetadataVersion v3 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
assertTrue(v1.equals(v2));
assertTrue(v2.equals(v3));
assertTrue(v1.equals(v3));
@@ -143,8 +164,12 @@ public class MetadataVersionTest {
@Test
public void shouldBeConsistent() {
- MetadataVersion v1 = new MetadataVersion("alpha.123");
- MetadataVersion v2 = new MetadataVersion("alpha.123");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
+ MetadataVersion v2 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
assertTrue(v1.equals(v2));
assertTrue(v1.equals(v2));
assertTrue(v1.equals(v2));
@@ -152,13 +177,17 @@ public class MetadataVersionTest {
@Test
public void shouldReturnFalseIfOtherVersionIsOfDifferentType() {
- MetadataVersion v = new MetadataVersion("alpha.123");
+ MetadataVersion v = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
assertFalse(v.equals(new String("alpha.123")));
}
@Test
public void shouldReturnFalseIfOtherVersionIsNull() {
- MetadataVersion v1 = new MetadataVersion("alpha.123");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
MetadataVersion v2 = null;
assertFalse(v1.equals(v2));
}
@@ -168,8 +197,12 @@ public class MetadataVersionTest {
@Test
public void shouldReturnSameHashCodeIfVersionsAreEqual() {
- MetadataVersion v1 = new MetadataVersion("alpha.123");
- MetadataVersion v2 = new MetadataVersion("alpha.123");
+ MetadataVersion v1 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
+ MetadataVersion v2 = new MetadataVersion(
+ new String[] {"alpha", "123"}
+ );
assertTrue(v1.equals(v2));
assertEquals(v1.hashCode(), v2.hashCode());
}
@@ -180,7 +213,7 @@ public class MetadataVersionTest {
@Test
public void shouldReturnStringRepresentation() {
String value = "beta.abc.def";
- MetadataVersion v = new MetadataVersion(value);
+ MetadataVersion v = new MetadataVersion(value.split("\\."));
assertEquals(value, v.toString());
}
}
diff --git a/src/test/java/com/github/zafarkhaja/semver/NormalVersionTest.java b/src/test/java/com/github/zafarkhaja/semver/NormalVersionTest.java
index 587e312..1fe2cdf 100644
--- a/src/test/java/com/github/zafarkhaja/semver/NormalVersionTest.java
+++ b/src/test/java/com/github/zafarkhaja/semver/NormalVersionTest.java
@@ -23,10 +23,10 @@
*/
package com.github.zafarkhaja.semver;
-import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
+import static org.junit.Assert.*;
/**
*
@@ -56,7 +56,7 @@ public class NormalVersionTest {
int[][] invalidVersions = {{-1, 2, 3}, {1, -2, 3}, {1, 2, -3}};
for (int[] versionParts : invalidVersions) {
try {
- NormalVersion v = new NormalVersion(
+ new NormalVersion(
versionParts[0],
versionParts[1],
versionParts[2]
@@ -116,14 +116,6 @@ public class NormalVersionTest {
}
@Test
- public void shouldHaveStaticFactoryMethod() {
- NormalVersion v = NormalVersion.valueOf("1.2.3");
- assertEquals(1, v.getMajor());
- assertEquals(2, v.getMinor());
- assertEquals(3, v.getPatch());
- }
-
- @Test
public void shoudBeImmutable() {
NormalVersion version = new NormalVersion(1, 2, 3);
NormalVersion incementedMajor = version.incrementMajor();
diff --git a/src/test/java/com/github/zafarkhaja/semver/VersionParserCharStreamTest.java b/src/test/java/com/github/zafarkhaja/semver/VersionParserCharStreamTest.java
new file mode 100644
index 0000000..1c3bf77
--- /dev/null
+++ b/src/test/java/com/github/zafarkhaja/semver/VersionParserCharStreamTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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;
+
+import com.github.zafarkhaja.semver.VersionParser.Char;
+import com.github.zafarkhaja.semver.VersionParser.CharStream;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Zafar Khaja <zafarkhaja at gmail.com>
+ */
+public class VersionParserCharStreamTest {
+
+ @Test
+ public void shouldBeBackedByCharArray() {
+ String input = "abc";
+ CharStream chars = new CharStream(input);
+ assertArrayEquals(input.toCharArray(), chars.toArray());
+ }
+
+ @Test
+ public void shouldNotReturnRealCharArray() {
+ CharStream chars = new CharStream("abc");
+ char[] charArray = chars.toArray();
+ charArray[0] = 'z';
+ assertEquals('z', charArray[0]);
+ assertEquals('a', chars.lookahead());
+ }
+
+ @Test
+ public void shouldConsumeCharactersOneByOne() {
+ CharStream chars = new CharStream("abc");
+ assertEquals('a', chars.consume());
+ assertEquals('b', chars.consume());
+ assertEquals('c', chars.consume());
+ }
+
+ @Test
+ public void shouldReturnEolWhenNothingLeftToConsume() {
+ CharStream chars = new CharStream("abc");
+ assertEquals('a', chars.consume());
+ assertEquals('b', chars.consume());
+ assertEquals('c', chars.consume());
+ assertEquals(CharStream.EOL, chars.consume());
+ }
+
+ @Test
+ public void shouldRaiseErrorWhenUnexpectedCharTypeConsumed() {
+ CharStream chars = new CharStream("abc");
+ try {
+ chars.consume(Char.DIGIT);
+ } catch (UnexpectedCharacterException e) {
+ return;
+ }
+ fail("Should raise error when unexpected character type is consumed");
+ }
+
+ @Test
+ public void shouldLookaheadWithoutConsuming() {
+ CharStream chars = new CharStream("abc");
+ assertEquals('a', chars.lookahead());
+ assertEquals('a', chars.lookahead());
+ }
+
+ @Test
+ public void shouldLookaheadArbitraryNumberOfCharacters() {
+ CharStream chars = new CharStream("abc");
+ assertEquals('a', chars.lookahead(1));
+ assertEquals('b', chars.lookahead(2));
+ assertEquals('c', chars.lookahead(3));
+ }
+
+ @Test
+ public void shouldReturnEolWhenNothingLeftToLookahead() {
+ CharStream chars = new CharStream("abc");
+ assertEquals('a', chars.consume());
+ assertEquals('b', chars.consume());
+ assertEquals('c', chars.consume());
+ assertEquals(CharStream.EOL, chars.lookahead());
+ }
+
+ @Test
+ public void shouldCheckIfLookaheadIsOfExpectedTypes() {
+ CharStream chars = new CharStream("abc");
+ assertTrue(chars.positiveLookahead(Char.LETTER));
+ assertFalse(chars.positiveLookahead(Char.DIGIT, Char.PLUS));
+ }
+
+ @Test
+ public void shouldCheckIfCharOfExpectedTypesExistBeforeGivenType() {
+ CharStream chars = new CharStream("1.0.0");
+ assertTrue(chars.positiveLookaheadBefore(Char.EOL, Char.DOT));
+ assertFalse(chars.positiveLookaheadBefore(Char.EOL, Char.LETTER));
+ }
+}
diff --git a/src/test/java/com/github/zafarkhaja/semver/VersionParserCharTest.java b/src/test/java/com/github/zafarkhaja/semver/VersionParserCharTest.java
new file mode 100644
index 0000000..3d4741c
--- /dev/null
+++ b/src/test/java/com/github/zafarkhaja/semver/VersionParserCharTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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;
+
+import com.github.zafarkhaja.semver.VersionParser.Char;
+import com.github.zafarkhaja.semver.VersionParser.CharStream;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Zafar Khaja <zafarkhaja at gmail.com>
+ */
+public class VersionParserCharTest {
+
+ @Test
+ public void shouldBeMatchedByDigit() {
+ assertTrue(Char.DIGIT.isMatchedBy('0'));
+ assertTrue(Char.DIGIT.isMatchedBy('9'));
+ assertFalse(Char.DIGIT.isMatchedBy('a'));
+ assertFalse(Char.DIGIT.isMatchedBy('A'));
+ }
+
+ @Test
+ public void shouldBeMatchedByLetter() {
+ assertTrue(Char.LETTER.isMatchedBy('a'));
+ assertTrue(Char.LETTER.isMatchedBy('A'));
+ assertFalse(Char.LETTER.isMatchedBy('0'));
+ assertFalse(Char.LETTER.isMatchedBy('9'));
+ }
+
+ @Test
+ public void shouldBeMatchedByDot() {
+ assertTrue(Char.DOT.isMatchedBy('.'));
+ assertFalse(Char.DOT.isMatchedBy('-'));
+ assertFalse(Char.DOT.isMatchedBy('0'));
+ assertFalse(Char.DOT.isMatchedBy('9'));
+ }
+
+ @Test
+ public void shouldBeMatchedByHyphen() {
+ assertTrue(Char.HYPHEN.isMatchedBy('-'));
+ assertFalse(Char.HYPHEN.isMatchedBy('+'));
+ assertFalse(Char.HYPHEN.isMatchedBy('a'));
+ assertFalse(Char.HYPHEN.isMatchedBy('0'));
+ }
+
+ @Test
+ public void shouldBeMatchedByPlus() {
+ assertTrue(Char.PLUS.isMatchedBy('+'));
+ assertFalse(Char.PLUS.isMatchedBy('-'));
+ assertFalse(Char.PLUS.isMatchedBy('a'));
+ assertFalse(Char.PLUS.isMatchedBy('0'));
+ }
+
+ @Test
+ public void shouldBeMatchedByEol() {
+ assertTrue(Char.EOL.isMatchedBy(CharStream.EOL));
+ assertFalse(Char.EOL.isMatchedBy('-'));
+ assertFalse(Char.EOL.isMatchedBy('a'));
+ assertFalse(Char.EOL.isMatchedBy('0'));
+ }
+}
diff --git a/src/test/java/com/github/zafarkhaja/semver/VersionParserTest.java b/src/test/java/com/github/zafarkhaja/semver/VersionParserTest.java
new file mode 100644
index 0000000..6831c7a
--- /dev/null
+++ b/src/test/java/com/github/zafarkhaja/semver/VersionParserTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Zafar Khaja <zafarkhaja at gmail.com>
+ */
+public class VersionParserTest {
+
+ @Test
+ public void shouldParseNormalVersion() {
+ NormalVersion version = VersionParser.parseVersionCore("1.0.0");
+ assertEquals(new NormalVersion(1, 0, 0), version);
+ }
+
+ @Test
+ public void shouldRaiseErrorIfNumericIdentifierHasLeadingZeroes() {
+ try {
+ VersionParser.parseVersionCore("01.1.0");
+ } catch (GrammarException e) {
+ return;
+ }
+ fail("Numeric identifier MUST NOT contain leading zeroes");
+ }
+
+ @Test
+ public void shouldParsePreReleaseVersion() {
+ MetadataVersion preRelease = VersionParser.parsePreRelease("beta-1.1");
+ assertEquals(new MetadataVersion(new String[] {"beta-1", "1"}), preRelease);
+ }
+
+ @Test
+ public void shouldNotAllowDigitsInPreReleaseVersion() {
+ try {
+ VersionParser.parsePreRelease("alpha.01");
+ } catch (ParserException e) {
+ return;
+ }
+ fail("Should not allow digits in pre-release version");
+ }
+
+ @Test
+ public void shouldRaiseErrorForEmptyPreReleaseIdentifier() {
+ try {
+ VersionParser.parsePreRelease("beta-1..1");
+ } catch (GrammarException e) {
+ return;
+ }
+ fail("Identifiers MUST NOT be empty");
+ }
+
+ @Test
+ public void shouldParseBuildMetadata() {
+ MetadataVersion build = VersionParser.parseBuild("build.1");
+ assertEquals(new MetadataVersion(new String[] {"build", "1"}), build);
+ }
+
+ @Test
+ public void shouldAllowDigitsInBuildMetadata() {
+ try {
+ VersionParser.parseBuild("build.01");
+ } catch (ParserException e) {
+ fail("Should allow digits in build metadata");
+ }
+ }
+
+ @Test
+ public void shouldRaiseErrorForEmptyBuildIdentifier() {
+ try {
+ VersionParser.parseBuild(".build.01");
+ } catch (GrammarException e) {
+ return;
+ }
+ fail("Identifiers MUST NOT be empty");
+ }
+
+ @Test
+ public void shouldParseValidSemVer() {
+ VersionParser parser = new VersionParser("1.0.0-rc.2+build.05");
+ Version version = parser.parse(null);
+ assertEquals(
+ new Version(
+ new NormalVersion(1, 0, 0),
+ new MetadataVersion(new String[] {"rc", "2"}),
+ new MetadataVersion(new String[] {"build", "05"})
+ ),
+ version
+ );
+ }
+}
diff --git a/src/test/java/com/github/zafarkhaja/semver/VersionTest.java b/src/test/java/com/github/zafarkhaja/semver/VersionTest.java
index 9533b51..af65488 100644
--- a/src/test/java/com/github/zafarkhaja/semver/VersionTest.java
+++ b/src/test/java/com/github/zafarkhaja/semver/VersionTest.java
@@ -23,10 +23,10 @@
*/
package com.github.zafarkhaja.semver;
-import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
+import static org.junit.Assert.*;
/**
*
@@ -118,10 +118,15 @@ public class VersionTest {
String[] versions = {
"1.0.0-alpha",
"1.0.0-alpha.1",
+ "1.0.0-alpha.beta",
+ "1.0.0-beta",
"1.0.0-beta.2",
"1.0.0-beta.11",
"1.0.0-rc.1",
"1.0.0",
+ "2.0.0",
+ "2.1.0",
+ "2.1.1"
};
for (int i = 1; i < versions.length; i++) {
Version v1 = Version.valueOf(versions[i-1]);
@@ -235,7 +240,7 @@ public class VersionTest {
public void shouldThrowExceptionWhenIncrementingPreReleaseIfItsNull() {
Version v1 = Version.valueOf("1.0.0");
try {
- Version v2 = v1.incrementPreReleaseVersion();
+ v1.incrementPreReleaseVersion();
} catch (NullPointerException e) {
return;
}
@@ -260,7 +265,7 @@ public class VersionTest {
public void shouldThrowExceptionWhenIncrementingBuildIfItsNull() {
Version v1 = Version.valueOf("1.0.0");
try {
- Version v2 = v1.incrementBuildMetadata();
+ v1.incrementBuildMetadata();
} catch (NullPointerException e) {
return;
}
@@ -377,7 +382,7 @@ public class VersionTest {
@Test
public void shouldThrowNullPointerExceptionIfNormalVersionIsNull() {
try {
- Version.Builder builder = new Version.Builder(null);
+ new Version.Builder(null);
} catch (NullPointerException e) {
return;
}
--
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