Initial MoonModel implementation
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "test_helper"
|
||||
|
||||
class GeneratorTest < Minitest::Test
|
||||
def test_one_piece_multicolor_package
|
||||
Dir.mktmpdir do |dir|
|
||||
data = MoonModel::DataSet.new(make_data(File.join(dir, "data.gz")))
|
||||
config = MoonModel::Config.new(
|
||||
"size" => { "value" => 40 }, "resolution" => { "longitude_segments" => 24 },
|
||||
"palette" => [{ "name" => "dark", "hex" => "#222222" }, { "name" => "light", "hex" => "#DDDDDD" }],
|
||||
"grid" => { "enabled" => true, "color_name" => "light" }, "output" => { "name" => "test" }
|
||||
)
|
||||
result = MoonModel::Generator.new(config, data_set: data, output_dir: File.join(dir, "out")).generate
|
||||
path = File.join(result[:output_dir], "moon.3mf")
|
||||
assert File.file?(path)
|
||||
Zip::File.open(path) do |zip|
|
||||
model = zip.read("3D/3dmodel.model")
|
||||
assert_includes model, "<basematerials"
|
||||
assert_includes model, "displaycolor=\"#222222\""
|
||||
assert_includes model, "<components>"
|
||||
end
|
||||
assert File.file?(File.join(result[:output_dir], "manifest.md"))
|
||||
assert_in_delta 40.0, result[:statistics]["final_envelope_mm"], 0.01
|
||||
end
|
||||
end
|
||||
|
||||
def test_segmented_box_outputs_parts_keys_and_stand
|
||||
Dir.mktmpdir do |dir|
|
||||
data = MoonModel::DataSet.new(make_data(File.join(dir, "data.gz")))
|
||||
config = MoonModel::Config.new("purpose" => "box", "size" => { "value" => 50 },
|
||||
"stand" => { "enabled" => true },
|
||||
"resolution" => { "longitude_segments" => 24 })
|
||||
result = MoonModel::Generator.new(config, data_set: data, output_dir: File.join(dir, "out")).generate
|
||||
assert_equal 8, Dir[File.join(result[:output_dir], "north_*.3mf")].length + Dir[File.join(result[:output_dir], "south_*.3mf")].length
|
||||
assert File.file?(File.join(result[:output_dir], "assembly_keys.3mf"))
|
||||
assert File.file?(File.join(result[:output_dir], "orbital_triskelion_stand.3mf"))
|
||||
manifest = File.read(File.join(result[:output_dir], "manifest.md"))
|
||||
assert_includes manifest, "Stand style: Orbital triskelion"
|
||||
assert_includes manifest, "Terrain envelope v2 (rotation independent)"
|
||||
assert_includes manifest, "Guaranteed Moon clearance above hub/base: 10.00 mm"
|
||||
assert_includes manifest, "Stand dimensions:"
|
||||
end
|
||||
end
|
||||
|
||||
def test_invalid_preflight_does_not_create_output_directory
|
||||
Dir.mktmpdir do |dir|
|
||||
data = MoonModel::DataSet.new(make_data(File.join(dir, "data.gz")))
|
||||
config = MoonModel::Config.new("size" => { "value" => 40, "meaning" => "datum" },
|
||||
"vertical_exaggeration" => 100_000,
|
||||
"resolution" => { "longitude_segments" => 24 })
|
||||
output = File.join(dir, "out")
|
||||
|
||||
assert_raises(ArgumentError) { MoonModel::Generator.new(config, data_set: data, output_dir: output).generate }
|
||||
refute Dir.exist?(output)
|
||||
end
|
||||
end
|
||||
|
||||
def test_revision_atomically_replaces_obsolete_files
|
||||
Dir.mktmpdir do |dir|
|
||||
data = MoonModel::DataSet.new(make_data(File.join(dir, "data.gz")))
|
||||
output = File.join(dir, "named_moon")
|
||||
common = { "size" => { "value" => 40 }, "resolution" => { "longitude_segments" => 24 },
|
||||
"output" => { "name" => "Named Moon" } }
|
||||
MoonModel::Generator.new(MoonModel::Config.new(common), data_set: data, output_dir: output).generate
|
||||
assert File.file?(File.join(output, "moon.3mf"))
|
||||
|
||||
revised = MoonModel::Config.new(common.merge("assembly" => "eight_piece"))
|
||||
MoonModel::Generator.new(revised, data_set: data, output_dir: output).generate
|
||||
|
||||
refute File.exist?(File.join(output, "moon.3mf"))
|
||||
assert File.file?(File.join(output, "north_1.3mf"))
|
||||
assert MoonModel::Generator.generated_directory?(output)
|
||||
end
|
||||
end
|
||||
|
||||
def test_refuses_to_replace_unrelated_directory
|
||||
Dir.mktmpdir do |dir|
|
||||
output = File.join(dir, "not_a_model")
|
||||
Dir.mkdir(output)
|
||||
File.write(File.join(output, "keep.txt"), "important")
|
||||
data = MoonModel::DataSet.new(make_data(File.join(dir, "data.gz")))
|
||||
config = MoonModel::Config.new("size" => { "value" => 40 },
|
||||
"resolution" => { "longitude_segments" => 24 })
|
||||
|
||||
assert_raises(ArgumentError) { MoonModel::Generator.new(config, data_set: data, output_dir: output).generate }
|
||||
assert_equal "important", File.read(File.join(output, "keep.txt"))
|
||||
end
|
||||
end
|
||||
|
||||
def test_failed_atomic_install_restores_previous_model
|
||||
Dir.mktmpdir do |dir|
|
||||
data = MoonModel::DataSet.new(make_data(File.join(dir, "data.gz")))
|
||||
output = File.join(dir, "recoverable")
|
||||
common = { "size" => { "value" => 40 }, "resolution" => { "longitude_segments" => 24 },
|
||||
"output" => { "name" => "Recoverable" } }
|
||||
MoonModel::Generator.new(MoonModel::Config.new(common), data_set: data, output_dir: output).generate
|
||||
original = File.binread(File.join(output, "moon.3mf"))
|
||||
failing_class = Class.new(MoonModel::Generator) do
|
||||
private
|
||||
|
||||
def rename_path(from, to)
|
||||
@rename_count = @rename_count.to_i + 1
|
||||
raise IOError, "simulated install failure" if @rename_count == 2
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
error = assert_raises(IOError) do
|
||||
failing_class.new(MoonModel::Config.new(common.merge("assembly" => "eight_piece")),
|
||||
data_set: data, output_dir: output).generate
|
||||
end
|
||||
assert_equal "simulated install failure", error.message
|
||||
assert_equal original, File.binread(File.join(output, "moon.3mf"))
|
||||
assert_empty Dir[File.join(dir, ".recoverable.*")]
|
||||
end
|
||||
end
|
||||
|
||||
def test_safe_model_name_and_default_build_directory
|
||||
config = MoonModel::Config.new("output" => { "name" => "My 8-inch Moon!" })
|
||||
generator = MoonModel::Generator.new(config)
|
||||
|
||||
assert_equal "My_8-inch_Moon", MoonModel::Generator.safe_name("My 8-inch Moon!")
|
||||
assert_equal File.expand_path("../build/My_8-inch_Moon", __dir__), generator.output_dir
|
||||
assert_raises(ArgumentError) { MoonModel::Generator.safe_name("...") }
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user