Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  archive-helpers.test.ts

  Sprache: JAVA
 

Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

import fs from "node:fs/promises";
import path from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import { createTrackedTempDirs } from "../test-utils/tracked-temp-dirs.js";
import {
  createTarEntryPreflightChecker,
  fileExists,
  readJsonFile,
  resolveArchiveKind,
  resolvePackedRootDir,
  withTimeout,
} from "./archive.js";

const tempDirs = createTrackedTempDirs();
const createTempDir = () => tempDirs.make("openclaw-archive-helper-test-");

function expectTarPreflightError(
  checker: ReturnType<typeof createTarEntryPreflightChecker>,
  entry: Parameters<ReturnType<typeof createTarEntryPreflightChecker>>[0],
  expected: string | RegExp,
): void {
  expect(() => checker(entry)).toThrow(expected);
}

afterEach(async () => {
  vi.useRealTimers();
  await tempDirs.cleanup();
});

describe("archive helpers", () => {
  it.each([
    { input: "/tmp/file.zip", expected: "zip" },
    { input: "/tmp/file.TAR.GZ", expected: "tar" },
    { input: "/tmp/file.tgz", expected: "tar" },
    { input: "/tmp/file.tar", expected: "tar" },
    { input: "/tmp/file.txt", expected: null },
  ])("detects archive kind for $input", ({ input, expected }) => {
    expect(resolveArchiveKind(input)).toBe(expected);
  });

  it.each([
    {
      name: "uses the package directory when present",
      setup: async (root: string) => {
        await fs.mkdir(path.join(root, "package"), { recursive: true });
      },
      expected: (root: string) => path.join(root, "package"),
    },
    {
      name: "uses the single extracted root directory as a fallback",
      setup: async (root: string) => {
        await fs.mkdir(path.join(root, "bundle-root"), { recursive: true });
      },
      expected: (root: string) => path.join(root, "bundle-root"),
    },
    {
      name: "uses the extraction root when a root marker is present",
      setup: async (root: string) => {
        await fs.writeFile(path.join(root, "package.json"), "{}", "utf8");
      },
      opts: { rootMarkers: ["package.json"] },
      expected: (root: string) => root,
    },
  ])("resolves packed roots when $name", async ({ setup, expected, opts }) => {
    const root = await createTempDir();
    await setup(root);
    await expect(resolvePackedRootDir(root, opts)).resolves.toBe(expected(root));
  });

  it.each([
    {
      name: "multiple extracted roots exist",
      setup: async (root: string) => {
        await fs.mkdir(path.join(root, "a"), { recursive: true });
        await fs.mkdir(path.join(root, "b"), { recursive: true });
      },
    },
    {
      name: "only non-root marker files exist",
      setup: async (root: string) => {
        await fs.writeFile(path.join(root, "note.txt"), "hi", "utf8");
      },
    },
  ])("rejects unexpected packed root layouts when $name", async ({ setup }) => {
    const root = await createTempDir();
    await setup(root);
    await expect(resolvePackedRootDir(root)).rejects.toThrow(/unexpected archive layout/i);
  });

  it("returns work results and propagates errors before timeout", async () => {
    await expect(withTimeout(Promise.resolve("ok"), 100, "extract zip")).resolves.toBe("ok");
    await expect(
      withTimeout(Promise.reject(new Error("boom")), 100, "extract zip"),
    ).rejects.toThrow("boom");
  });

  it("rejects when archive work exceeds the timeout", async () => {
    vi.useFakeTimers();
    const late = new Promise<string>((resolve) => setTimeout(() => resolve("ok"), 50));
    const result = withTimeout(late, 1, "extract tar");
    const pending = expect(result).rejects.toThrow("extract tar timed out after 1ms");
    await vi.advanceTimersByTimeAsync(1);
    await pending;
  });

  it("preflights tar entries for blocked link types, path escapes, and size budgets", () => {
    const checker = createTarEntryPreflightChecker({
      rootDir: "/tmp/dest",
      limits: {
        maxEntries: 1,
        maxEntryBytes: 8,
        maxExtractedBytes: 12,
      },
    });

    expectTarPreflightError(
      checker,
      { path: "package/link", type: "SymbolicLink", size: 0 },
      "tar entry is a link: package/link",
    );
    expectTarPreflightError(
      checker,
      { path: "../escape.txt", type: "File", size: 1 },
      /escapes destination|absolute/i,
    );

    checker({ path: "package/ok.txt", type: "File", size: 8 });
    expectTarPreflightError(
      checker,
      { path: "package/second.txt", type: "File", size: 1 },
      "archive entry count exceeds limit",
    );
  });

  it("treats stripped-away tar entries as no-ops and enforces extracted byte budgets", () => {
    const checker = createTarEntryPreflightChecker({
      rootDir: "/tmp/dest",
      stripComponents: 1,
      limits: {
        maxEntries: 4,
        maxEntryBytes: 16,
        maxExtractedBytes: 10,
      },
    });

    expect(() => checker({ path: "package", type: "Directory", size: 0 })).not.toThrow();
    checker({ path: "package/a.txt", type: "File", size: 6 });
    expectTarPreflightError(
      checker,
      { path: "package/b.txt", type: "File", size: 6 },
      "archive extracted size exceeds limit",
    );
  });

  it("reads JSON files and reports file existence", async () => {
    const dir = await createTempDir();
    const jsonPath = path.join(dir, "data.json");
    const badPath = path.join(dir, "bad.json");
    await fs.writeFile(jsonPath, '{"ok":true}', "utf8");
    await fs.writeFile(badPath, "{not json", "utf8");

    await expect(readJsonFile<{ ok: boolean }>(jsonPath)).resolves.toEqual({ ok: true });
    await expect(readJsonFile(badPath)).rejects.toThrow();
    await expect(fileExists(jsonPath)).resolves.toBe(true);
    await expect(fileExists(path.join(dir, "missing.json"))).resolves.toBe(false);
  });
});

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge