krz/orgstar

A native macOS editor for org-mode files. editor org-mode swift

Tests/OrgAppTests/BabelSessionTests.swift

ab6ccec56eca03d0dadf2c9332aab10c4490eb62
orgstar/Tests/OrgAppTests/BabelSessionTests.swift history · blame · raw

66 lines · 3838 bytes

 1import Foundation
 2import Testing
 3import OrgCore
 4@testable import OrgApp
 5
 6struct BabelSessionStateTests {
 7    func run(_ text: String, in folder: URL) async throws -> String {
 8        let context = EditContext(revision: 0, text: text, tree: OrgParser.parse(text), selection: [2..<2])
 9        guard case .success(let job) = Babel.plan(context) else { Issue.record("not planned: \(text)"); return "" }
10        let output = try await BabelRunner.run(job, fileDirectory: folder)
11        guard case .success(let edits) = Babel.finish(job, output: output, text: text) else { return "" }
12        let new = edits.sorted { $0.range.lowerBound > $1.range.lowerBound }.reduce(text) { $1.apply(to: $0) }
13        return String(new.dropFirst(text.count))
14    }
15
16    @Test func sessionsKeepState() async throws {
17        let folder = FileManager.default.temporaryDirectory.appendingPathComponent("orgstar-session-\(UUID().uuidString)")
18        try FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true)
19        defer {
20            BabelSessions.shared.stopAll()
21            try? FileManager.default.removeItem(at: folder)
22        }
23        _ = try await run("#+begin_src sh :session s1\nx=5; cd /tmp\n#+end_src\n", in: folder)
24        #expect(try await run("#+begin_src sh :session s1 :results output\necho $x\n#+end_src\n", in: folder) == "\n#+RESULTS:\n: 5\n")
25        #expect(try await run("#+begin_src sh :session other :results output\necho \"[$x]\"\n#+end_src\n", in: folder) == "\n#+RESULTS:\n: []\n")
26        _ = try await run("#+begin_src python :session py :results output\na = 2\nprint('set')\n#+end_src\n", in: folder)
27        #expect(try await run("#+begin_src python :session py\na * 3\n#+end_src\n", in: folder) == "\n#+RESULTS:\n: 6\n")
28        #expect(try await run("#+begin_src python :session py :results output\nprint(a + 1)\n#+end_src\n", in: folder) == "\n#+RESULTS:\n: 3\n")
29        _ = try await run("#+begin_src python :session py :results output\nraise ValueError('x')\n#+end_src\n", in: folder)
30        #expect(try await run("#+begin_src python :session py\n[a, a]\n#+end_src\n", in: folder) == "\n#+RESULTS:\n| 2 | 2 |\n")
31    }
32}
33
34struct BabelRunnerTests {
35    @Test func refusesWithoutTheCompiler() async throws {
36        for (text, programs, message) in [
37            ("#+begin_src D\nwriteln(1);\n#+end_src\n", ["rdmd"], "rdmd isn't installed, so D blocks can't run."),
38            ("#+begin_src clojure\n1\n#+end_src\n", ["bb", "clojure"], "Neither bb nor clojure is installed, so clojure blocks can't run."),
39        ] where !programs.contains(where: BabelRunner.installed) {
40            let context = EditContext(revision: 0, text: text, tree: OrgParser.parse(text), selection: [2..<2])
41            guard case .success(let job) = Babel.plan(context) else {
42                Issue.record("not planned: \(text)")
43                continue
44            }
45            do {
46                _ = try await BabelRunner.run(job, fileDirectory: FileManager.default.temporaryDirectory)
47                Issue.record("ran: \(text)")
48            } catch let failure as BabelRunner.Failure {
49                #expect(failure.description == message)
50            }
51        }
52    }
53
54    @Test(.enabled(if: BabelRunner.installed("gcc")))
55    func compilesAndRunsC() async throws {
56        let text = "#+begin_src C :includes <stdio.h>\nprintf(\"%d\\n\", 6 * 7);\n#+end_src\n"
57        let context = EditContext(revision: 0, text: text, tree: OrgParser.parse(text), selection: [2..<2])
58        guard case .success(let job) = Babel.plan(context) else {
59            Issue.record("not planned")
60            return
61        }
62        let output = try await BabelRunner.run(job, fileDirectory: FileManager.default.temporaryDirectory)
63        #expect(output.stdout == "42\n")
64        #expect(output.problem == nil)
65    }
66}