Skip to content

Commit

Permalink
fix(rce): increase test limitations
Browse files Browse the repository at this point in the history
  • Loading branch information
aldy505 committed Mar 3, 2024
1 parent 40ecb0c commit 35691af
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 238 deletions.
2 changes: 2 additions & 0 deletions rce/src/Error.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
export class ServerError extends Error {
constructor(public readonly reason: string) {
super(reason);
this.name = "ServerError";
}
}

export class ClientError extends Error {
constructor(public readonly reason: string, public readonly code = 400) {
super(reason);
this.code = code;
this.name = "ClientError";
}
}
78 changes: 41 additions & 37 deletions rce/src/runtime/acquire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type Semver = {
* If the length of the array is 4, we should examine the 3rd index and check if it's compatible with our edition.
* We'll ignore every value that comes after the 3rd index.
*/
function parseSemver(tags: string[]): Semver {
export function parseSemver(tags: string[]): Semver {
const semver: Semver = {
major: 0,
minor: 0,
Expand Down Expand Up @@ -85,42 +85,7 @@ function parseSemver(tags: string[]): Semver {
return semver;
}

export async function acquireRuntime() {
const runtimes: Runtime[] = [];
const packagesDir = await fs.readdir(
path.resolve(fileURLToPath(import.meta.url), "../../packages"),
{ withFileTypes: true }
);

for await (const packageDir of packagesDir) {
if (packageDir.isDirectory()) {
const packageDirPath = path.resolve(
fileURLToPath(import.meta.url),
"../../packages",
packageDir.name
);
const configFilePath = path.resolve(packageDirPath, "config.toml");
const configFile = await fs.readFile(configFilePath, "utf8");
const configObject = toml.parse(configFile);
const runtime = new Runtime(
configObject.language,
configObject.version,
false,
configObject.extension,
configObject.compiled,
configObject.build_command,
configObject.run_command,
configObject.aliases,
Object.fromEntries(configObject.environment.map((o: string) => o.split("="))),
configObject.should_limit_memory,
configObject.memory_limit * 1024 * 1024,
configObject.process_limit,
configObject.allowed_entrypoints
);
runtimes.push(runtime);
}
}

export function attemptToSetLatestForRuntimes(runtimes: Runtime[]): Runtime[] {
// Attempt to set the "latest" tag to true for each language
const languageVersions: LanguageVersion[] = [];
for (let i = 0; i < runtimes.length; i++) {
Expand Down Expand Up @@ -173,3 +138,42 @@ export async function acquireRuntime() {

return runtimes;
}

export async function acquireRuntime() {
const runtimes: Runtime[] = [];
const packagesDir = await fs.readdir(
path.resolve(fileURLToPath(import.meta.url), "../../packages"),
{ withFileTypes: true }
);

for await (const packageDir of packagesDir) {
if (packageDir.isDirectory()) {
const packageDirPath = path.resolve(
fileURLToPath(import.meta.url),
"../../packages",
packageDir.name
);
const configFilePath = path.resolve(packageDirPath, "config.toml");
const configFile = await fs.readFile(configFilePath, "utf8");
const configObject = toml.parse(configFile);
const runtime = new Runtime(
configObject.language,
configObject.version,
false,
configObject.extension,
configObject.compiled,
configObject.build_command,
configObject.run_command,
configObject.aliases,
Object.fromEntries(configObject.environment.map((o: string) => o.split("="))),
configObject.should_limit_memory,
configObject.memory_limit * 1024 * 1024,
configObject.process_limit,
configObject.allowed_entrypoints
);
runtimes.push(runtime);
}
}

return attemptToSetLatestForRuntimes(runtimes);
}

Check warning on line 179 in rce/src/runtime/acquire.ts

View check run for this annotation

Codecov / codecov/patch

rce/src/runtime/acquire.ts#L142-L179

Added lines #L142 - L179 were not covered by tests
19 changes: 19 additions & 0 deletions rce/tests/error.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ClientError, ServerError } from "../src/Error";
import { expect, test } from "vitest";

test("ServerError", () => {
const serverError = new ServerError("Unexpected input");
expect(serverError).toBeInstanceOf(Error);
expect(serverError.message).toStrictEqual("Unexpected input");
expect(serverError.reason).toStrictEqual("Unexpected input");
expect(serverError.name).toStrictEqual("ServerError");
});

test("ClientError", () => {
const clientError = new ClientError("Unexpected input", 403);
expect(clientError).toBeInstanceOf(Error);
expect(clientError.message).toStrictEqual("Unexpected input");
expect(clientError.reason).toStrictEqual("Unexpected input");
expect(clientError.name).toStrictEqual("ClientError");
expect(clientError.code).toStrictEqual(403);
});
4 changes: 2 additions & 2 deletions rce/tests/job.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ test.sequential("should be able to run a file - NodeJS", async (t) => {
}

const currentUser = os.userInfo();
const runtime = new Runtime("Javascript", "16.14.0", true, "js", false, [], ["node", "{file}"], ["node", "js"], {}, true, 512 * 1024 * 1024, 256, 1);
const runtime = new Runtime("Javascript", "16.14.0", true, "js", false, [], ["node", "{file}"], ["node", "js"], {}, false, 512 * 1024 * 1024, 4096, 1);
const job = new Job(
{ uid: currentUser.uid, gid: currentUser.gid, free: true, username: currentUser.username },
runtime,
Expand Down Expand Up @@ -235,7 +235,7 @@ test.sequential("should be able to run multiple files - NodeJS", async (t) => {
}

const currentUser = os.userInfo();
const runtime = new Runtime("Javascript", "16.14.0", true, "js", false, [], ["node", "{file}"], ["node", "js"], {}, true, 512 * 1024 * 1024, 256, 1);
const runtime = new Runtime("Javascript", "16.14.0", true, "js", false, [], ["node", "{file}"], ["node", "js"], {}, false, 512 * 1024 * 1024, 4096, 1);
const job = new Job(
{ uid: currentUser.uid, gid: currentUser.gid, free: true, username: currentUser.username },
runtime,
Expand Down
202 changes: 3 additions & 199 deletions rce/tests/runtime.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { test, expect } from "vitest";
import { Runtime } from "../src/runtime/runtime.js";
import { attemptToSetLatestForRuntimes, parseSemver } from "../src/runtime/acquire.js";

test("should throw error on invalid runtime parameters", () => {
expect(
Expand Down Expand Up @@ -34,145 +35,13 @@ test("should throw error on invalid processLimit parameters", () => {
});

test("should be able to parse semver", () => {
type Semver = {
major: number,
minor: number,
patch: number,
edition: "latest" | "rc" | "beta" | "alpha" | "nightly"
}

function parseSemver(tags: string[]): Semver {
const semver: Semver = {
major: 0,
minor: 0,
patch: 0,
edition: "latest"
};

for (let i = 0; i < tags.length; i++) {
switch (i) {
case 0: {
const parsedNumber = Number.parseInt(tags[i]);
if (Number.isNaN(parsedNumber)) {
break;
}

semver.major = parsedNumber;
break;
}
case 1: {
const parsedNumber = Number.parseInt(tags[i]);
if (Number.isNaN(parsedNumber)) {
break;
}

semver.minor = parsedNumber;
break;
}
case 2: {
const parsedNumber = Number.parseInt(tags[i]);
if (Number.isNaN(parsedNumber)) {
break;
}

semver.patch = parsedNumber;
break;
}
case 3: {
if (tags[i].startsWith("rc")) {
semver.edition = "rc";
} else if (tags[i].startsWith("beta")) {
semver.edition = "beta";
} else if (tags[i].startsWith("alpha")) {
semver.edition = "alpha";
} else if (tags[i] !== "") {
semver.edition = "nightly";
}
}
}
}

return semver;
}

expect(parseSemver(["3"])).toMatchObject({ major: 3, minor: 0, patch: 0, edition: "latest" });
expect(parseSemver(["16", "15", "8", "rc-8"])).toMatchObject({ major: 16, minor: 15, patch: 8, edition: "rc" });
expect(parseSemver(["lorem", "ipsum", "dolor", "sit", "amet"])).toMatchObject({ major: 0, minor: 0, patch: 0, edition: "nightly" });
});

test("should be able to search for latest tag", () => {
type LanguageVersion = {
language: string,
versions: Array<
{
index: number,
version: string
}
>
}

type Semver = {
major: number,
minor: number,
patch: number,
edition: "latest" | "rc" | "beta" | "alpha" | "nightly"
}

function parseSemver(tags: string[]): Semver {
const semver: Semver = {
major: 0,
minor: 0,
patch: 0,
edition: "latest"
};

for (let i = 0; i < tags.length; i++) {
switch (i) {
case 0: {
const parsedNumber = Number.parseInt(tags[i]);
if (Number.isNaN(parsedNumber)) {
break;
}

semver.major = parsedNumber;
break;
}
case 1: {
const parsedNumber = Number.parseInt(tags[i]);
if (Number.isNaN(parsedNumber)) {
break;
}

semver.minor = parsedNumber;
break;
}
case 2: {
const parsedNumber = Number.parseInt(tags[i]);
if (Number.isNaN(parsedNumber)) {
break;
}

semver.patch = parsedNumber;
break;
}
case 3: {
if (tags[i].startsWith("rc")) {
semver.edition = "rc";
} else if (tags[i].startsWith("beta")) {
semver.edition = "beta";
} else if (tags[i].startsWith("alpha")) {
semver.edition = "alpha";
} else if (tags[i] !== "") {
semver.edition = "nightly";
}
}
}
}

return semver;
}

const runtimes: Runtime[] = [
const rawRuntimes: Runtime[] = [
new Runtime("Java", "17", false, "java", true, ["javac", "build"], ["javac", "run"], ["java"], {}, false, 500, 100, 1),
new Runtime("Java", "11", false, "java", true, ["javac", "build"], ["javac", "run"], ["java"], {}, false, 500, 100, 1),
new Runtime("Java", "8", false, "java", true, ["javac", "build"], ["javac", "run"], ["java"], {}, false, 500, 100, 1),
Expand All @@ -183,72 +52,7 @@ test("should be able to search for latest tag", () => {
new Runtime("Nodejs", "14.6.11", false, "js", false, [], ["node", "run"], ["node"], {}, false, 500, 100, 1)
];

// Attempt to set the "latest" tag to true for each language
const languageVersions: LanguageVersion[] = [];
for (let i = 0; i < runtimes.length; i++) {
const languageIndex = languageVersions.findIndex(r => r.language === runtimes[i].language);
if (languageIndex === -1) {
languageVersions.push({ language: runtimes[i].language, versions: [{ index: i, version: runtimes[i].version }] });
continue;
}

languageVersions[languageIndex].versions.push({ index: i, version: runtimes[i].version });
}

for (const language of languageVersions) {
// Don't waste time sorting. If the length of language.versions is 1
// then it must be the latest version.
if (language.versions.length === 1) {
runtimes[language.versions[0].index].markAsLatest();
continue;
}

// Otherwise, we'll sort them as normal case.
// Note that in Javascript, this sort function sorts the array in place.
// Documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#return_value
language.versions.sort((a, b): number => {
// Parse the semver
const aVersionTag = a.version.split(/\.|-/gm, 4);
const bVersionTag = b.version.split(/\.|-/gm, 4);

// Normal semver consist of major.minor.patch-edition
const aSemver: Semver = parseSemver(aVersionTag);
const bSemver: Semver = parseSemver(bVersionTag);

if (aSemver.major === bSemver.major) {
if (aSemver.minor === bSemver.minor) {
if (aSemver.patch === bSemver.patch) {
if (aSemver.edition === bSemver.edition) {
return 0;
}

// I'm too lazy to write the rest of it. We'll just avoid nightly.
if (aSemver.edition === "nightly" || bSemver.edition === "nightly") {
return 1;
}

// Otherwise, we'll just return -1
return -1;
} else if (aSemver.patch > bSemver.patch) {
return -1;
}

return 1;
} else if (aSemver.minor > bSemver.minor) {
return -1;
}

return 1;
} else if (aSemver.major > bSemver.major) {
return -1;
}

return 1;
});

const latestIndex = language.versions[0].index;
runtimes[latestIndex].markAsLatest();
}
const runtimes = attemptToSetLatestForRuntimes(rawRuntimes);

expect(runtimes[0].latest).toStrictEqual(true);
expect(runtimes[1].latest).toStrictEqual(false);
Expand Down

0 comments on commit 35691af

Please sign in to comment.