adds .ts tests for parser

This commit is contained in:
damirka 2021-09-23 17:05:00 +03:00
parent 63cc0b7d05
commit 1ffcede96c
7 changed files with 314 additions and 1 deletions

View File

@ -20,7 +20,7 @@ use std::path::PathBuf;
use crate::{ use crate::{
commands::{ commands::{
package::{Login, Logout}, package::{Login, Logout},
Build, Command, Prove, Run, Setup, Test, Update, UpdateAutomatic, Build, Command, Prove, Run, Setup, Test,
}, },
context::{create_context, Context}, context::{create_context, Context},
}; };
@ -176,6 +176,8 @@ pub fn login_incorrect_credentials_or_token() -> Result<()> {
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
#[test] #[test]
pub fn leo_update_and_update_automatic() -> Result<()> { pub fn leo_update_and_update_automatic() -> Result<()> {
use crate::commands::{Update, UpdateAutomatic};
let update = Update { let update = Update {
list: true, list: true,
studio: true, studio: true,

View File

@ -37,6 +37,10 @@ path = "../asg"
version = "1.5.3" version = "1.5.3"
path = "../ast" path = "../ast"
[dependencies.leo-compiler]
version = "1.5.3"
path = "../compiler"
[dependencies.leo-ast-passes] [dependencies.leo-ast-passes]
version = "1.5.3" version = "1.5.3"
path = "../ast-passes" path = "../ast-passes"

2
wasm/tests/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
dist

87
wasm/tests/package-lock.json generated Normal file
View File

@ -0,0 +1,87 @@
{
"name": "parser-wasm-tests",
"version": "0.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "parser-wasm-tests",
"version": "0.1.0",
"license": "GNU",
"dependencies": {
"@types/js-yaml": "^4.0.3",
"@types/node": "^16.9.4",
"js-yaml": "^4.1.0",
"typescript": "^3.9.10"
}
},
"node_modules/@types/js-yaml": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.3.tgz",
"integrity": "sha512-5t9BhoORasuF5uCPr+d5/hdB++zRFUTMIZOzbNkr+jZh3yQht4HYbRDyj9fY8n2TZT30iW9huzav73x4NikqWg=="
},
"node_modules/@types/node": {
"version": "16.9.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.4.tgz",
"integrity": "sha512-KDazLNYAGIuJugdbULwFZULF9qQ13yNWEBFnfVpqlpgAAo6H/qnM9RjBgh0A0kmHf3XxAKLdN5mTIng9iUvVLA=="
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/typescript": {
"version": "3.9.10",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
}
},
"dependencies": {
"@types/js-yaml": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.3.tgz",
"integrity": "sha512-5t9BhoORasuF5uCPr+d5/hdB++zRFUTMIZOzbNkr+jZh3yQht4HYbRDyj9fY8n2TZT30iW9huzav73x4NikqWg=="
},
"@types/node": {
"version": "16.9.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.4.tgz",
"integrity": "sha512-KDazLNYAGIuJugdbULwFZULF9qQ13yNWEBFnfVpqlpgAAo6H/qnM9RjBgh0A0kmHf3XxAKLdN5mTIng9iUvVLA=="
},
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"requires": {
"argparse": "^2.0.1"
}
},
"typescript": {
"version": "3.9.10",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q=="
}
}
}

25
wasm/tests/package.json Normal file
View File

@ -0,0 +1,25 @@
{
"name": "parser-wasm-tests",
"version": "0.1.0",
"description": "Test Framework implementation for compiler tests in WASM",
"main": "index.js",
"scripts": {
"compile": "tsc -p ./"
},
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/aleohq/leo.git"
},
"author": "The Aleo Team <hello@aleo.org>",
"license": "GNU",
"bugs": {
"url": "https://github.com/aleohq/leo/issues"
},
"homepage": "https://github.com/aleohq/leo#readme",
"dependencies": {
"@types/js-yaml": "^4.0.3",
"@types/node": "^16.9.4",
"js-yaml": "^4.1.0",
"typescript": "^3.9.10"
}
}

180
wasm/tests/src/index.ts Normal file
View File

