mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 18:38:55 +00:00
182 lines
7.1 KiB
TypeScript
182 lines
7.1 KiB
TypeScript
import { $ } from "bun";
|
|
import { shellInternals } from "bun:internal-for-testing";
|
|
import { describe, expect } from "bun:test";
|
|
import { tempDirWithFiles } from "harness";
|
|
import { bunExe, createTestBuilder } from "../test_builder";
|
|
import { sortedShellOutput } from "../util";
|
|
const { builtinDisabled } = shellInternals;
|
|
|
|
const TestBuilder = createTestBuilder(import.meta.path);
|
|
|
|
const p = process.platform === "win32" ? (s: string) => s.replaceAll("/", "\\") : (s: string) => s;
|
|
|
|
$.nothrow();
|
|
|
|
describe.if(!builtinDisabled("cp"))("bunshell cp", async () => {
|
|
TestBuilder.command`cat ${import.meta.filename} > lmao.txt; cp -v lmao.txt lmao2.txt`
|
|
.stdout(p("$TEMP_DIR/lmao.txt -> $TEMP_DIR/lmao2.txt\n"))
|
|
.ensureTempDir()
|
|
.testMini()
|
|
.fileEquals("lmao2.txt", () => $`cat ${import.meta.filename}`.text())
|
|
.runAsTest("file -> file");
|
|
|
|
TestBuilder.command`cat ${import.meta.filename} > lmao.txt; touch lmao2.txt; cp -v lmao.txt lmao2.txt`
|
|
.stdout(p("$TEMP_DIR/lmao.txt -> $TEMP_DIR/lmao2.txt\n"))
|
|
.ensureTempDir()
|
|
.testMini()
|
|
.fileEquals("lmao2.txt", () => $`cat ${import.meta.filename}`.text())
|
|
.runAsTest("file -> existing file replaces contents");
|
|
|
|
TestBuilder.command`cat ${import.meta.filename} > lmao.txt; mkdir lmao2; cp -v lmao.txt lmao2`
|
|
.ensureTempDir()
|
|
.stdout(p("$TEMP_DIR/lmao.txt -> $TEMP_DIR/lmao2/lmao.txt\n"))
|
|
.fileEquals("lmao2/lmao.txt", () => $`cat ${import.meta.filename}`.text())
|
|
.testMini()
|
|
.runAsTest("file -> dir");
|
|
|
|
TestBuilder.command`cat ${import.meta.filename} > lmao.txt; cp -v lmao.txt lmao2/`
|
|
.ensureTempDir()
|
|
.stderr("cp: lmao2/ is not a directory\n")
|
|
.exitCode(1)
|
|
.testMini()
|
|
.runAsTest("file -> non-existent dir fails");
|
|
|
|
TestBuilder.command`cat ${import.meta.filename} > lmao.txt; cat ${import.meta.filename} > lmao2.txt; mkdir lmao3; cp -v lmao.txt lmao2.txt lmao3`
|
|
.ensureTempDir()
|
|
.stdout(
|
|
expectSortedOutput(
|
|
p("$TEMP_DIR/lmao.txt -> $TEMP_DIR/lmao3/lmao.txt\n$TEMP_DIR/lmao2.txt -> $TEMP_DIR/lmao3/lmao2.txt\n"),
|
|
),
|
|
)
|
|
.fileEquals("lmao3/lmao.txt", () => $`cat ${import.meta.filename}`.text())
|
|
.fileEquals("lmao3/lmao2.txt", () => $`cat ${import.meta.filename}`.text())
|
|
.testMini()
|
|
.runAsTest("file+ -> dir");
|
|
|
|
TestBuilder.command`mkdir lmao; mkdir lmao2; cp -v lmao lmao2 lmao3`
|
|
.ensureTempDir()
|
|
.stderr(expectSortedOutput("cp: lmao is a directory (not copied)\ncp: lmao2 is a directory (not copied)\n"))
|
|
.exitCode(1)
|
|
.testMini()
|
|
.runAsTest("dir -> ? fails without -R");
|
|
|
|
describe("EBUSY windows", () => {
|
|
TestBuilder.command /* sh */ `
|
|
echo hi! > hello.txt
|
|
mkdir somedir
|
|
cp ${{ raw: Array(50).fill("hello.txt").join(" ") }} somedir
|
|
`
|
|
.ensureTempDir()
|
|
.exitCode(0)
|
|
.fileEquals("somedir/hello.txt", "hi!\n")
|
|
.runAsTest("doesn't fail on EBUSY when copying multiple files that are the same");
|
|
});
|
|
|
|
describe("uutils ported", () => {
|
|
const TEST_EXISTING_FILE: string = "existing_file.txt";
|
|
const TEST_HELLO_WORLD_SOURCE: string = "hello_world.txt";
|
|
const TEST_HELLO_WORLD_SOURCE_SYMLINK: string = "hello_world.txt.link";
|
|
const TEST_HELLO_WORLD_DEST: string = "copy_of_hello_world.txt";
|
|
const TEST_HELLO_WORLD_DEST_SYMLINK: string = "copy_of_hello_world.txt.link";
|
|
const TEST_HOW_ARE_YOU_SOURCE: string = "how_are_you.txt";
|
|
const TEST_HOW_ARE_YOU_DEST: string = "hello_dir/how_are_you.txt";
|
|
const TEST_COPY_TO_FOLDER: string = "hello_dir/";
|
|
const TEST_COPY_TO_FOLDER_FILE: string = "hello_dir/hello_world.txt";
|
|
const TEST_COPY_FROM_FOLDER: string = "hello_dir_with_file/";
|
|
const TEST_COPY_FROM_FOLDER_FILE: string = "hello_dir_with_file/hello_world.txt";
|
|
const TEST_COPY_TO_FOLDER_NEW: string = "hello_dir_new";
|
|
const TEST_COPY_TO_FOLDER_NEW_FILE: string = "hello_dir_new/hello_world.txt";
|
|
|
|
// beforeAll doesn't work beacuse of the way TestBuilder is setup
|
|
const tempFiles = {
|
|
"hello_world.txt": "Hello, World!",
|
|
"existing_file.txt": "Cogito ergo sum.",
|
|
"how_are_you.txt": "How are you?",
|
|
"hello_dir": {
|
|
"hello.txt": "",
|
|
},
|
|
"hello_dir_with_file": {
|
|
"hello_world.txt": "Hello, World!",
|
|
},
|
|
"dir_with_10_files": {
|
|
"0": "",
|
|
"1": "",
|
|
"2": "",
|
|
"3": "",
|
|
"4": "",
|
|
"5": "",
|
|
"6": "",
|
|
"7": "",
|
|
"8": "",
|
|
"9": "",
|
|
},
|
|
};
|
|
const tmpdir: string = tempDirWithFiles("cp-uutils", tempFiles);
|
|
const mini_tmpdir: string = tempDirWithFiles("cp-uutils-mini", tempFiles);
|
|
|
|
TestBuilder.command`cp ${TEST_HELLO_WORLD_SOURCE} ${TEST_HELLO_WORLD_DEST}`
|
|
.ensureTempDir(tmpdir)
|
|
.fileEquals(TEST_HELLO_WORLD_DEST, "Hello, World!")
|
|
.testMini({ cwd: mini_tmpdir })
|
|
.runAsTest("cp_cp");
|
|
|
|
TestBuilder.command`cp ${TEST_HELLO_WORLD_SOURCE} ${TEST_EXISTING_FILE}`
|
|
.ensureTempDir(tmpdir)
|
|
.fileEquals(TEST_EXISTING_FILE, "Hello, World!")
|
|
.testMini({ cwd: mini_tmpdir })
|
|
.runAsTest("cp_existing_target");
|
|
|
|
TestBuilder.command`cp ${TEST_HELLO_WORLD_SOURCE} ${TEST_HELLO_WORLD_SOURCE} ${TEST_COPY_TO_FOLDER}`
|
|
.ensureTempDir(tmpdir)
|
|
.file(TEST_EXISTING_FILE, "Hello, World!\n")
|
|
.testMini({ cwd: mini_tmpdir })
|
|
.runAsTest("cp_duplicate_files");
|
|
|
|
TestBuilder.command`touch a; cp a a`
|
|
.ensureTempDir(tmpdir)
|
|
.stderr_contains("cp: a and a are identical (not copied)\n")
|
|
.exitCode(1)
|
|
.testMini({ cwd: mini_tmpdir })
|
|
.runAsTest("cp_same_file");
|
|
|
|
TestBuilder.command`cp ${TEST_HELLO_WORLD_SOURCE} ${TEST_HELLO_WORLD_SOURCE} ${TEST_EXISTING_FILE}`
|
|
.ensureTempDir(tmpdir)
|
|
.stderr_contains(`cp: ${TEST_EXISTING_FILE} is not a directory\n`)
|
|
.exitCode(1)
|
|
.testMini({ cwd: mini_tmpdir })
|
|
.runAsTest("cp_multiple_files_target_is_file");
|
|
|
|
TestBuilder.command`cp ${TEST_COPY_TO_FOLDER} ${TEST_HELLO_WORLD_DEST}`
|
|
.ensureTempDir(tmpdir)
|
|
.stderr_contains(`cp: ${TEST_COPY_TO_FOLDER} is a directory (not copied)\n`)
|
|
.exitCode(1)
|
|
.testMini({ cwd: mini_tmpdir })
|
|
.runAsTest("cp_directory_not_recursive");
|
|
|
|
TestBuilder.command`cp ${TEST_HELLO_WORLD_SOURCE} ${TEST_HOW_ARE_YOU_SOURCE} ${TEST_COPY_TO_FOLDER}`
|
|
.ensureTempDir(tmpdir)
|
|
.fileEquals(TEST_COPY_TO_FOLDER_FILE, "Hello, World!")
|
|
.fileEquals(TEST_HOW_ARE_YOU_DEST, "How are you?")
|
|
.testMini({ cwd: mini_tmpdir })
|
|
.runAsTest("cp_multiple_files");
|
|
|
|
TestBuilder.command`cp ${TEST_HELLO_WORLD_SOURCE} ${TEST_HOW_ARE_YOU_SOURCE} ${TEST_COPY_TO_FOLDER} && ${bunExe()} -e ${'console.log("HI")'}`
|
|
.ensureTempDir(tmpdir)
|
|
.stdout("HI\n")
|
|
.runAsTest("cp_multiple_files");
|
|
|
|
TestBuilder.command`cp -R ${TEST_COPY_FROM_FOLDER} ${TEST_COPY_TO_FOLDER_NEW}`
|
|
.ensureTempDir(tmpdir)
|
|
.fileEquals(TEST_COPY_TO_FOLDER_NEW_FILE, "Hello, World!")
|
|
.testMini({ cwd: mini_tmpdir })
|
|
.runAsTest("cp_recurse");
|
|
});
|
|
});
|
|
|
|
function expectSortedOutput(expected: string) {
|
|
return (stdout: string, tempdir: string) =>
|
|
expect(sortedShellOutput(stdout).join("\n")).toEqual(
|
|
sortedShellOutput(expected).join("\n").replaceAll("$TEMP_DIR", tempdir),
|
|
);
|
|
}
|