diff options
Diffstat (limited to 'tests/test_low_memory.py')
| -rw-r--r-- | tests/test_low_memory.py | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/tests/test_low_memory.py b/tests/test_low_memory.py new file mode 100644 index 0000000..c5ed333 --- /dev/null +++ b/tests/test_low_memory.py @@ -0,0 +1,83 @@ +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]) |
