Skip to content

Add test builder #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions cli/src/builders/make/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export class MakeProject {
private noChildren: boolean = false;
private settings: iProject;
private folderSettings: {[folder: string]: FolderOptions} = {};
private pseudoTargets: {[name: string]: string[]} = {};

constructor(private cwd: string, private targets: Targets) {
this.settings = MakeProject.getDefaultSettings();
Expand All @@ -67,12 +68,11 @@ export class MakeProject {
command: `CRTPGM`,
parameters: {
pgm: `$(BIN_LIB)/$*`,
entry: `$*`,
modules: `*MODULES`,
entmod: `$*`,
module: `*MODULES`,
tgtrls: `*CURRENT`,
tgtccsid: `*JOB`,
bnddir: `$(BNDDIR)`,
dftactgrp: `*NO`
replace: `*YES`
}
},
"pgm.rpgle": {
Expand Down Expand Up @@ -334,15 +334,31 @@ export class MakeProject {
}

public getMakefile(specificObjects?: ILEObject[]) {
let customTargetLines = [];

for (const pseudoTarget in this.pseudoTargets) {
customTargetLines.push(
`${pseudoTarget}:`,
...this.pseudoTargets[pseudoTarget].map(t => `\t${t}`),
``
);
}

return [
...this.generateHeader(),
``,
...this.generateTargets(specificObjects),
``,
...this.generateGenericRules()
...this.generateGenericRules(),
``,
...customTargetLines
];
}

addPseudoTarget(name: string, commands: string[]) {
this.pseudoTargets[name] = commands;
}

public generateHeader(): string[] {
let baseBinders = [
...(this.targets.binderRequired() ? [`($(BIN_LIB)/$(APP_BNDDIR))`] : []),
Expand Down
3 changes: 2 additions & 1 deletion cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ export let cliSettings = {
fileList: false,
lookupFiles: [] as string[],
userBranch: ``,
makeFileNoChildren: false
makeFileNoChildren: false,
writeTestRunner: false,
};

export function infoOut(message: string) {
Expand Down
32 changes: 31 additions & 1 deletion cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { BobProject } from "./builders/bob";
import { ImpactMarkdown } from "./builders/imd";
import { allExtensions } from "./extensions";
import { getBranchLibraryName } from "./builders/environment";
import { getFiles, renameFiles, replaceIncludes } from './utils';
import { getFiles, mkdir, renameFiles, replaceIncludes } from './utils';
import { TestBuilder } from './tester';

const isCli = process.argv.length >= 2 && process.argv[1].endsWith(`so`);

Expand Down Expand Up @@ -78,6 +79,11 @@ async function main() {
cliSettings.fileList = true;
break;

case `-wt`:
case `--withTests`:
cliSettings.writeTestRunner = true;
break;

case `-h`:
case `--help`:
console.log(``);
Expand Down Expand Up @@ -192,6 +198,22 @@ async function main() {
}
}

const testModules = targets.getResolvedObjects().filter(o => o.testModule);
if (testModules.length > 0) {
const testBuilder = new TestBuilder(testModules, targets.logger);
const results = testBuilder.getRunnerStructure();

if (cliSettings.writeTestRunner) {
targets.storeResolved(path.join(cwd, TestBuilder.getRunnerSourcePath()), results.newObjects.module);
targets.storeResolved(path.join(cwd, TestBuilder.getRunnerSourcePath(true)), results.newObjects.program);
targets.addNewTarget(results.newObjects.program);

const modulePath = path.join(cwd, TestBuilder.getRunnerSourcePath(false));
mkdir(path.dirname(modulePath)); // Ensure the directory exists
writeFileSync(modulePath, results.lines.join(`\n`));
}
}

switch (cliSettings.buildFile) {
case `bob`:
const bobProj = new BobProject(targets);
Expand All @@ -206,6 +228,14 @@ async function main() {
const makeProj = new MakeProject(cwd, targets);
makeProj.setNoChildrenInBuild(cliSettings.makeFileNoChildren);

if (cliSettings.writeTestRunner) {
makeProj.addPseudoTarget(`test`, [
`liblist -c $(BIN_LIB);\\`,
`liblist -a $(LIBL);\\`,
...TestBuilder.getRunnerPaseCommands()
]);
}

let specificObjects: ILEObject[] | undefined = cliSettings.fileList ? cliSettings.lookupFiles.map(f => targets.getResolvedObject(path.join(cwd, f))).filter(o => o) : undefined;
writeFileSync(path.join(cwd, `makefile`), makeProj.getMakefile(specificObjects).join(`\n`));

Expand Down
28 changes: 14 additions & 14 deletions cli/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,41 +28,41 @@ export class Logger {

constructor() {}

flush(specificPath?: string) {
if (specificPath) {
this.logs[specificPath] = [];
flush(relativePath?: string) {
if (relativePath) {
this.logs[relativePath] = [];
} else {
this.logs = {}
}
}

fileLog(path: string, log: FileLog) {
fileLog(relativePath: string, log: FileLog) {
switch (log.type) {
case `info`: infoOut(`${path}${log.line ? `:${log.line}` : ``} - ${log.message}`); break;
case `warning`: warningOut(`${path}${log.line ? `:${log.line}` : ``} - ${log.message}`); break;
case `info`: infoOut(`${relativePath}${log.line ? `:${log.line}` : ``} - ${log.message}`); break;
case `warning`: warningOut(`${relativePath}${log.line ? `:${log.line}` : ``} - ${log.message}`); break;
}

if (!this.logs[path]) {
this.logs[path] = [];
if (!this.logs[relativePath]) {
this.logs[relativePath] = [];
}

if (log.type === `rename`) {
// If this path already contains a rename, ignore this
if (this.logs[path].some(l => l.type === `rename`)) return;
if (this.logs[relativePath].some(l => l.type === `rename`)) return;
}

this.logs[path].push(log);
this.logs[relativePath].push(log);
}

exists(path: string, type: LogType) {
return this.logs[path] && this.logs[path].some(l => l.type === type)
exists(relativePath: string, type: LogType) {
return this.logs[relativePath] && this.logs[relativePath].some(l => l.type === type)
}

getAllLogs() {
return this.logs;
}

getLogsFor(path: string): FileLog[]|undefined {
return this.logs[path];
getLogsFor(relativePath: string): FileLog[]|undefined {
return this.logs[relativePath];
}
}
87 changes: 50 additions & 37 deletions cli/src/targets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface ILEObject {
systemName: string;
longName?: string;
type: ObjectType;
testModule?: boolean;
text?: string,
relativePath?: string;
extension?: string;
Expand Down Expand Up @@ -119,7 +120,7 @@ export class Targets {
return path.relative(this.cwd, fullPath);
}

private storeResolved(localPath: string, ileObject: ILEObject) {
public storeResolved(localPath: string, ileObject: ILEObject) {
this.resolvedObjects[localPath] = ileObject;
}

Expand All @@ -132,19 +133,30 @@ export class Targets {
const detail = path.parse(localPath);
const relativePath = this.getRelative(localPath);

let subTypeLength = 0;
const isProgram = detail.name.toUpperCase().endsWith(`.PGM`);
const name = getSystemNameFromPath(isProgram ? detail.name.substring(0, detail.name.length - 4) : detail.name);
const isTestModule = detail.name.toUpperCase().endsWith(`.TEST`);

if (isProgram) subTypeLength = 4;
if (isTestModule) subTypeLength = 5;

const validBaseName = (subTypeLength > 0 ? detail.name.substring(0, detail.name.length - subTypeLength) : detail.name);
const systemName = getSystemNameFromPath((isTestModule ? `t_` : ``) + validBaseName);
const extension = detail.ext.length > 1 ? detail.ext.substring(1) : detail.ext;
const type: ObjectType = (isProgram ? "PGM" : this.getObjectType(relativePath, extension));

const theObject: ILEObject = {
systemName: name,
systemName,
type: type,
text: newText,
relativePath,
extension
};

// The reason we assign seperately is because
// we don't need to clog up the result
if (isTestModule) theObject.testModule = true;

this.storeResolved(localPath, theObject);

return theObject;
Expand Down Expand Up @@ -940,10 +952,6 @@ export class Targets {
const pathDetail = path.parse(localPath);
const sourceName = pathDetail.base;
const ileObject = this.resolvePathToObject(localPath, options.text);
const target: ILEObjectTarget = {
...ileObject,
deps: []
};

infoOut(`${ileObject.systemName}.${ileObject.type}: ${ileObject.relativePath}`);

Expand Down Expand Up @@ -1054,6 +1062,40 @@ export class Targets {
});
}

// define internal imports
ileObject.imports = cache.procedures
.filter((proc: any) => proc.keyword[`EXTPROC`])
.map(ref => {
const keyword = ref.keyword;
let importName: string = ref.name;
const extproc: string | boolean = keyword[`EXTPROC`];
if (extproc) {
if (extproc === true) importName = ref.name;
else importName = extproc;
}

if (importName.includes(`:`)) {
const parmParms = importName.split(`:`);
importName = parmParms.filter(p => !p.startsWith(`*`)).join(``);
}

importName = trimQuotes(importName);

return importName;
});

// define exported functions
if (cache.keyword[`NOMAIN`]) {
ileObject.exports = cache.procedures
.filter((proc: any) => proc.keyword[`EXPORT`])
.map(ref => ref.name.toUpperCase());
}

const target: ILEObjectTarget = {
...ileObject,
deps: []
};

// Find external programs
cache.procedures
.filter((proc: any) => proc.keyword[`EXTPGM`])
Expand Down Expand Up @@ -1245,35 +1287,6 @@ export class Targets {
const resolvedObject = this.searchForObject({systemName: ileObject.systemName, type: `CMD`}, ileObject);
if (resolvedObject) this.createOrAppend(resolvedObject, target);

// define internal imports
target.imports = cache.procedures
.filter((proc: any) => proc.keyword[`EXTPROC`])
.map(ref => {
const keyword = ref.keyword;
let importName: string = ref.name;
const extproc: string | boolean = keyword[`EXTPROC`];
if (extproc) {
if (extproc === true) importName = ref.name;
else importName = extproc;
}

if (importName.includes(`:`)) {
const parmParms = importName.split(`:`);
importName = parmParms.filter(p => !p.startsWith(`*`)).join(``);
}

importName = trimQuotes(importName);

return importName;
});

// define exported functions
if (cache.keyword[`NOMAIN`]) {
target.exports = cache.procedures
.filter((proc: any) => proc.keyword[`EXPORT`])
.map(ref => ref.name.toUpperCase());
}

if (target.deps.length > 0)
infoOut(`Depends on: ${target.deps.map(d => `${d.systemName}.${d.type}`).join(` `)}`);

Expand Down Expand Up @@ -1468,7 +1481,7 @@ export class Targets {
return existingTarget;
}

private addNewTarget(dep: ILEObjectTarget) {
public addNewTarget(dep: ILEObjectTarget) {
this.targets[`${dep.systemName}.${dep.type}`] = dep;
}

Expand Down
Loading