Skip to content
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

Integration test of builders #88

Merged
merged 10 commits into from
Oct 16, 2024
Merged
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
1 change: 1 addition & 0 deletions apps/cli/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ node_modules
oclif.manifest.json
src/contracts.ts
src/graphql/
test/builder/output
1 change: 1 addition & 0 deletions apps/cli/src/builder/directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const build = async (
cwd: destination,
image: sdkImage,
});
break;
}
}
} finally {
Expand Down
1 change: 0 additions & 1 deletion apps/cli/src/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
"--workdir",
"/work",
"--interactive",
"--tty",
"--user",
`${userInfo.uid}:${userInfo.gid}`,
];
Expand Down Expand Up @@ -62,7 +61,7 @@
) => {
const result = spawnSync(command, args, options);
if (result.error) {
const code = (result.error as any).code;

Check warning on line 64 in apps/cli/src/exec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
if (code === "ENOENT" && options.image) {
console.warn(
`error executing '${command}', falling back to docker execution using image '${options.image}'`,
Expand Down
5 changes: 5 additions & 0 deletions apps/cli/test/builder/data/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM --platform=linux/riscv64 ubuntu:22.04 AS test
ADD ./file2 .

FROM --platform=linux/riscv64 ubuntu:22.04
ADD ./file1 .
2 changes: 2 additions & 0 deletions apps/cli/test/builder/data/Dockerfile.nonriscv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM scratch
ADD ./file1 .
Binary file added apps/cli/test/builder/data/data.ext2
Binary file not shown.
Binary file added apps/cli/test/builder/data/data.sqfs
Binary file not shown.
Binary file added apps/cli/test/builder/data/data.tar
Binary file not shown.
Empty file.
Empty file.
1 change: 1 addition & 0 deletions apps/cli/test/builder/data/sample1/file1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lorem ipsum
1 change: 1 addition & 0 deletions apps/cli/test/builder/data/sample1/file2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lorem ipsum lorem ipsum
97 changes: 97 additions & 0 deletions apps/cli/test/builder/directory.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import fs from "fs-extra";
import path from "path";
import { describe, expect } from "vitest";
import { build } from "../../src/builder/directory";
import { DirectoryDriveConfig } from "../../src/config";
import { tmpdirTest } from "./tmpdirTest";

describe("when building with the directory builder", () => {
const image = "cartesi/sdk:0.11.0";

tmpdirTest(
"should fail when the directory doesn't exists",
async ({ tmpdir }) => {
const destination = tmpdir;
const drive: DirectoryDriveConfig = {
builder: "directory",
directory: path.join(__dirname, "data", "invalid"),
extraSize: 0,
format: "ext2",
};
await expect(
build("root", drive, image, destination),
).rejects.toThrow("no such file or directory");
},
);

tmpdirTest(
"should fail when the directory is empty",
async ({ tmpdir }) => {
const destination = tmpdir;
const directory = path.join(__dirname, "data", "empty");
fs.ensureDirSync(directory);
const drive: DirectoryDriveConfig = {
builder: "directory",
directory,
extraSize: 0,
format: "ext2",
};
await expect(
build("root", drive, image, destination),
).rejects.toThrow("too few blocks");
},
);

tmpdirTest(
"should pass when the directory is empty but extra size is defined",
async ({ tmpdir }) => {
const destination = tmpdir;
const directory = path.join(__dirname, "data", "empty");
fs.ensureDirSync(directory);
const drive: DirectoryDriveConfig = {
builder: "directory",
directory,
extraSize: 1024 * 1024, // 1Mb
format: "ext2",
};
await build("root", drive, image, destination);
const filename = path.join(destination, "root.ext2");
const stat = fs.statSync(filename);
expect(stat.size).toEqual(1069056);
},
);

tmpdirTest(
"should pass for a populated directory (ext2)",
async ({ tmpdir }) => {
const destination = tmpdir;
const drive: DirectoryDriveConfig = {
builder: "directory",
directory: path.join(__dirname, "data", "sample1"),
extraSize: 0,
format: "ext2",
};
await build("root", drive, image, destination);
const filename = path.join(destination, "root.ext2");
const stat = fs.statSync(filename);
expect(stat.size).toEqual(32768);
},
);

tmpdirTest(
"should pass for a populated directory (sqfs)",
async ({ tmpdir }) => {
const destination = tmpdir;
const drive: DirectoryDriveConfig = {
builder: "directory",
directory: path.join(__dirname, "data", "sample1"),
extraSize: 0,
format: "sqfs",
};
await build("root", drive, image, destination);
const filename = path.join(destination, "root.sqfs");
const stat = fs.statSync(filename);
expect(stat.size).toEqual(4096);
},
);
});
106 changes: 106 additions & 0 deletions apps/cli/test/builder/docker.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import fs from "fs-extra";
import { beforeEach } from "node:test";
import path from "path";
import { describe, expect } from "vitest";
import { build } from "../../src/builder/docker";
import { DockerDriveConfig } from "../../src/config";
import { tmpdirTest } from "./tmpdirTest";

describe("when building with the docker builder", () => {
const image = "cartesi/sdk:0.11.0";

beforeEach(({ name }) => {
fs.mkdirpSync(path.join(__dirname, "output", name));
});

tmpdirTest("should fail without correct context", async ({ tmpdir }) => {
const destination = tmpdir;
const drive: DockerDriveConfig = {
builder: "docker",
context: ".",
dockerfile: "Dockerfile",
extraSize: 0,
format: "ext2",
tags: [],
image: undefined,
target: undefined,
};
await expect(build("root", drive, image, destination)).rejects.toThrow(
"exit code 1",
);
});

tmpdirTest("should fail a non-riscv image", async ({ tmpdir }) => {
const destination = tmpdir;
const drive: DockerDriveConfig = {
builder: "docker",
context: path.join(__dirname, "data"),
dockerfile: path.join(__dirname, "data", "Dockerfile.nonriscv"),
extraSize: 0,
format: "ext2",
tags: [],
image: undefined,
target: undefined,
};
await expect(build("root", drive, image, destination)).rejects.toThrow(
"Expected riscv64",
);
});

tmpdirTest(
"should build an ext2 drive with a target definition",
async ({ tmpdir }) => {
const destination = tmpdir;
const drive: DockerDriveConfig = {
builder: "docker",
context: path.join(__dirname, "data"),
dockerfile: path.join(__dirname, "data", "Dockerfile"),
extraSize: 0,
format: "ext2",
tags: [],
image: undefined,
target: "test",
};
await build("root", drive, image, destination);
const filename = path.join(destination, "root.ext2");
const stat = fs.statSync(filename);
expect(stat.size).toEqual(76087296);
},
);

tmpdirTest("should build an ext2 drive", async ({ tmpdir }) => {
const destination = tmpdir;
const drive: DockerDriveConfig = {
builder: "docker",
context: path.join(__dirname, "data"),
dockerfile: path.join(__dirname, "data", "Dockerfile"),
extraSize: 0,
format: "ext2",
tags: [],
image: undefined,
target: undefined,
};
await build("root", drive, image, destination);
const filename = path.join(destination, "root.ext2");
const stat = fs.statSync(filename);
expect(stat.size).toEqual(76087296);
});

tmpdirTest.skip("should build a sqfs drive", async ({ tmpdir }) => {
const destination = tmpdir;
const drive: DockerDriveConfig = {
builder: "docker",
context: path.join(__dirname, "data"),
dockerfile: path.join(__dirname, "data", "Dockerfile"),
extraSize: 0,
format: "sqfs",
tags: [],
image: undefined,
target: undefined,
};
await build("root", drive, image, destination);
const filename = path.join(destination, "root.sqfs");
const stat = fs.statSync(filename);
expect(stat.size).toEqual(29327360);
});
});
56 changes: 56 additions & 0 deletions apps/cli/test/builder/empty.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import fs from "fs-extra";
import path from "path";
import { describe, expect } from "vitest";
import { build } from "../../src/builder/empty";
import { EmptyDriveConfig } from "../../src/config";
import { tmpdirTest } from "./tmpdirTest";

describe("when building with the empty builder", () => {
const image = "cartesi/sdk:0.11.0";

tmpdirTest("should fail with an invalid size", async ({ tmpdir }) => {
const destination = tmpdir;
const drive: EmptyDriveConfig = {
builder: "empty",
format: "ext2",
size: 0,
};
await expect(build("root", drive, image, destination)).rejects.toThrow(
"too few blocks",
);
});

tmpdirTest("should pass and create ext2 drive", async ({ tmpdir }) => {
const destination = tmpdir;
const driveName = "root.ext2";
const drive: EmptyDriveConfig = {
builder: "empty",
format: "ext2",
size: 1024 * 1024 * 1, // 1Mb
};
await build("root", drive, image, destination);

const filename = path.join(destination, driveName);
expect(fs.existsSync(filename)).toBeTruthy();
const stat = await fs.stat(filename);
expect(stat.isFile()).toBeTruthy();
expect(stat.size).toEqual(1 * 1024 * 1024);
});

tmpdirTest("should pass and create raw drive", async ({ tmpdir }) => {
const destination = tmpdir;
const driveName = "root.raw";
const drive: EmptyDriveConfig = {
builder: "empty",
format: "raw",
size: 1024 * 1024 * 1, // 1Mb
};
await build("root", drive, image, destination);

const filename = path.join(destination, driveName);
expect(fs.existsSync(filename)).toBeTruthy();
const stat = await fs.stat(filename);
expect(stat.isFile()).toBeTruthy();
expect(stat.size).toEqual(1 * 1024 * 1024);
});
});
34 changes: 34 additions & 0 deletions apps/cli/test/builder/none.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import fs from "fs-extra";
import path from "path";
import { describe, expect } from "vitest";
import { build } from "../../src/builder/none";
import { ExistingDriveConfig } from "../../src/config";
import { tmpdirTest } from "./tmpdirTest";

describe("when building with the none builder", () => {
tmpdirTest("should not build a missing file", async ({ tmpdir }) => {
const destination = tmpdir;
const drive: ExistingDriveConfig = {
builder: "none",
filename: path.join(__dirname, "data", "missing.ext2"),
format: "ext2",
};
await expect(build("root", drive, destination)).rejects.toThrow(
"no such file or directory",
);
});

tmpdirTest("should just copy an existing drive", async ({ tmpdir }) => {
const destination = tmpdir;
const filename = path.join(__dirname, "data", "data.ext2");
const drive: ExistingDriveConfig = {
builder: "none",
filename,
format: "ext2",
};
await build("root", drive, destination);
const src = fs.statSync(filename);
const dest = fs.statSync(path.join(destination, "root.ext2"));
expect(dest.size).toEqual(src.size);
});
});
51 changes: 51 additions & 0 deletions apps/cli/test/builder/tar.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import fs from "fs-extra";
import path from "path";
import { describe, expect } from "vitest";
import { build } from "../../src/builder/tar";
import { TarDriveConfig } from "../../src/config";
import { tmpdirTest } from "./tmpdirTest";

describe("when building with the tar builder", () => {
const image = "cartesi/sdk:0.11.0";

tmpdirTest("should not build a missing file", async ({ tmpdir }) => {
const destination = tmpdir;
const drive: TarDriveConfig = {
builder: "tar",
filename: path.join(__dirname, "data", "unexisting.tar"),
extraSize: 0,
format: "ext2",
};
await expect(build("root", drive, image, destination)).rejects.toThrow(
"no such file or directory",
);
});

tmpdirTest("should build a ext2 drive", async ({ tmpdir }) => {
const destination = tmpdir;
const drive: TarDriveConfig = {
builder: "tar",
filename: path.join(__dirname, "data", "data.tar"),
extraSize: 0,
format: "ext2",
};
await build("root", drive, image, destination);
const filename = path.join(destination, "root.ext2");
const stat = fs.statSync(filename);
expect(stat.size).toEqual(36864);
});

tmpdirTest("should build a sqfs drive", async ({ tmpdir }) => {
const destination = tmpdir;
const drive: TarDriveConfig = {
builder: "tar",
filename: path.join(__dirname, "data", "data.tar"),
extraSize: 0,
format: "sqfs",
};
await build("root", drive, image, destination);
const filename = path.join(destination, "root.sqfs");
const stat = fs.statSync(filename);
expect(stat.size).toEqual(4096);
});
});
Loading
Loading