import shutil import tempfile import tracemalloc import unittest from pathlib import Path import numpy as np from mapgen import pipeline as P from mapgen import render as RN from mapgen.testing import small_world def _files(root: Path) -> dict: return {p.relative_to(root).as_posix(): p.read_bytes() for p in sorted(root.rglob("*")) if p.is_file() and "cache" not in p.parts} class LowMemoryTest(unittest.TestCase): def test_low_memory_build_writes_identical_files(self): # oracle: the normal-mode build of the same world; every output byte must match outs = [] for low in (False, True): tmp = Path(tempfile.mkdtemp()) try: small_world(tmp) P.build(tmp, 2, log=lambda m: None, low_memory=low) outs.append({**_files(tmp / "out"), **_files(tmp / "previews")}) finally: shutil.rmtree(tmp) self.assertEqual(sorted(outs[0]), sorted(outs[1])) for k in outs[0]: self.assertEqual(outs[0][k], outs[1][k], k) def test_chunked_relief_matches_and_uses_less_memory(self): rng = np.random.default_rng(0) H, W = 512, 1024 z = rng.normal(0, 2000, (H, W)) hs = rng.random((H, W)) zone = rng.integers(0, 38, (H, W)).astype(np.int16) ground = rng.integers(0, 9, (H, W)).astype(np.int8) ice = rng.integers(0, 5, (H, W)).astype(np.int8) lake = rng.random((H, W)) < 0.05 peaks = [] outs = [] for low in (False, True): tracemalloc.start() outs.append(RN.relief_rgb(z, hs, zone, ground, ice, lake, low_memory=low)) peaks.append(tracemalloc.get_traced_memory()[1]) tracemalloc.stop() np.testing.assert_array_equal(outs[0], outs[1]) self.assertLess(peaks[1], 0.4 * peaks[0]) # measured ≈ 0.28 class ProjectionMemoryTest(unittest.TestCase): def test_sampling_converts_one_channel_at_a_time(self): from mapgen import projections as PJ rng = np.random.default_rng(1) img = rng.integers(0, 256, (512, 1024, 3), dtype=np.uint8) lat = rng.uniform(-90, 90, (64, 64)) lon = rng.uniform(-180, 180, (64, 64)) whole = img.astype(np.float64) # oracle: the whole-image float conversion want = np.stack([PJ.sample_equirect(whole[..., k], lat, lon) for k in range(3)], axis=-1) del whole tracemalloc.start() got = PJ._sample_rgb(img, lat, lon) peak = tracemalloc.get_traced_memory()[1] tracemalloc.stop() np.testing.assert_array_equal(got, want) self.assertLess(peak, 0.5 * img.size * 8) # no full-size float64 copy class HillshadeTest(unittest.TestCase): def test_chunked_hillshade_matches_and_uses_less_memory(self): z = np.random.default_rng(2).normal(0, 1500, (700, 1400)) # 700 rows: chunk edges fall mid-raster peaks, outs = [], [] for low in (False, True): tracemalloc.start() outs.append(RN.hillshade(z, 6371.0, low_memory=low)) peaks.append(tracemalloc.get_traced_memory()[1]) tracemalloc.stop() np.testing.assert_array_equal(outs[0], outs[1]) self.assertLess(peaks[1], 0.5 * peaks[0])