| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- import { describe, expect, test } from "bun:test"
- import { AppRuntime } from "../../src/effect/app-runtime"
- import { Bus } from "../../src/bus"
- import { Effect } from "effect"
- import { Instance } from "../../src/project/instance"
- import { Pty } from "../../src/pty"
- import type { PtyID } from "../../src/pty/schema"
- import { tmpdir } from "../fixture/fixture"
- import { setTimeout as sleep } from "node:timers/promises"
- const wait = async (fn: () => boolean, ms = 5000) => {
- const end = Date.now() + ms
- while (Date.now() < end) {
- if (fn()) return
- await sleep(25)
- }
- throw new Error("timeout waiting for pty events")
- }
- const pick = (log: Array<{ type: "created" | "exited" | "deleted"; id: PtyID }>, id: PtyID) => {
- return log.filter((evt) => evt.id === id).map((evt) => evt.type)
- }
- describe("pty", () => {
- test("publishes created, exited, deleted in order for a short-lived process", async () => {
- if (process.platform === "win32") return
- await using dir = await tmpdir({ git: true })
- await Instance.provide({
- directory: dir.path,
- fn: () =>
- AppRuntime.runPromise(
- Effect.gen(function* () {
- const pty = yield* Pty.Service
- const log: Array<{ type: "created" | "exited" | "deleted"; id: PtyID }> = []
- const off = [
- Bus.subscribe(Pty.Event.Created, (evt) => log.push({ type: "created", id: evt.properties.info.id })),
- Bus.subscribe(Pty.Event.Exited, (evt) => log.push({ type: "exited", id: evt.properties.id })),
- Bus.subscribe(Pty.Event.Deleted, (evt) => log.push({ type: "deleted", id: evt.properties.id })),
- ]
- let id: PtyID | undefined
- try {
- const info = yield* pty.create({
- command: "/usr/bin/env",
- args: ["sh", "-c", "sleep 0.1"],
- title: "sleep",
- })
- id = info.id
- yield* Effect.promise(() => wait(() => pick(log, id!).includes("exited")))
- yield* pty.remove(id)
- yield* Effect.promise(() => wait(() => pick(log, id!).length >= 3))
- expect(pick(log, id!)).toEqual(["created", "exited", "deleted"])
- } finally {
- off.forEach((x) => x())
- if (id) yield* pty.remove(id)
- }
- }),
- ),
- })
- })
- test("publishes created, exited, deleted in order for /bin/sh + remove", async () => {
- if (process.platform === "win32") return
- await using dir = await tmpdir({ git: true })
- await Instance.provide({
- directory: dir.path,
- fn: () =>
- AppRuntime.runPromise(
- Effect.gen(function* () {
- const pty = yield* Pty.Service
- const log: Array<{ type: "created" | "exited" | "deleted"; id: PtyID }> = []
- const off = [
- Bus.subscribe(Pty.Event.Created, (evt) => log.push({ type: "created", id: evt.properties.info.id })),
- Bus.subscribe(Pty.Event.Exited, (evt) => log.push({ type: "exited", id: evt.properties.id })),
- Bus.subscribe(Pty.Event.Deleted, (evt) => log.push({ type: "deleted", id: evt.properties.id })),
- ]
- let id: PtyID | undefined
- try {
- const info = yield* pty.create({ command: "/bin/sh", title: "sh" })
- id = info.id
- yield* Effect.promise(() => sleep(100))
- yield* pty.remove(id)
- yield* Effect.promise(() => wait(() => pick(log, id!).length >= 3))
- expect(pick(log, id!)).toEqual(["created", "exited", "deleted"])
- } finally {
- off.forEach((x) => x())
- if (id) yield* pty.remove(id)
- }
- }),
- ),
- })
- })
- })
|