From b4b30ac65ca3507d83960b29e68c73b6f0569438 Mon Sep 17 00:00:00 2001 From: Korenevskiy Denis Date: Wed, 19 Aug 2026 22:14:41 +0300 Subject: [PATCH] test(workflow-tengo): run a command in a workdir with 10000 files Platforma 4.3.2 fixed k8s jobs that failed to start when the working directory held more than ~7300 files: the runner passed the expected- workdir-item list to the job inline, and above that count `execve` returned E2BIG before the container started. The list now goes to the job by path (`.pl/expected_items`). That fix shipped with unit coverage only (`core/pl/util/k8s/template_test.go`). The defect itself was found by hand during release validation, so add the end-to-end case: a template that fills the working directory with 10000 one-byte files through `exec.builder().writeFile` and then runs `hello-world` in it, plus a test that asserts the command's stdout. `hello-world` has both a binary and a docker distribution, so the same test covers the local exec runner (monorepo-localfs) and the k8s runner (monorepo-k8s-s3, once that job re-adds the workflow-tengo filter). --- .../src/exec/large-workdir.test.ts | 35 +++++++++++++ .../src/exec/run/large_workdir.tpl.tengo | 49 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 tests/workflow-tengo/src/exec/large-workdir.test.ts create mode 100644 tests/workflow-tengo/src/exec/run/large_workdir.tpl.tengo diff --git a/tests/workflow-tengo/src/exec/large-workdir.test.ts b/tests/workflow-tengo/src/exec/large-workdir.test.ts new file mode 100644 index 0000000000..8ac5872c74 --- /dev/null +++ b/tests/workflow-tengo/src/exec/large-workdir.test.ts @@ -0,0 +1,35 @@ +import { Pl } from "@milaboratories/pl-middle-layer"; +import { tplTest } from "@platforma-sdk/test"; + +/* + * End-to-end check for the E2BIG failure on large working directories + * (fixed in Platforma 4.3.2): a command must start and complete when its + * working directory holds more files than the old inline expected-items list + * could carry (~7300 entries). + * + * `exec.run.large_workdir` fills the working directory with 10000 files and + * runs `hello-world` in it. The software has both a binary and a docker + * distribution, so the same test covers the local exec runner and the k8s + * runner. + * + * The message carries a random suffix on purpose: an exec step with a stable + * CID is deduplicated by the backend, and a cached result would never start a + * job at all. + */ +tplTest.concurrent( + "run-in-workdir-with-10k-files", + async ({ helper, expect }) => { + const helloText = `Hello from a workdir with 10000 files (${Math.random()})`; + + const result = await helper.renderTemplate(false, "exec.run.large_workdir", ["main"], (tx) => ({ + text: tx.createValue(Pl.JsonObject, JSON.stringify(helloText)), + })); + const mainResult = result.computeOutput("main", (a) => a?.getDataAsString()); + + expect(await mainResult.awaitStableValue()).eq(helloText + "\n"); + }, + // Building 10000 workdir entries means 10000 value resources plus the map + // that holds them, all in one transaction. That is slow on the backend, so + // the default 15s test timeout is not enough. + 300_000, +); diff --git a/tests/workflow-tengo/src/exec/run/large_workdir.tpl.tengo b/tests/workflow-tengo/src/exec/run/large_workdir.tpl.tengo new file mode 100644 index 0000000000..797f857527 --- /dev/null +++ b/tests/workflow-tengo/src/exec/run/large_workdir.tpl.tengo @@ -0,0 +1,49 @@ +/** + * Regression test for the E2BIG failure on large working directories + * (fixed in Platforma 4.3.2). + * + * The k8s runner used to pass the expected-workdir-item list to the job + * inline. Above roughly 7300 entries the argument list got larger than the + * kernel limit, `execve` returned E2BIG and the job failed before the + * container started. The list now goes to the job by path + * (`.pl/expected_items` inside the workdir, see + * `util/k8s/job_params.go: DefaultExpectedItemsFileName` in the backend). + * + * The template fills the working directory with 10000 files, which is + * comfortably above the ~7300 threshold, then runs a command in it. Do not + * lower the count below ~7300: under that number the test passes on the + * buggy runner too and gives no coverage. Every file holds one byte, because + * the item *count* is what matters here, not the payload size. + */ + +self := import("@platforma-sdk/workflow-tengo:tpl") +assets := import("@platforma-sdk/workflow-tengo:assets") +exec := import("@platforma-sdk/workflow-tengo:exec") + +self.defineOutputs(["main"]) + +sw := assets.importSoftware("@platforma-open/milaboratories.software-test-utils:hello-world") + +// Number of files to put into the working directory. +// Keep it above the ~7300 entries that used to break `execve`. +workdirFileCount := 10000 + +self.body(func(inputs) { + builder := exec.builder(). + cpu(1).ram("50Mi"). + software(sw). + arg(inputs.text). + saveStdoutContent() + + // `writeFile` is the cheapest way to reach the file count: it needs no + // blob, no upload and no signature, only a small value resource. + for i := 0; i < workdirFileCount; i++ { + builder.writeFile("filler/" + string(i) + ".txt", "x") + } + + run := builder.run() + + return { + main: run.getStdoutContent() + } +})