From 75f3922ffa76852f300b441e13485c96f8c3b054 Mon Sep 17 00:00:00 2001 From: Huzaifa Danish Date: Fri, 8 May 2026 15:36:18 -0700 Subject: [PATCH 1/2] feat: add dark-themed python-pptx e2e test for microvm backend - Bump NanVix from 7b756ef to ee6cfe1 (includes python-pptx 1.0.2) - Update nanvix_rootfs.img checksum for new build - Add e2e test generating a 3-slide dark-themed PPTX inside NanVix VM using real python-pptx API (Presentation, Inches, Pt, RGBColor) - Restore cleanup in original PPTX test's finally block Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../integration/microvm-filesystem.test.ts | 140 ++++++++++++++++++ src/nanvix_binaries/checksums.json | 2 +- src/nanvix_binaries/versions.json | 2 +- 3 files changed, 142 insertions(+), 2 deletions(-) diff --git a/sdk/tests/integration/microvm-filesystem.test.ts b/sdk/tests/integration/microvm-filesystem.test.ts index c579e6a5..e22e6a1f 100644 --- a/sdk/tests/integration/microvm-filesystem.test.ts +++ b/sdk/tests/integration/microvm-filesystem.test.ts @@ -325,4 +325,144 @@ describe('MicroVM SDK E2E — spawnSandboxFromConfig with containment: microvm', fs.rmSync(testDir, { recursive: true, force: true }); } }); + + it('should generate a dark-themed 3-slide PPTX about MXC and NanVix using python-pptx', async () => { + const testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mxc-microvm-pptx-dark-')); + const rwDir = path.join(testDir, 'output'); + fs.mkdirSync(rwDir); + + try { + const rwDirPy = pyEscape(rwDir); + const config = { + version: '0.5.0-alpha', + containment: 'microvm' as const, + process: { + commandLine: [ + // site-packages isn't on sys.path by default in this NanVix build + "import sys; sys.path.insert(0, '/sysroot/lib/python3.12/site-packages')", + "import os", + "from pptx import Presentation", + "from pptx.util import Inches, Pt, Emu", + "from pptx.dml.color import RGBColor", + "from pptx.enum.text import PP_ALIGN", + "", + "prs = Presentation()", + "prs.slide_width = Emu(12192000)", + "prs.slide_height = Emu(6858000)", + "", + "BG = RGBColor(0x1B, 0x1B, 0x2F)", + "WHITE = RGBColor(0xFF, 0xFF, 0xFF)", + "BLUE = RGBColor(0x56, 0x9C, 0xD6)", + "TEAL = RGBColor(0x4E, 0xC9, 0xB0)", + "GRAY = RGBColor(0xD4, 0xD4, 0xD4)", + "", + "def set_bg(slide):", + " bg = slide.background", + " fill = bg.fill", + " fill.solid()", + " fill.fore_color.rgb = BG", + "", + "def add_text(slide, left, top, width, height, text, font_size, color, bold=False, alignment=PP_ALIGN.LEFT):", + " txBox = slide.shapes.add_textbox(left, top, width, height)", + " tf = txBox.text_frame", + " tf.word_wrap = True", + " p = tf.paragraphs[0]", + " p.text = text", + " p.font.size = Pt(font_size)", + " p.font.color.rgb = color", + " p.font.bold = bold", + " p.alignment = alignment", + " return tf", + "", + "def add_para(tf, text, font_size, color, bold=False):", + " p = tf.add_paragraph()", + " p.text = text", + " p.font.size = Pt(font_size)", + " p.font.color.rgb = color", + " p.font.bold = bold", + " return tf", + "", + "# --- Slide 1: Title ---", + "blank = prs.slide_layouts[6]", + "s1 = prs.slides.add_slide(blank)", + "set_bg(s1)", + "add_text(s1, Inches(0.8), Inches(1.8), Inches(10), Inches(1.2),", + " '\\U0001f680 MXC \\u00d7 NanVix', 44, WHITE, bold=True, alignment=PP_ALIGN.CENTER)", + "tf1 = add_text(s1, Inches(0.8), Inches(3.2), Inches(10), Inches(1.5),", + " 'Sandboxed Code Execution with Micro-VM Isolation', 24, BLUE, alignment=PP_ALIGN.CENTER)", + "add_para(tf1, '', 12, WHITE)", + "add_para(tf1, '\\U0001f512 Secure \\u2022 \\u26a1 Fast \\u2022 \\U0001f30d Cross-Platform', 20, TEAL)", + "tf1.paragraphs[-1].alignment = PP_ALIGN.CENTER", + "", + "# --- Slide 2: Architecture ---", + "s2 = prs.slides.add_slide(blank)", + "set_bg(s2)", + "add_text(s2, Inches(0.8), Inches(0.4), Inches(10), Inches(0.8),", + " '\\U0001f527 How It Works', 32, WHITE, bold=True)", + "tf2 = add_text(s2, Inches(0.8), Inches(1.4), Inches(10), Inches(5),", + " '\\U0001f4e6 MXC (Microsoft eXecution Container)', 20, BLUE, bold=True)", + "add_para(tf2, 'Orchestrates sandboxed execution across backends', 16, GRAY)", + "add_para(tf2, '', 12, GRAY)", + "add_para(tf2, '\\U0001f5a5 NanVix Micro-VM Backend', 20, BLUE, bold=True)", + "add_para(tf2, 'Lightweight hypervisor isolation via WHP', 16, GRAY)", + "add_para(tf2, 'CPython 3.12 inside a minimal microkernel', 16, GRAY)", + "add_para(tf2, '', 12, GRAY)", + "add_para(tf2, '\\U0001f504 The Flow', 20, BLUE, bold=True)", + "add_para(tf2, 'SDK \\u2192 wxc-exec \\u2192 nanvixd \\u2192 kernel.elf \\u2192 Python \\U0001f40d', 16, TEAL)", + "", + "# --- Slide 3: What's Next ---", + "s3 = prs.slides.add_slide(blank)", + "set_bg(s3)", + "add_text(s3, Inches(0.8), Inches(0.4), Inches(10), Inches(0.8),", + " '\\u2728 What\\'s Next', 32, WHITE, bold=True)", + "tf3 = add_text(s3, Inches(0.8), Inches(1.4), Inches(10), Inches(5),", + " '\\u2705 Filesystem sharing via readwritePaths', 18, GRAY)", + "add_para(tf3, '\\u2705 Stdout/stderr streaming back to host', 18, GRAY)", + "add_para(tf3, '\\u2705 Exit code propagation', 18, GRAY)", + "add_para(tf3, '\\U0001f6a7 Network isolation & proxy support', 18, GRAY)", + "add_para(tf3, '\\U0001f6a7 Multi-language guest support', 18, GRAY)", + "add_para(tf3, '\\U0001f6a7 GPU passthrough for AI workloads', 18, GRAY)", + "add_para(tf3, '', 12, GRAY)", + "add_para(tf3, '\\U0001f4ac \"Run untrusted code safely, at VM speed\"', 20, TEAL, bold=True)", + "", + `pptx_path = os.path.join('${rwDirPy}', 'mxc-nanvix.pptx')`, + "prs.save(pptx_path)", + "size = os.path.getsize(pptx_path)", + "print(f'PPTX created: {size} bytes, 3 slides')", + "print(f'Output: {pptx_path}')", + ].join('\n'), + timeout: 60000, + }, + filesystem: { + readwritePaths: [rwDir], + }, + }; + + const { stdout, stderr, exitCode } = await runMicrovm(config); + const combined = stdout + stderr; + + assert.strictEqual(exitCode, 0, `Expected exit code 0.\nstdout: ${stdout}\nstderr: ${stderr}`); + assert.ok(combined.includes('PPTX created:'), `Expected creation message in output:\n${combined}`); + assert.ok(combined.includes('3 slides'), `Expected 3 slides in output:\n${combined}`); + + // Verify the PPTX was copied back to the host. + const pptxPath = path.join(rwDir, 'mxc-nanvix.pptx'); + assert.ok(fs.existsSync(pptxPath), `Expected mxc-nanvix.pptx at ${pptxPath}`); + const size = fs.statSync(pptxPath).size; + assert.ok(size > 10000, `Expected substantial PPTX from python-pptx, got ${size} bytes`); + + // Verify valid zip with PK header. + const header = Buffer.alloc(4); + const fd = fs.openSync(pptxPath, 'r'); + fs.readSync(fd, header, 0, 4, 0); + fs.closeSync(fd); + assert.strictEqual(header[0], 0x50, 'Expected PK zip header byte 1'); + assert.strictEqual(header[1], 0x4B, 'Expected PK zip header byte 2'); + + console.log(`Dark PPTX output: ${pptxPath} (${size} bytes)`); + } finally { + // Keep output for manual inspection — open in PowerPoint to verify. + console.log(`Dark PPTX test dir persisted at: ${testDir}`); + } + }); }); diff --git a/src/nanvix_binaries/checksums.json b/src/nanvix_binaries/checksums.json index 2c225409..3395cd83 100644 --- a/src/nanvix_binaries/checksums.json +++ b/src/nanvix_binaries/checksums.json @@ -2,5 +2,5 @@ "nanvixd.exe": "375f21ea2cf148c0fc761779237c88921742890979b3389c6aa45409a4dd9c0c", "kernel.elf": "034ce96131b727d65f728b98e617257ebb514d3318b599ab139ce7901c7cd4ba", "python3.12": "46516dd7437c4e63470c3889bfb61cc3c195c792d697d5e137697620abe2af15", - "nanvix_rootfs.img": "0d7719bdb1943eae340991eadde016cd91b4111834152590bfb472b1f7dba7b4" + "nanvix_rootfs.img": "7015e5280d1490958d13f8eff7ebe8ff6cf9e197167d23518985284a1d143309" } diff --git a/src/nanvix_binaries/versions.json b/src/nanvix_binaries/versions.json index 8acfbd40..aaba28c0 100644 --- a/src/nanvix_binaries/versions.json +++ b/src/nanvix_binaries/versions.json @@ -1,6 +1,6 @@ { "nanvix_python": { - "tag": "3.12.3-nanvix-0.12.529-7b756ef", + "tag": "3.12.3-nanvix-0.12.529-ee6cfe1", "asset": "microvm-standalone-256mb.zip", "binaries": ["nanvixd.exe", "kernel.elf", "python3.12", "nanvix_rootfs.img"] } From 9c93955f151fe852e8261c68af62d7b490fe5c9a Mon Sep 17 00:00:00 2001 From: Huzaifa Danish Date: Tue, 12 May 2026 16:06:52 -0700 Subject: [PATCH 2/2] fix: update has_nanvix_binaries() to match current binary names The prereq check used stale filenames (python.elf, cpython-ramfs.img) causing all Rust microvm e2e tests to silently skip. Updated to match the current nanvix_runner.rs constants (python3.12, nanvix_rootfs.img). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/wxc_e2e_tests/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wxc_e2e_tests/src/lib.rs b/src/wxc_e2e_tests/src/lib.rs index 5c4a0ed2..19704b45 100644 --- a/src/wxc_e2e_tests/src/lib.rs +++ b/src/wxc_e2e_tests/src/lib.rs @@ -157,8 +157,8 @@ pub fn has_nanvix_binaries() -> bool { let present = [ "nanvixd.exe", "kernel.elf", - "python.elf", - "cpython-ramfs.img", + "python3.12", + "nanvix_rootfs.img", ] .iter() .all(|name| bin_dir.join(name).exists());