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 <[email protected]> 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 [](https://travis-ci.org/zafarkhaja/java-semver) +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/). -**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 <[email protected]>. + * + * 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 <[email protected]> + */ +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 <[email protected]> @@ -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 <[email protected]>. + * + * 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 <[email protected]> + */ +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 <[email protected]>. + * + * 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 <[email protected]> + */ +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 <[email protected]>. + * + * 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 <[email protected]> + */ +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 <[email protected]>. + * + * 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 <[email protected]> + */ +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 <[email protected]>. + * + * 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 <[email protected]> + */ +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 <[email protected]>. + * + * 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 <[email protected]> + */ +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 <[email protected]>. + * + * 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 <[email protected]> + */ +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 _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