@ -0,0 +1,180 @@
// Copyright (C) 2019-2021 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
import * as fs from 'fs';
import * as path from 'path';
import * as parser from '../../pkg/leo_wasm';
import * as yaml from 'js-yaml';
import {JSON_SCHEMA, CORE_SCHEMA, DEFAULT_SCHEMA} from 'js-yaml';
// Path to the parser tests folder
const TESTS_PATH: string = path.join(__dirname, '../../../tests/parser');
// Path to the test expectations for parser tests
const EXPECTATIONS_PATH: string = path.join(__dirname, '../../../tests/expectations/parser/parser');
// List of folders containing parser tests
const TEST_FOLDERS: string[] = fs.readdirSync(TESTS_PATH);
// Test expectations enum, maps to string values: Pass and Fail
enum Expectation {
Pass = "Pass",
Fail = "Fail"
}
interface TestHeader {
expectation: Expectation,
namespace: string
}
interface TestResult {
filePath: string,
expectation: Expectation,
received: Expectation,
error: string|null
}
// Main function for the tests
(function runTests() {
let results: TestResult[] = [];
for (let folder of TEST_FOLDERS) {
results.push(...walkDir(folder));
}
if (results.length !== 0) {
results.forEach((result) => {
console.log(
'Test failed. Path: %s; Expected: %s; Received: %s',
result.filePath,
result.expectation,
result.received
);
});
process.exit(1);
} else {
console.log('All tests successfully passed.');
process.exit(0);
}
})();
/**
* Test specific file an compare its outputs to the test expectations.
*
* @param filePath Path to the tested file
* @param outFile Contents of the expectation file of there is one
* @returns {TestResult[]} Tests that failed execution, empty means success
*/
function test(filePath: string, outFile: string|null): TestResult[] {
const text = fs.readFileSync(filePath).toString();
// Process the test's contents by cutting off the header
const header = text.slice(text.indexOf('/*') + 2, text.indexOf('*/'));
const testBody = text.slice(text.indexOf('*/') + 2);
const {expectation /* , namespace */} = readHeader(header);
const mismatches: TestResult[] = [];
const outputs: string[] = [];
// Get the tests by splitting by 2 newlines and sanitize each sample.
const samples = testBody
.split('\n\n')
.map((el) => el.trim())
.filter((el) => el.length !== 0);
// Go through each test and run WASM parse function. Check the results agains expectations
// and collect outputs to later compare to saved .out expectations.
for (const sample of samples) {
try {
outputs.push(JSON.parse(parser.parse(sample))); // Parser outputs JSON
if (expectation === Expectation.Fail) { // If expectation was Fail and it passed
mismatches.push({
filePath,
expectation: Expectation.Fail,
received: Expectation.Pass,
error: null
});
}
} catch (error) {
outputs.push(error.toString());
if (expectation === Expectation.Pass) { // If expectation was Pass and it failed
mismatches.push({
error,
filePath,
expectation: Expectation.Pass,
received: Expectation.Fail,
});
}
}
}
// Todo: After AST spans are removed, figure out a way to canonicalize strings
// and get them to the same format as serde's. For now comparing the outputs as
// strings is impossible.
//
// const formedOut = yaml.dump({
// expectation: expectation,
// namespace: namespace,
// outputs: outputs
// }, {schema: DEFAULT_SCHEMA});
return mismatches;
}
/**
* Recursively go through each directory. If a file is met,
* then run test function for this file.
*
* @param fileOrDir
*/
function walkDir(fileOrDir: string): TestResult[] {
const currTarget = path.join(TESTS_PATH, fileOrDir);
let results: TestResult[] = []; // collect test results from sub calls
if (fs.lstatSync(currTarget).isDirectory()) {
for (const entry of fs.readdirSync(currTarget)) {
results.push(...walkDir(path.join(fileOrDir, entry)));
}
} else {
const outFilePath = path.join(EXPECTATIONS_PATH, fileOrDir + '.out');
const outFile = fs.existsSync(outFilePath) ? fs.readFileSync(outFilePath).toString() : null;
return results.concat(test(currTarget, outFile));
}
return results;
}
/**
* Read a test header yaml and transform it into an Object.
*
* @param header
* @returns {TestHeader}
*/
function readHeader(header: string): TestHeader {
const parsed: any = yaml.load(header);
if (!parsed || parsed.constructor !== Object) {
throw "Unable to read test expectations: " + header;
}
return {
expectation: parsed.namespace,
namespace: parsed.expectation,
};
}

13
wasm/tests/tsconfig.json Normal file
View File

@ -0,0 +1,13 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2019",
"allowJs": true,
"lib": ["ES2019"],
"outDir": "dist",
"sourceMap": true,
"strict": true
},
"exclude": ["node_modules", ".vscode-test"],
"include": ["./src/**/*"]
}