diff --git a/tools/blender/tests/smoke_frame.py b/tools/blender/tests/smoke_frame.py index 9bcf10789..d9cd6a805 100644 --- a/tools/blender/tests/smoke_frame.py +++ b/tools/blender/tests/smoke_frame.py @@ -35,7 +35,7 @@ SHIP_ID = "smoke.frame" GAME = Path(os.environ.get("SMOKE_GAME_FOLDER") or sys.exit("Set SMOKE_GAME_FOLDER to a folder holding GameData/Aetheria.cc and ModTools/AetherDb")) MODS = GAME / "GameData" / "Mods" COLLECTION = "Smoke Frame" -NAMES_NOT_ECHOED = (SHIP_ID, COLLECTION, "Second Frame", "Loose Nub", "Hull", str(GAME), GAME.name) +NAMES_NOT_ECHOED = (SHIP_ID, COLLECTION, "Second Frame", "Loose Nub", "Hull", "NoSuchHullXYZ", str(GAME), GAME.name) def new_object(collection, name, mesh, location=(0, 0, 0), parent=None): @@ -237,7 +237,12 @@ def main(): root = bpy.data.objects["Ship Root"] print("PASS 1 new ship ok") - # Pass 2: a Save that fails after create removes what it made; the retry succeeds. + # Pass 2: a Save that fails in create or after it leaves nothing behind and tells the author nothing of the input; + # the retry succeeds. + collection["aetheria.pending"] = ["Smoke Frame", "NoSuchHullXYZ"] + refused(bpy.ops.aetheria.save_ship_layout, "AetherDb refused to create the ship", "Save with an unknown reference hull") + require(not (MODS / SHIP_ID).exists(), "A refused create left the ship folder behind") + collection["aetheria.pending"] = ["Smoke Frame", "Djinni"] real = aetheria_ships.replace_layout def failing(*args, **kwargs): @@ -323,9 +328,10 @@ def main(): require(snapshot == (buffer(bpy.context.scene), list(collection["aetheria.grid_origin"]), [tuple(map(tuple, child_obj.matrix_world)) for child_obj in root.children]), f"{what} changed the scene while refusing") - for obj in (render, nub): - obj.parent = root - obj.matrix_parent_inverse = root.matrix_world.inverted() + render.parent = root # Ship Root's descendants count, however deep: the nub hangs from the hull + render.matrix_parent_inverse = root.matrix_world.inverted() + nub.parent = render + nub.matrix_parent_inverse = render.matrix_world.inverted() select(render) result, message = run(bpy.ops.aetheria.rasterise_hull) require(result == {"FINISHED"}, f"Rasterise Hull was refused: {message}") diff --git a/tools/blender/tests/test_ship_cc.py b/tools/blender/tests/test_ship_cc.py index 4a9c045d8..bd39a83e3 100644 --- a/tools/blender/tests/test_ship_cc.py +++ b/tools/blender/tests/test_ship_cc.py @@ -519,6 +519,27 @@ class CSharpWrittenFixtureTests(unittest.TestCase): shutil.copy(Path(os.environ["SHIP_FIXTURE_DIR"]) / "mod.skiff" / "skiff.glb", target / "skiff.glb") +class RefusalsNameNoInputTests(ShipFileCase): + def test_refusals_name_no_path_mount_or_anchor_id(self): + _, _, revision = ship_cc.read_layout(self.path, PACKAGES) + mount = "mount.zq-unique" + duplicate = [[ "anchor.zq-unique", "map-icon", "n1", None, 0], ["anchor.zq-unique", "shield", "n2", None, 0]] + bad_footprint = ship_cc.encode_hardpoint( + Type=3, Position=[1, 0], Shape=[[1, 1, [0]]], Transform=mount, Rotation=0, Armor=0.0, FiringArc=0.0) + empty_footprint = ship_cc.encode_hardpoint( + Type=3, Position=[1, 0], Shape=[[1, 1, [False]]], Transform=mount, Rotation=0, Armor=0.0, FiringArc=0.0) + calls = (lambda: ship_cc.replace_visual(self.path, PACKAGES, "mod.skiff", "ship.glb", duplicate), + lambda: ship_cc.replace_layout(self.path, PACKAGES, "mod.skiff", revision, [2, 2, [True] * 4], [bad_footprint]), + lambda: ship_cc.replace_layout(self.path, PACKAGES, "mod.skiff", revision, [2, 2, [True] * 4], [empty_footprint]), + lambda: ship_cc.read(os.path.join(self.path, "missing.cc"), PACKAGES)) + for call in calls: + with self.subTest(call): + with self.assertRaises(Exception) as caught: + call() + for forbidden in ("zq-unique", self.path, os.path.dirname(self.path)): + self.assertNotIn(forbidden, str(caught.exception)) + + class ShipIdTests(unittest.TestCase): def test_admits_the_ids_the_c_sharp_rule_admits(self): for ship_id in ("probe.a", "a", "0x", "a_b-c", "com10", "com0", "lpt0", "console", "aux2", "a.nul", "x.com1"):