cheatah
Source

tests/purrc/io_sys_test.cpp

1// Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).
2// Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.
3// System-level (whole-module) test for the `io` stdlib module: ONE cohesive .purr
4// program that exercises EVERY public purr-callable entry point in stdlib/io/io.hpp
5// in a single run, compiles it with purrc, runs it under the cheatah runtime, and
6// asserts the exact stdout byte-for-byte. Complements the per-function compile-run
7// tests (tests/purrc/io_cr_test.cpp) and the in-process unit tests
8// (stdlib/tests/io_test.cpp).
9//
10// Coverage (every documented purr-callable symbol in io.hpp):
11// io.str (generic Streamable overload) -> io.str(3), io.str(os.remove(...))
12// io.str (bool overload) -> io.str(1 == 1) / io.str(1 == 2) -> True/False
13// io.str (std::string identity) -> io.str(name)
14// io.repr (std::string overload) -> io.repr(name), io.repr(first), io.repr(rest)
15// io.repr (const char* overload) -> io.repr("raw")
16// io.print -> used throughout
17// io.format -> summary + the file body
18// io.open (free function) -> let f/g/h = io.open(path, mode)
19// File.write -> f.write(...)
20// File.is_open -> f.is_open() before/after close
21// File.close -> f.close()
22// File.read -> g.read()
23// File.readline -> g.readline()
24// File.readlines -> h.readlines()
25// io.read_file -> io.read_file(path)
26//
27// io.input is intentionally NOT covered: it reads from stdin, which the e2e harness
28// does not feed (covered instead by the in-process test CheatahIo.InputReadsALine).
29//
30// The program builds strings with str/repr/format, writes a temp file under /tmp via
31// the File object, reads it back three ways (readline+read, readlines, read_file),
32// prints a deterministic summary, then deletes the temp file (os.remove) and confirms
33// it is gone (os.path.exists). os is imported only for path joining and cleanup.
34#include "e2e_harness.hpp"
36TEST(StdlibE2E, Io) {
37 e2e::expect_e2e("io_sys", R"PURR(import io
38import os
40let path = os.path.join("/tmp", "io_sys_data.txt")
42let name = "lines"
43let header = io.str(1 == 1)
44let count = io.str(3)
45let kind = io.str(name)
46let label = io.repr(name)
47let lit = io.repr("raw")
48let summary = io.format("{} {} {} ({} total)", header, label, lit, count)
50let f = io.open(path, "w")
51f.write(io.format("alpha={}\n", 1))
52f.write(io.format("beta={}\n", io.str(1 == 2)))
53f.write("gamma=3\n")
54io.print("writing open:", io.str(f.is_open()))
55f.close()
56io.print("writing closed:", io.str(f.is_open()))
58let g = io.open(path, "r")
59let first = g.readline()
60let rest = g.read()
61g.close()
63let h = io.open(path, "r")
64let all_lines = h.readlines()
65h.close()
67let whole = io.read_file(path)
69io.print("kind:", kind)
70io.print("summary:", summary)
71io.print("first:", io.repr(first))
72io.print("rest:", io.repr(rest))
73io.print("line count:", io.str(3))
74for line in all_lines { io.print(" line:", line) }
75io.print("first line again:", all_lines[0])
76io.print("read_file whole:")
77io.print(whole)
79io.print("removed:", io.str(os.remove(path)))
80io.print("still exists:", io.str(os.path.exists(path)))
81)PURR",
82 "writing open: True\n"
83 "writing closed: False\n"
84 "kind: lines\n"
85 "summary: True 'lines' 'raw' (3 total)\n"
86 "first: 'alpha=1'\n"
87 "rest: 'beta=False\ngamma=3\n'\n"
88 "line count: 3\n"
89 " line: alpha=1\n"
90 " line: beta=False\n"
91 " line: gamma=3\n"
92 "first line again: alpha=1\n"
93 "read_file whole:\n"
94 "alpha=1\nbeta=False\ngamma=3\n\n"
95 "removed: True\n"
96 "still exists: False\n");