downport and unit tests (#12)

* refactor tests

* additional unit tests, closes #10

* refactor

* better error messages

* add downport step, closes #9

* test
This commit is contained in:
Lars Hvam
2021-11-25 18:23:15 +01:00
committed by GitHub
parent 94a1e2392c
commit e088e2de27
15 changed files with 224 additions and 68 deletions

View File

@@ -4,6 +4,7 @@ WORKDIR /opt/test-runner
COPY . .
RUN npm ci
RUN npm run build
RUN npm install @abaplint/cli -g
RUN npm install @abaplint/transpiler-cli -g
RUN npm install @abaplint/runtime -g
ENTRYPOINT ["/opt/test-runner/bin/run.sh"]

17
package-lock.json generated
View File

@@ -9,6 +9,7 @@
"version": "0.1.0",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@abaplint/cli": "^2.82.1",
"@abaplint/runtime": "^1.6.66",
"@abaplint/transpiler": "^1.6.66",
"@abaplint/transpiler-cli": "^1.6.66"
@@ -26,6 +27,17 @@
"typescript": "^4.5.2"
}
},
"node_modules/@abaplint/cli": {
"version": "2.82.1",
"resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.82.1.tgz",
"integrity": "sha512-ZG5ykfBbUYw2dfe69k1ON4yQKNpzr+ddV4OwtYYU8/TPyPMkXnzn9hTPigiNK3SxyoKTW2X1KLtfllLAx5V+KA==",
"bin": {
"abaplint": "abaplint"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/@abaplint/core": {
"version": "2.80.10",
"resolved": "https://registry.npmjs.org/@abaplint/core/-/core-2.80.10.tgz",
@@ -1211,6 +1223,11 @@
}
},
"dependencies": {
"@abaplint/cli": {
"version": "2.82.1",
"resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.82.1.tgz",
"integrity": "sha512-ZG5ykfBbUYw2dfe69k1ON4yQKNpzr+ddV4OwtYYU8/TPyPMkXnzn9hTPigiNK3SxyoKTW2X1KLtfllLAx5V+KA=="
},
"@abaplint/core": {
"version": "2.80.10",
"resolved": "https://registry.npmjs.org/@abaplint/core/-/core-2.80.10.tgz",

View File

@@ -28,6 +28,7 @@
"dependencies": {
"@abaplint/transpiler-cli": "^1.6.66",
"@abaplint/transpiler": "^1.6.66",
"@abaplint/cli": "^2.82.1",
"@abaplint/runtime": "^1.6.66"
},
"devDependencies": {

View File

@@ -26,12 +26,47 @@ export interface ITranspilerConfig {
options: Transpiler.ITranspilerOptions;
}
const COMPILE_RESULT = "_compile_result.txt";
const RUN_RESULT = "_run_result.txt";
const output: IOutput = {
version: 1,
status: "pass",
}
function run() {
class Runner {
private readonly tmpDir: string;
let config: ITranspilerConfig = {
public constructor() {
this.tmpDir = fs.mkdtempSync(path.join(tmpdir(), 'exercism-abap-runner-'));
}
public run() {
this.initialize();
this.syntaxAndDownport();
if (output.status === "pass") {
this.transpile();
}
if (output.status === "pass") {
this.executeTests();
}
fs.writeFileSync(outputFile, JSON.stringify(output));
}
private syntaxAndDownport() {
const LINT_RESULT = "_abaplint.txt";
const abaplintConfig = Transpiler.config;
abaplintConfig.rules["downport"] = true;
fs.writeFileSync(path.join(this.tmpDir, "abaplint.json"), JSON.stringify(abaplintConfig, null, 2));
try {
execSync(`abaplint --fix > ` + LINT_RESULT, {
stdio: 'pipe',
cwd: this.tmpDir});
} catch (error) {
output.status = "error";
output.message = fs.readFileSync(path.join(this.tmpDir, LINT_RESULT), "utf-8");
}
}
private initialize() {
const config: ITranspilerConfig = {
input_folder: ".",
input_filter: [],
output_folder: "compiled",
@@ -46,49 +81,49 @@ function run() {
}
}
const tmpDir = fs.mkdtempSync(path.join(tmpdir(), 'exercism-abap-runner-'));
fs.writeFileSync(path.join(tmpDir, "abap_transpile.json"), JSON.stringify(config, null, 2));
execSync(`cp ${inputDir}/*.abap ${tmpDir}`, {stdio: 'pipe'});
fs.mkdirSync(`${tmpDir}/deps`);
execSync(`cp open-abap/src/unit/*.clas.abap ${tmpDir}/deps/`, {stdio: 'pipe'});
execSync(`cp open-abap/src/classrun/*.intf.abap ${tmpDir}/deps/`, {stdio: 'pipe'});
const output: IOutput = {
version: 1,
status: "pass",
fs.writeFileSync(path.join(this.tmpDir, "abap_transpile.json"), JSON.stringify(config, null, 2));
execSync(`cp ${inputDir}/*.abap ${this.tmpDir}`, {stdio: 'pipe'});
fs.mkdirSync(`${this.tmpDir}/deps`);
execSync(`cp open-abap/src/unit/*.clas.abap ${this.tmpDir}/deps/`, {stdio: 'pipe'});
execSync(`cp open-abap/src/exceptions/* ${this.tmpDir}/deps/`, {stdio: 'pipe'});
execSync(`cp open-abap/src/ddic/*.xml ${this.tmpDir}/deps/`, {stdio: 'pipe'});
execSync(`cp open-abap/src/classrun/*.intf.abap ${this.tmpDir}/deps/`, {stdio: 'pipe'});
execSync(`rm ${this.tmpDir}/deps/*.testclasses.*`, {stdio: 'pipe'});
}
private transpile() {
const COMPILE_RESULT = "_compile_result.txt";
try {
execSync(`abap_transpile > ` + COMPILE_RESULT, {
stdio: 'pipe',
cwd: tmpDir});
cwd: this.tmpDir});
} catch (error) {
output.status = "error";
output.message = fs.readFileSync(path.join(tmpDir, COMPILE_RESULT), "utf-8");
output.message = fs.readFileSync(path.join(this.tmpDir, COMPILE_RESULT), "utf-8");
output.message = output.message.split("at Transpiler.validate")[0];
output.message = output.message.trim();
}
}
if (output.status === "pass") {
private executeTests() {
const RUN_RESULT = "_run_result.txt";
execSync(`npm link @abaplint/runtime`, {
stdio: 'pipe',
cwd: tmpDir });
cwd: this.tmpDir });
try {
execSync(`node compiled/index.mjs > ` + RUN_RESULT, {
stdio: 'pipe',
cwd: tmpDir});
cwd: this.tmpDir});
} catch (error) {
output.status = "fail";
output.message = fs.readFileSync(path.join(tmpDir, RUN_RESULT), "utf-8");
output.message = fs.readFileSync(path.join(this.tmpDir, RUN_RESULT), "utf-8");
if (output.message.includes("Error: ASSERT failed")) {
output.message = output.message.split("Error: ASSERT failed")[0] + "Error: ASSERT failed";
}
output.message = output.message.trim();
}
}
fs.writeFileSync(outputFile, JSON.stringify(output));
}
run();
new Runner().run();

View File

@@ -20,40 +20,40 @@ function checkExpected(expectedFile: string): void {
expect(act).to.equal(exp);
}
function test(slug: string, expectedStatus: string) {
const path = join(fixtures, slug);
const res = spawnSync('bash', [run, slug, path, output], {cwd: root});
expect(res.status).to.equal(0);
checkExpected(join(path, "expected_results.json"));
expect(readResult().status).to.equal(expectedStatus);
}
describe('abap-test-runner', async () => {
it('simple, pass', async () => {
const slug = "simple-pass";
const path = join(fixtures, slug);
const res = spawnSync('bash', [run, slug, path, output], {cwd: root});
expect(res.status).to.equal(0);
expect(readResult().status).to.equal("pass");
checkExpected(join(path, "expected_results.json"));
test("simple-pass", "pass");
});
it('simple, fail', async () => {
const slug = "simple-fail";
const path = join(fixtures, slug);
const res = spawnSync('bash', [run, slug, path, output], {cwd: root});
expect(res.status).to.equal(0);
expect(readResult().status).to.equal("fail");
checkExpected(join(path, "expected_results.json"));
it('simple-fail', async () => {
test("simple-fail", "fail");
});
it('simple, syntax error', async () => {
const slug = "simple-error";
const path = join(fixtures, slug);
const res = spawnSync('bash', [run, slug, path, output], {cwd: root});
expect(res.status).to.equal(0);
expect(readResult().status).to.equal("error");
checkExpected(join(path, "expected_results.json"));
it('simple-error', async () => {
test("simple-error", "error");
});
it('hello-world, pass', async () => {
const slug = "hello-world-pass";
const path = join(fixtures, slug);
const res = spawnSync('bash', [run, slug, path, output], {cwd: root});
expect(res.status).to.equal(0);
expect(readResult().status).to.equal("pass");
checkExpected(join(path, "expected_results.json"));
it('hello-world-pass', async () => {
test("hello-world-pass", "pass");
});
it('simple-all-fail', async () => {
test("simple-all-fail", "fail");
});
it('simple-some-fail', async () => {
test("simple-some-fail", "fail");
});
it('simple-downport-pass', async () => {
test("simple-downport-pass", "pass");
});
});

View File

@@ -0,0 +1 @@
{"version":1,"status":"fail","message":"ZCL_SIMPLE: running ltcl_simple->test1\n\nError: ASSERT failed"}

View File

@@ -0,0 +1,12 @@
CLASS zcl_simple DEFINITION PUBLIC.
PUBLIC SECTION.
METHODS run RETURNING VALUE(res) TYPE i.
ENDCLASS.
CLASS zcl_simple IMPLEMENTATION.
METHOD run.
res = 3.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,23 @@
CLASS ltcl_simple DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL.
PRIVATE SECTION.
METHODS test1 FOR TESTING RAISING cx_static_check.
METHODS test2 FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_simple IMPLEMENTATION.
METHOD test1.
cl_abap_unit_assert=>assert_equals(
act = 2
exp = 123 ).
ENDMETHOD.
METHOD test2.
cl_abap_unit_assert=>assert_equals(
act = 2
exp = 36 ).
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1 @@
{"version":1,"status":"pass"}

View File

@@ -0,0 +1,12 @@
CLASS zcl_simple DEFINITION PUBLIC.
PUBLIC SECTION.
METHODS run RETURNING VALUE(res) TYPE i.
ENDCLASS.
CLASS zcl_simple IMPLEMENTATION.
METHOD run.
res = 3.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,17 @@
CLASS ltcl_simple DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL.
PRIVATE SECTION.
METHODS test FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_simple IMPLEMENTATION.
METHOD test.
DATA(simple) = NEW zcl_simple( ).
cl_abap_unit_assert=>assert_equals(
act = simple->run( )
exp = 3 ).
ENDMETHOD.
ENDCLASS.

View File

@@ -1 +1 @@
{"version":1,"status":"error","message":"Transpiler CLI\nUsing config: abap_transpile.json\n7 files added\n0 files skipped\n\nBuilding\nError: parser_error, Statement does not exist in ABAPopen-abap(or a parser error), \"blah\", zcl_simple.clas.abap:9"}
{"version":1,"status":"error","message":"./zcl_simple.clas.abap[9, 5] - Statement does not exist in ABAPopen-abap(or a parser error), \"blah\" (parser_error) [E]\nabaplint: 1 issue(s) found, 59 file(s) analyzed\nFixes applied"}

View File

@@ -0,0 +1 @@
{"version":1,"status":"fail","message":"ZCL_SIMPLE: running ltcl_simple->test1\nZCL_SIMPLE: running ltcl_simple->test2\n\nError: ASSERT failed"}

View File

@@ -0,0 +1,12 @@
CLASS zcl_simple DEFINITION PUBLIC.
PUBLIC SECTION.
METHODS run RETURNING VALUE(res) TYPE i.
ENDCLASS.
CLASS zcl_simple IMPLEMENTATION.
METHOD run.
res = 3.
ENDMETHOD.
ENDCLASS.

View File

@@ -0,0 +1,23 @@
CLASS ltcl_simple DEFINITION FOR TESTING RISK LEVEL HARMLESS DURATION SHORT FINAL.
PRIVATE SECTION.
METHODS test1 FOR TESTING RAISING cx_static_check.
METHODS test2 FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl_simple IMPLEMENTATION.
METHOD test1.
cl_abap_unit_assert=>assert_equals(
act = 2
exp = 2 ).
ENDMETHOD.
METHOD test2.
cl_abap_unit_assert=>assert_equals(
act = 2
exp = 36 ).
ENDMETHOD.
ENDCLASS.