From 4acfc77ad67eb1ffa87912d0489ccafe99111840 Mon Sep 17 00:00:00 2001 From: Saza <49511480+saza-ku@users.noreply.github.com> Date: Mon, 18 Mar 2024 18:02:57 +0900 Subject: [PATCH] CI: add integration test (#56) * CI: add integration test * README: add info about integration test * lwip: update the upstream * CI: not to use timeout --- .github/workflows/ci.yaml | 58 ++++++++++++++++++ README.md | 6 ++ build.zig | 116 ++++++++++++++++++++++++++---------- scripts/create-test-dir.sh | 8 +++ scripts/integration-test.sh | 19 ++++++ submodules/lwip | 2 +- 6 files changed, 177 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/ci.yaml create mode 100644 scripts/create-test-dir.sh create mode 100755 scripts/integration-test.sh diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..91eaf6c --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,58 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + branches: + - '*' + +jobs: + run-integration-test: + runs-on: ubuntu-latest + steps: + - name: Checkout mewz + uses: actions/checkout@v3 + with: + repository: mewz-project/mewz + submodules: true + + - name: Install Zig + uses: goto-bus-stop/setup-zig@v2 + with: + version: 0.12.0-dev.926+3be8490d8 + cache: true + + - name: Install packages for running tests + uses: awalsh128/cache-apt-pkgs-action@v1.3.0 + with: + packages: qemu-system mtools + + - name: Cache mewz + uses: actions/cache@v2 + with: + path: + zig-cache + key: ${{ runner.os }}-mewz + + - name: Cache Newlib + uses: actions/cache@v2 + with: + path: + build/newlib + key: ${{ runner.os }}-mewz-newlib + + - name: Cache lwIP + uses: actions/cache@v2 + with: + path: + build/lwip + key: ${{ runner.os }}-mewz-lwip + + - name: Build Mewz + run: zig build -Dtest=true -Doptimize=ReleaseFast + + - name: Run tests + run: | + zig build -Dtest=true -Doptimize=ReleaseFast run diff --git a/README.md b/README.md index 6fba13d..c031f03 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,12 @@ To use file systems, specify the directory by `-Ddir=`. See [exampl > [!NOTE] > QEMU's port 1234 is mapped to localhost:1234. +## Run integration tests + +```sh +zig bulid -Dtest=true run +``` + ### Current Status diff --git a/build.zig b/build.zig index 959fb04..03219e9 100644 --- a/build.zig +++ b/build.zig @@ -4,37 +4,80 @@ const Target = @import("std").Target; const CrossTarget = @import("std").zig.CrossTarget; const Feature = @import("std").Target.Cpu.Feature; -pub fn build(b: *Build) !void { - const kernel_options = b.addOptions(); - - const obj_path_option = b.option([]const u8, "app-obj", "object file of application"); - if (obj_path_option) |_| { - kernel_options.addOption(bool, "has_wasm", true); - } else { - kernel_options.addOption(bool, "has_wasm", false); +const TEST_DIR_PATH = "build/test"; + +const BuildParams = struct { + obj_path: ?[]const u8 = undefined, + dir_path: ?[]const u8 = undefined, + is_test: bool = undefined, + log_level: []const u8 = undefined, + + const Self = @This(); + + fn new(b: *Build) Self { + var params = BuildParams{}; + + const test_option = b.option(bool, "test", "run tests"); + if (test_option) |t| { + params.is_test = t; + if (t) { + createTestDir() catch unreachable; + params.dir_path = TEST_DIR_PATH; + } + } else { + params.is_test = false; + } + + const obj_path_option = b.option([]const u8, "app-obj", "object file of application"); + if (obj_path_option) |p| { + params.obj_path = p; + } else { + params.obj_path = null; + } + + const log_level_option = b.option([]const u8, "log-level", "log level"); + if (log_level_option) |l| { + params.log_level = l; + } else { + params.log_level = "fatal"; + } + + const dir_path_option = b.option([]const u8, "dir", "path to directory"); + if (dir_path_option) |p| { + std.debug.print("building fs: {s}\n", .{p}); + params.dir_path = p; + } else { + params.dir_path = null; + } + + return params; } - const test_option = b.option(bool, "test", "run tests"); - if (test_option) |t| { - kernel_options.addOption(bool, "is_test", t); - } else { - kernel_options.addOption(bool, "is_test", false); - } + fn setOptions(self: *const Self, b: *Build) *Build.Step.Options { + const options = b.addOptions(); - const log_level_option = b.option([]const u8, "log-level", "log level"); - if (log_level_option) |l| { - kernel_options.addOption([]const u8, "log_level", l); - } else { - kernel_options.addOption([]const u8, "log_level", "fatal"); - } + options.addOption(bool, "is_test", self.is_test); + options.addOption([]const u8, "log_level", self.log_level); + + if (self.obj_path) |_| { + options.addOption(bool, "has_wasm", true); + } else { + options.addOption(bool, "has_wasm", false); + } - const fs_path_option = b.option([]const u8, "dir", "path to filesystem"); - if (fs_path_option) |p| { - std.debug.print("building fs: {s}\n", .{p}); - kernel_options.addOption(bool, "has_fs", true); - } else { - kernel_options.addOption(bool, "has_fs", false); + if (self.dir_path) |_| { + options.addOption(bool, "has_fs", true); + } else { + options.addOption(bool, "has_fs", false); + } + + return options; } +}; + +pub fn build(b: *Build) !void { + const params = BuildParams.new(b); + const options = params.setOptions(b); const features = Target.x86.Feature; @@ -72,19 +115,19 @@ pub fn build(b: *Build) !void { kernel.addObjectFile(Build.LazyPath{ .path = "build/lwip/liblwipallapps.a" }); kernel.addCSourceFile(Build.Step.Compile.CSourceFile{ .file = Build.LazyPath{ .path = "src/c/newlib_support.c" }, .flags = &[_][]const u8{ "-I", "submodules/newlib/newlib/libc/include" } }); kernel.addCSourceFile(Build.Step.Compile.CSourceFile{ .file = Build.LazyPath{ .path = "src/c/lwip_support.c" }, .flags = &[_][]const u8{ "-I", "submodules/newlib/newlib/libc/include" } }); - if (obj_path_option) |p| { + if (params.obj_path) |p| { kernel.addObjectFile(Build.LazyPath{ .path = p }); } - if (fs_path_option) |_| { + if (params.dir_path) |_| { kernel.addObjectFile(Build.LazyPath{ .path = "build/disk.o" }); } - kernel.addOptions("options", kernel_options); + kernel.addOptions("options", options); b.installArtifact(kernel); const kernel_step = b.step("kernel", "Build the kernel"); kernel.step.dependOn(&newlib_build_cmd.step); kernel.step.dependOn(&lwip_build_cmd.step); - if (fs_path_option) |p| { + if (params.dir_path) |p| { const fs_build_cmd = b.addSystemCommand(&[_][]const u8{ "./scripts/build-fs.sh", p }); kernel.step.dependOn(&fs_build_cmd.step); } @@ -93,7 +136,10 @@ pub fn build(b: *Build) !void { const rewrite_kernel_cmd = b.addSystemCommand(&[_][]const u8{"./scripts/rewrite-kernel.sh"}); rewrite_kernel_cmd.step.dependOn(b.getInstallStep()); - const run_cmd_str = [_][]const u8{"./scripts/run-qemu.sh"}; + const run_cmd_str = if (params.is_test) + [_][]const u8{"./scripts/integration-test.sh"} + else + [_][]const u8{"./scripts/run-qemu.sh"}; const run_cmd = b.addSystemCommand(&run_cmd_str); run_cmd.step.dependOn(&rewrite_kernel_cmd.step); @@ -111,3 +157,11 @@ pub fn build(b: *Build) !void { const debug_step = b.step("debug", "Debug the kernel"); debug_step.dependOn(&debug_cmd.step); } + +fn createTestDir() !void { + const cwd = std.fs.cwd(); + const test_dir = try cwd.makeOpenPath(TEST_DIR_PATH, std.fs.Dir.OpenDirOptions{}); + const file = try test_dir.createFile("test.txt", std.fs.File.CreateFlags{}); + defer file.close(); + _ = try file.write("fd_read test\n"); +} diff --git a/scripts/create-test-dir.sh b/scripts/create-test-dir.sh new file mode 100644 index 0000000..8c74e37 --- /dev/null +++ b/scripts/create-test-dir.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -ex + +REPO_ROOT=$(git rev-parse --show-toplevel) +cd $REPO_ROOT + +mkdir -p build/test +echo "fd_read test" > build/test/hogehoge.txt diff --git a/scripts/integration-test.sh b/scripts/integration-test.sh new file mode 100755 index 0000000..444dc28 --- /dev/null +++ b/scripts/integration-test.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -ex + +REPO_ROOT=$(git rev-parse --show-toplevel) +cd $REPO_ROOT + +mkdir -p build/test +(stty -echo; sleep 4; (sleep 0.5; echo q) | telnet localhost 1234) & +(sleep 2; curl localhost:1234) & +./scripts/run-qemu.sh > build/test/output.txt + +if ! grep -q "Integration test passed" build/test/output.txt; then + echo "Integration Test FAILED!!" + echo "output:" + cat build/test/output.txt + exit 1 +fi + +echo -e "\nIntegration Test PASSED!!" diff --git a/submodules/lwip b/submodules/lwip index b413b04..d0efd9e 160000 --- a/submodules/lwip +++ b/submodules/lwip @@ -1 +1 @@ -Subproject commit b413b040936f48d4cd9ed632ac579542c710efae +Subproject commit d0efd9ef7ba08e54b46b1060e2b4629a4907391b