Skip to content

Commit

Permalink
Add tests for directory structure
Browse files Browse the repository at this point in the history
I hate tests that touch the filesystem, but in this case I think it's
necessary. I can't know which import files to read without loading
them, so I can't set up an in-memory system very easily.

Maybe if there was a mock simplifiles? 🤔
  • Loading branch information
dusty-phillips committed Aug 27, 2024
1 parent 4dfffa5 commit b85dad6
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 1 deletion.
1 change: 1 addition & 0 deletions gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ glexer = ">= 1.0.1 and < 2.0.0"
gleescript = ">= 1.4.0 and < 2.0.0"
pprint = ">= 1.0.3 and < 2.0.0"
gleeunit = ">= 1.2.0 and < 2.0.0"
temporary = ">= 1.0.0 and < 2.0.0"
5 changes: 5 additions & 0 deletions manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@

packages = [
{ name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
{ name = "envoy", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "CFAACCCFC47654F7E8B75E614746ED924C65BD08B1DE21101548AC314A8B6A41" },
{ name = "exception", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "F5580D584F16A20B7FCDCABF9E9BE9A2C1F6AC4F9176FA6DD0B63E3B20D450AA" },
{ name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" },
{ name = "glam", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "66EC3BCD632E51EED029678F8DF419659C1E57B1A93D874C5131FE220DFAD2B2" },
{ name = "glance", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "8F3314D27773B7C3B9FB58D8C02C634290422CE531988C0394FA0DF8676B964D" },
{ name = "gleam_crypto", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "ADD058DEDE8F0341F1ADE3AAC492A224F15700829D9A3A3F9ADF370F875C51B7" },
{ name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" },
{ name = "gleam_stdlib", version = "0.39.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "2D7DE885A6EA7F1D5015D1698920C9BAF7241102836CE0C3837A4F160128A9C4" },
{ name = "gleescript", version = "1.4.0", build_tools = ["gleam"], requirements = ["argv", "filepath", "gleam_erlang", "gleam_stdlib", "simplifile", "snag", "tom"], otp_app = "gleescript", source = "hex", outer_checksum = "8CDDD29F91064E69950A91A40061785F10275ADB70A0520075591F61A724C455" },
Expand All @@ -14,6 +17,7 @@ packages = [
{ name = "pprint", version = "1.0.3", build_tools = ["gleam"], requirements = ["glam", "gleam_stdlib"], otp_app = "pprint", source = "hex", outer_checksum = "76BBB92E23D12D954BD452686543F29EDE8EBEBB7FC0ACCBCA66EEF276EC3A06" },
{ name = "simplifile", version = "2.0.1", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "5FFEBD0CAB39BDD343C3E1CCA6438B2848847DC170BA2386DF9D7064F34DF000" },
{ name = "snag", version = "0.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "54D32E16E33655346AA3E66CBA7E191DE0A8793D2C05284E3EFB90AD2CE92BCC" },
{ name = "temporary", version = "1.0.0", build_tools = ["gleam"], requirements = ["envoy", "exception", "filepath", "gleam_crypto", "gleam_stdlib", "simplifile"], otp_app = "temporary", source = "hex", outer_checksum = "51C0FEF4D72CE7CA507BD188B21C1F00695B3D5B09D7DFE38240BFD3A8E1E9B3" },
{ name = "tom", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "tom", source = "hex", outer_checksum = "9EECB60150E834A07238BD5C7DF1FF07F7D4C5862BB8A773923D1981C7875FB0" },
]

Expand All @@ -27,3 +31,4 @@ gleeunit = { version = ">= 1.2.0 and < 2.0.0" }
glexer = { version = ">= 1.0.1 and < 2.0.0" }
pprint = { version = ">= 1.0.3 and < 2.0.0" }
simplifile = { version = ">= 2.0.1 and < 3.0.0" }
temporary = { version = ">= 1.0.0 and < 2.0.0" }
4 changes: 3 additions & 1 deletion src/macabre.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ pub fn usage(message: String) -> Nil {
io.println("Usage: macabre <filename.gleam>\n\n" <> message)
}

fn write_program(program: program.CompiledProgram) -> Result(Nil, errors.Error) {
pub fn write_program(
program: program.CompiledProgram,
) -> Result(Nil, errors.Error) {
let build_directory = program.build_directory(program.base_directory)
let source_directory = program.source_directory(program.base_directory)
output.delete(build_directory)
Expand Down
146 changes: 146 additions & 0 deletions test/compiler/directory_structure_tests.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import compiler
import compiler/program
import filepath
import gleam/dict
import gleam/list
import gleam/option
import gleam/set
import gleam/string
import gleeunit/should
import macabre
import simplifile
import temporary

// These tests have to touch the filesystem, so
// they add measurably to the compile time.
// Tests in other files are pure and require no IO.
// This file should *only* test that stuff is being placed
// in the right directories.
//
// I tried to bulk all the situations in just one test, but
// it may have to be split out if it becomes too hard to
// maintain.

pub type ProjectFiles {
ProjectFiles(
base_dir: String,
src_dir: String,
build_dir: String,
main_path: String,
)
}

fn init_folders(
use_function: fn(ProjectFiles) -> a,
) -> Result(a, simplifile.FileError) {
use dir <- temporary.create(temporary.directory())
let project_name = filepath.base_name(dir)
let src = filepath.join(dir, "src")
let build = filepath.join(dir, "build")
let main_path = filepath.join(src, project_name <> ".gleam")

simplifile.create_directory_all(src)
|> should.be_ok
let project_files =
ProjectFiles(
base_dir: dir,
src_dir: src,
build_dir: build,
main_path: main_path,
)
use_function(project_files)
}

pub fn program_compile_test_with_nested_folders_test() {
// src/<dirname.gleam>
// src/baz.py
// src/foo/bar.gleam
// src/foo/bindings.py
use project_files <- init_folders()
simplifile.write(
to: project_files.main_path,
contents: "import foo/bar
@external(python, \"baz\", \"baz\")
fn baz() -> Nil
pub fn main() {}",
)
|> should.be_ok

simplifile.write(
to: filepath.join(project_files.src_dir, "baz.py"),
contents: "
fn baz():
print('baz')",
)
|> should.be_ok

let foo_dir = filepath.join(project_files.src_dir, "foo")
simplifile.create_directory_all(foo_dir)
|> should.be_ok
simplifile.write(
to: filepath.join(foo_dir, "bar.gleam"),
contents: "@external(python, \"foo.bindings\", \"bar\")
fn bar() -> Nil",
)
|> should.be_ok

simplifile.write(
to: filepath.join(foo_dir, "bindings.py"),
contents: "def bar():
pass",
)
|> should.be_ok

let gleam_program =
program.load_program(project_files.base_dir)
|> should.be_ok

// load

should.equal(gleam_program.base_directory, project_files.base_dir)
should.equal(
gleam_program.main_module,
filepath.base_name(project_files.main_path),
)
gleam_program.modules
|> dict.size
|> should.equal(2)
gleam_program.external_import_files |> set.size |> should.equal(2)

// --- compile
let compiled_program = compiler.compile_program(gleam_program)
should.equal(compiled_program.base_directory, project_files.base_dir)
should.equal(
compiled_program.main_module,
option.Some(
filepath.base_name(project_files.main_path) |> string.drop_right(6),
),
)
compiled_program.modules
|> dict.size
|> should.equal(2)
compiled_program.external_import_files |> set.size |> should.equal(2)

// --- write output
macabre.write_program(compiled_program) |> should.be_ok

simplifile.read_directory(project_files.build_dir)
|> should.be_ok
|> list.sort(string.compare)
|> should.equal([
filepath.base_name(project_files.main_path) |> string.drop_right(6) <> ".py",
"__main__.py",
"baz.py",
"foo",
"gleam_builtins.py",
])

project_files.build_dir
|> filepath.join("foo")
|> simplifile.read_directory
|> should.be_ok
|> should.equal(["bindings.py", "bar.py"])
}

0 comments on commit b85dad6

Please sign in to comment.