Skip to content

Commit 207ae96

Browse files
committed
unit tests
1 parent 04f76d0 commit 207ae96

File tree

7 files changed

+93
-37
lines changed

7 files changed

+93
-37
lines changed

__tests__/code-excution/python.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { CodeContext } from "../../src/types/worker";
2+
import JobWorker from "../../src/worker";
3+
import fs from 'fs'
4+
5+
6+
describe("Python code excution test", () => {
7+
const worker = new JobWorker();
8+
9+
it('should calculate a frequency in string', () => {
10+
fs.readFile(`${__dirname}/../test-code/python/counter.py`, 'utf8', (_, code) => {
11+
const codeContext: CodeContext = {
12+
code: code,
13+
functionName: "calculate"
14+
}
15+
worker
16+
.startContainer("python3", codeContext)
17+
.then((output) => {
18+
expect(output).toBe("Counter({'a': 2, 's': 2, 'w': 2, 'e': 2, 'l': 1, 'd': 1, 'k': 1})")
19+
})
20+
.catch((e) => console.log(e));
21+
});
22+
})
23+
})
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
from collections import Counter
2-
str = "asldkasweew"
3-
print(Counter(str))
2+
3+
class Execute:
4+
def calculate(self):
5+
str = "asldkasweew"
6+
print(Counter(str))
7+

__tests__/worker.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { ContainerInitialization } from "../src/types/worker";
1+
import { mainClassName } from "../src/config";
2+
import { CodeContext, ContainerInitialization } from "../src/types/worker";
23
import JobWorker from "../src/worker";
3-
import fs from 'fs'
4+
45

