Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-environment

Environment files for Pudu: load .env variables safely with layered files, discovery, expansion, typed reads, and secrets kept out of every message

0.1.0Apache-2.01

InstallClose

SourceTest.pudu

Pudu49 lines2.6 KB

GitHub ↗
1/** @Test.Source.Suite — files, text, and bytes as sources */2module PuduLangEnvironment.SourceTest34import Std.Bytes as Bytes5import Std.Env as Env6import Std.Fs as Fs7import Std.Io as Io8import Std.Path as Path9import Std.Result as Result10import Std.Test as Test11import PuduLangEnvironment.Domain.Encoding as Encoding12import PuduLangEnvironment as Environment13import PuduLangEnvironment.Source as Source1415/// Bytes from hexadecimal text.16fn hex(text: Str) -> Bytes { Result.unwrapOr(Bytes.decodeHex(text), Bytes.empty()) }1718/// Runs the suite.19fn main() -> Int {20  let root = Result.unwrapOr(Fs.temporaryDirectoryIn(Env.temporaryDirectory(), "pudu-env-source-"), ".")21  let written = Path.join(root, "app.env")22  let latin = Path.join(root, "latin.env")23  let _plain = Io.write(written, "A=1\r\nB=2\n")24  let _latin = Fs.writeAtomically(latin, &hex("4b3de9"))25  let missing = Path.join(root, "absent.env")26  let checks = Test.suite("Source", &[27      Test.equals("a file's label is its path", &Source.label(&Source.File("x.env")), &"x.env"),28      Test.equals("text and bytes are labelled as given", &[Source.label(&Source.Text("inline", "")), Source.label(&Source.Data("blob", Bytes.empty()))], &["inline", "blob"]),29      Test.equals("a file's lines are read", &Source.lines(&Source.File(written), Encoding.Utf8), &Ok(["A=1", "B=2", ""])),30      Test.equals("a file is decoded in the declared encoding", &Source.lines(&Source.File(latin), Encoding.Latin1), &Ok(["K=é"])),31      Test.equals("a file that does not decode is refused", &Source.lines(&Source.File(latin), Encoding.Utf8), &Err(Environment.Undecodable(latin, "UTF-8"))),32      Test.equals("a missing file is refused", &Source.lines(&Source.File(missing), Encoding.Utf8), &Err(Environment.MissingFile(missing))),33      Test.equals("a blank path is refused", &Source.lines(&Source.File("  "), Encoding.Utf8), &Err(Environment.BlankPath)),34      Test.that("a directory cannot be read", match Source.lines(&Source.File(root), Encoding.Utf8) {35          case Err(Environment.Unreadable(path, _)) => path == root36          case _ => false37        }),38      Test.equals("text is split into lines", &Source.lines(&Source.Text("inline", "A=1\r\nB=2"), Encoding.Latin1), &Ok(["A=1", "B=2"])),39      Test.equals("bytes are decoded", &Source.lines(&Source.Data("blob", hex("4b3de9")), Encoding.Latin1), &Ok(["K=é"])),40      Test.equals("bytes that do not decode name their label", &Source.lines(&Source.Data("blob", hex("4b00ff")), Encoding.Utf16Le), &Err(Environment.Undecodable("blob", "UTF-16LE")))41    ])42  let _cleared = Fs.removeTree(root)43  let ran = Test.run(&checks)44  for failure in Test.failuresOf(&ran) {45    let _reported = Io.writeErrorLine(failure)46  }47  Test.report(&ran)48}49