Skip to content

Commit 2c5698b

Browse files
committed
Improve tests and fix bounds' issues
1 parent 3d466d8 commit 2c5698b

File tree

9 files changed

+477
-191
lines changed

9 files changed

+477
-191
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,5 @@ Tasks/**/*.js.map
254254
Tasks/**/*.d.ts
255255
Tasks/*/common/**/*.*
256256

257-
.BuildOutput
257+
.BuildOutput
258+
nunitresults.xml

Tasks/EncodeSemverToInteger/EncodeSemverToInteger.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,38 @@
1-
import { Encoder } from "./encoder";
1+
import { Encoder, EncodingConfiguration, IPrereleaseTagMap } from "./encoder";
22
import tl = require("vsts-task-lib/task");
33
import semver = require("semver");
44

55
try {
6+
7+
let checkNaN = (numberToCheck: number, numberName: string): number => {
8+
if (isNaN(numberToCheck)) {
9+
throw new Error(numberName + " is not a valid number.");
10+
}
11+
12+
return numberToCheck;
13+
};
14+
15+
let getNumberInput = (inputName: string): number => {
16+
return checkNaN(parseInt(tl.getInput(inputName)), inputName);
17+
};
18+
619
let sourceSemVer = tl.getInput("SourceSemver");
7-
let minorBits = parseInt(tl.getInput("MinorBits"));
8-
let patchBits = parseInt(tl.getInput("PatchBits"));
9-
let preReleaseTagBits = parseInt(tl.getInput("PreReleaseTagBits"));
10-
let preReleaseTagMap = JSON.parse(tl.getInput("PreReleaseTagMap"));
11-
let preReleaseNumberBits = parseInt(tl.getInput("PreReleaseNumberBits"));
20+
let minorBits = getNumberInput("MinorBits");
21+
let patchBits = getNumberInput("PatchBits");
22+
let preReleaseTagBits = getNumberInput("PreReleaseTagBits");
23+
let preReleaseTagMap: IPrereleaseTagMap = JSON.parse(tl.getInput("PreReleaseTagMap"));
24+
let preReleaseNumberBits = getNumberInput("PreReleaseNumberBits");
1225
let outputVariable = tl.getInput("OutputVariable");
1326

1427
let varRegex = /\$\((.*?)\)/g;
1528
sourceSemVer = sourceSemVer.replace(varRegex, (match, varName, offset, s) => tl.getVariable(varName));
1629

17-
console.log("SourceSemVer : " + sourceSemVer);
30+
console.log("Source Semver: " + sourceSemVer);
1831

19-
let encoder = new Encoder(sourceSemVer);
20-
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
32+
let encoder = new Encoder(new EncodingConfiguration(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits));
33+
let code = checkNaN(encoder.encode(sourceSemVer), "Computed Version Code");
2134

22-
console.log("computed versioncode : " + code.toString());
35+
console.log("Computed Version Code: " + code.toString());
2336
tl.setVariable(outputVariable, code.toString());
2437

2538
tl.setResult(tl.TaskResult.Succeeded, "Code encoded");

Tasks/EncodeSemverToInteger/encoder.ts

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,79 @@
11
import semver = require("semver");
22

3+
export interface IPrereleaseTagMap {
4+
[key: string]: number;
5+
}
6+
7+
export class EncodingConfiguration {
8+
readonly majorBits: number = 31 - this.minorBits - this.patchBits - this.prereleaseNumberBits - this.prereleaseTagBits;
9+
10+
readonly maxPrereleaseTagCode = Math.pow(2, this.prereleaseTagBits) - 1;
11+
readonly maxPrereleaseNumberCode = Math.pow(2, this.prereleaseNumberBits) - 1;
12+
13+
constructor(
14+
readonly minorBits: number,
15+
readonly patchBits: number,
16+
readonly prereleaseTagBits: number,
17+
readonly prereleaseTagMap: IPrereleaseTagMap,
18+
readonly prereleaseNumberBits: number,
19+
readonly friendlyName: string = "Default") {
20+
}
21+
}
22+
323
export class Encoder {
4-
constructor(private sourceSemVer: string) {
24+
constructor(private configuration: EncodingConfiguration) {
525
}
626

7-
private checkBounds(value: number, bits: number, name: string) {
8-
if (value >= (Math.pow(2, bits))) {
9-
throw new Error(name + " will overflow allocated bits. " + value.toString() + " >= " + (Math.pow(2, bits)).toString());
27+
private checkOverflow(value: number, bits: number, name: string) {
28+
let maxValue = Math.pow(2, bits);
29+
if (value >= maxValue) {
30+
throw new Error(name + " will overflow allocated bits (" + value.toString() + " >= " + maxValue.toString() + ").");
1031
}
1132
}
1233

13-
encode(minorBits: number, patchBits: number, preReleaseTagBits: number, preReleaseTagMap: any, preReleaseNumberBits: number): number {
14-
let majorBits = 32 - minorBits - patchBits - preReleaseNumberBits - preReleaseTagBits;
15-
16-
let parsedSemver = new semver.SemVer(this.sourceSemVer, false);
34+
encode(sourceSemver: string): number {
35+
let parsedSemver = new semver.SemVer(sourceSemver, false);
1736

1837
let code: number = 0;
1938

20-
this.checkBounds(parsedSemver.major, majorBits, "major");
39+
this.checkOverflow(parsedSemver.major, this.configuration.majorBits, "Major");
2140
code += parsedSemver.major;
2241

23-
this.checkBounds(parsedSemver.minor, minorBits, "minor");
24-
code = code << minorBits;
42+
this.checkOverflow(parsedSemver.minor, this.configuration.minorBits, "Minor");
43+
code = code << this.configuration.minorBits;
2544
code += parsedSemver.minor;
2645

27-
this.checkBounds(parsedSemver.patch, patchBits, "patch");
28-
code = code << patchBits;
46+
this.checkOverflow(parsedSemver.patch, this.configuration.patchBits, "Patch");
47+
code = code << this.configuration.patchBits;
2948
code += parsedSemver.patch;
3049

31-
let preReleaseTagCode: number = Math.pow(2, preReleaseTagBits) - 1;
32-
let preReleaseNumber: number = Math.pow(2, preReleaseNumberBits) - 1;
50+
let prereleaseTagCode = this.configuration.maxPrereleaseTagCode;
51+
let prereleaseNumberCode = this.configuration.maxPrereleaseNumberCode;
3352
if (parsedSemver.prerelease && parsedSemver.prerelease.length) {
34-
let mapResult = preReleaseTagMap[parsedSemver.prerelease[0]];
53+
prereleaseTagCode = 0;
54+
prereleaseNumberCode = 0;
55+
56+
let mapResult = this.configuration.prereleaseTagMap[parsedSemver.prerelease[0]];
3557
if (mapResult) {
36-
preReleaseTagCode = mapResult;
37-
} else {
38-
preReleaseTagCode = 0;
58+
if (mapResult === this.configuration.maxPrereleaseTagCode) {
59+
throw new Error("The max allowed Prerelease Tag value (" + this.configuration.maxPrereleaseTagCode + ") should be kept for Semver without Prerelease Tag.");
60+
}
61+
62+
prereleaseTagCode = mapResult;
3963
}
64+
4065
if (parsedSemver.prerelease.length > 1) {
41-
preReleaseNumber = parseInt(parsedSemver.prerelease[1]);
66+
prereleaseNumberCode = parseInt(parsedSemver.prerelease[1]);
4267
}
4368
}
4469

45-
this.checkBounds(preReleaseTagCode, preReleaseTagBits, "preReleaseTagBits");
46-
code = code << preReleaseTagBits;
47-
code += preReleaseTagCode;
70+
this.checkOverflow(prereleaseTagCode, this.configuration.prereleaseTagBits, "Prerelease Tag");
71+
code = code << this.configuration.prereleaseTagBits;
72+
code += prereleaseTagCode;
4873

49-
this.checkBounds(preReleaseNumber, preReleaseNumberBits, "preReleaseNumberBits");
50-
code = code << preReleaseNumberBits;
51-
code += preReleaseNumber;
74+
this.checkOverflow(prereleaseNumberCode, this.configuration.prereleaseNumberBits, "Prerelease Number");
75+
code = code << this.configuration.prereleaseNumberBits;
76+
code += prereleaseNumberCode;
5277

5378
return code;
5479
}

0 commit comments

Comments
 (0)