56
describe("Docker initialization test", () => {
67
const worker = new JobWorker();
@@ -27,17 +28,15 @@ describe("Docker initialization test", () => {
2728
});
2829

2930

30-
describe("Python code excution test", () => {
31+
32+
describe("Transform into executable", () => {
3133
const worker = new JobWorker();
32-
33-
it('should calculate a frequency in string', () => {
34-
fs.readFile(`${__dirname}/test-code/python/counter.py`, 'utf8', (_, code) => {
35-
worker
36-
.startContainer("python3", code)
37-
.then((output) => {
38-
expect(output).toBe("Counter({'a': 2, 's': 2, 'w': 2, 'e': 2, 'l': 1, 'd': 1, 'k': 1})")
39-
})
40-
.catch((e) => console.log(e));
41-
});
42-
})
34+
it('should instantiate an object and execute the function', () => {
35+
const functionName = "solution"
36+
const code = worker.transformCodeIntoExecutable("python3", {
37+
code: "",
38+
functionName: functionName
39+
})
40+
expect(code).toBe(`\n${mainClassName}().${functionName}()`)
41+
})
4342
})

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"scripts": {
33
"start:dev": "npx nodemon",
44
"build": "rimraf ./build && tsc",
5-
"test": "jest"
5+
"test": "jest",
6+
"ct": "rm ./temp/*"
67
},
78
"devDependencies": {
89
"@types/jest": "^29.5.0",

src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const mainClassName = "Execute"

src/types/worker.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
1-
export type container = "python3" | "javascript";
1+
export type language = "python3" | "javascript";
22
export type fileFormat = "py" | "js";
33

4+
export interface CodeContext {
5+
/**
6+
* raw string code to be excuted
7+
*/
8+
code: string
9+
10+
/**
11+
* A method name in class to be executed
12+
*/
13+
functionName: string
14+
}
15+
416
export interface ContainerInitialization {
517
/**
618
* Indicates whether it successfully created a contaienr
@@ -49,7 +61,7 @@ export interface JobStatus {
4961
/**
5062
* the raw data of the target code
5163
*/
52-
context: string;
64+
context: CodeContext;
5365

5466
/**
5567
* Newly created ontainer ID if exists

src/worker.ts

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,30 @@ import crypto from "crypto";
33
import fs from "fs";
44
import path from "path";
55
import {
6+
CodeContext,
67
ContainerInitialization,
78
JobStatus,
89
WriteFileStatus,
9-
container,
10+
language,
1011
fileFormat,
1112
} from "./types/worker";
13+
import { mainClassName } from "./config";
1214

1315
class JobWorker {
1416
constructor() {}
1517

16-
private _fileFormats: Record<container, fileFormat> = {
18+
private _fileFormats: Record<language, fileFormat> = {
1719
python3: "py",
1820
javascript: "js",
1921
};
2022
/**
2123
* Creates an appropriate docker container
2224
* to execute the target code
2325
*/
24-
createContainer(container: container): Promise<ContainerInitialization> {
26+
createContainer(language: language): Promise<ContainerInitialization> {
2527
return new Promise((resolve, reject) => {
26-
const initCommand = `docker create ${container}`;
27-
if (!(container in this._fileFormats)) {
28+
const initCommand = `docker create ${language}`;
29+
if (!(language in this._fileFormats)) {
2830
return reject({
2931
error: true,
3032
errorMessage: "Invalid container name.",
@@ -53,24 +55,38 @@ class JobWorker {
5355
}
5456

5557
/**
56-
* writes a code into a temp file
58+
* Returns a piece of code that executes a function in a class
59+
* language specific, so defined using switch cases
5760
*/
61+
transformCodeIntoExecutable(language: language, context: CodeContext) {
62+
switch(language) {
63+
case "python3": {
64+
return `\n${mainClassName}().${context.functionName}()`
65+
}
66+
}
67+
}
5868

69+
/**
70+
* writes a code into a temp file
71+
*/
5972
private async writeFile(
60-
container: container,
61-
context: string
73+
language: language,
74+
context: CodeContext
6275
): Promise<WriteFileStatus> {
6376
return new Promise((resolve, reject) => {
6477
const fileName = crypto.randomBytes(32).toString("hex");
65-
const fileFormat = this._fileFormats[container];
78+
const fileFormat = this._fileFormats[language];
6679
const filePath = path.join(
6780
__dirname,
6881
"..",
6982
"temp",
7083
`${fileName}.${fileFormat}`
7184
);
7285

73-
fs.writeFile(filePath, context, (error) => {
86+
// appending a line to execute a specific function
87+
context.code += this.transformCodeIntoExecutable(language, context)
88+
89+
fs.writeFile(filePath, context.code, (error) => {
7490
if (error) {
7591
reject(error.message);
7692
} else {
@@ -104,11 +120,11 @@ class JobWorker {
104120
*/
105121
copyContext(
106122
containerID: string,
107-
container: container,
108-
context: string
123+
language: language,
124+
context: CodeContext
109125
): Promise<string> {
110126
return new Promise(async (resolve, reject) => {
111-
this.writeFile(container, context)
127+
this.writeFile(language, context)
112128
.then(({ filePath, fileFormat }) => {
113129
const initCommand = `docker cp ${filePath} ${containerID}:/src/target.${fileFormat}`;
114130
child.exec(initCommand, (error, containerID, stderr) => {
@@ -132,12 +148,12 @@ class JobWorker {
132148
* 1] Creates a new container
133149
* 2] Copies the code into the contaienr
134150
*/
135-
initContainer(container: container, context: string): Promise<JobStatus> {
151+
initContainer(language: language, context: CodeContext): Promise<JobStatus> {
136152
return new Promise(async (resolve, reject) => {
137-
this.createContainer(container)
153+
this.createContainer(language)
138154
.then(async ({ containerID, error, errorMessage }) => {
139155
if (error) return new Error(errorMessage);
140-
return this.copyContext(containerID, container, context)
156+
return this.copyContext(containerID, language, context)
141157
.then(() => {
142158
resolve({
143159
message: `Job has succedded.`,
@@ -167,9 +183,9 @@ class JobWorker {
167183
* 1] Spin up the container
168184
* 2] Record the output from the container
169185
*/
170-
startContainer(container: container, context: string): Promise<string> {
186+
startContainer(language: language, context: CodeContext): Promise<string> {
171187
return new Promise((resolve, reject) => {
172-
this.initContainer(container, context)
188+
this.initContainer(language, context)
173189
.then((jobStatus: JobStatus) => {
174190
if (!jobStatus.jobFailed && jobStatus.containerID) {
175191
const startContainer = `docker start -a ${jobStatus.containerID}`;

0 commit comments

Comments
 (0)