# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. """Unit tests for imageserver.util extent coalescing helpers.""" import unittest from imageserver.util import ( coalesce_allocation_extents, coalesce_dirty_zero_extents, merge_dirty_zero_extents, ) class TestCoalesceAllocationExtents(unittest.TestCase): def test_empty(self): self.assertEqual(coalesce_allocation_extents([]), []) def test_single(self): inp = [{"start": 0, "length": 4096, "zero": False}] out = coalesce_allocation_extents(inp) self.assertEqual(out, [{"start": 0, "length": 4096, "zero": False}]) self.assertIsNot(out[0], inp[0]) def test_merges_contiguous_same_zero(self): inp = [ {"start": 0, "length": 10, "zero": False}, {"start": 10, "length": 5, "zero": False}, {"start": 15, "length": 100, "zero": False}, ] self.assertEqual( coalesce_allocation_extents(inp), [{"start": 0, "length": 115, "zero": False}], ) def test_does_not_merge_different_zero(self): inp = [ {"start": 0, "length": 64, "zero": False}, {"start": 64, "length": 64, "zero": True}, {"start": 128, "length": 64, "zero": False}, ] self.assertEqual(coalesce_allocation_extents(inp), inp) def test_does_not_merge_gap(self): inp = [ {"start": 0, "length": 100, "zero": False}, {"start": 200, "length": 50, "zero": False}, ] self.assertEqual(coalesce_allocation_extents(inp), inp) def test_does_not_merge_same_zero_with_gap(self): inp = [ {"start": 0, "length": 10, "zero": True}, {"start": 20, "length": 10, "zero": True}, ] self.assertEqual(coalesce_allocation_extents(inp), inp) class TestCoalesceDirtyZeroExtents(unittest.TestCase): def test_empty(self): self.assertEqual(coalesce_dirty_zero_extents([]), []) def test_single(self): inp = [{"start": 0, "length": 8192, "dirty": True, "zero": False}] out = coalesce_dirty_zero_extents(inp) self.assertEqual( out, [{"start": 0, "length": 8192, "dirty": True, "zero": False}] ) def test_merges_contiguous_same_flags(self): inp = [ {"start": 0, "length": 50, "dirty": True, "zero": False}, {"start": 50, "length": 50, "dirty": True, "zero": False}, ] self.assertEqual( coalesce_dirty_zero_extents(inp), [{"start": 0, "length": 100, "dirty": True, "zero": False}], ) def test_does_not_merge_differing_dirty(self): inp = [ {"start": 0, "length": 32, "dirty": False, "zero": False}, {"start": 32, "length": 32, "dirty": True, "zero": False}, ] self.assertEqual(coalesce_dirty_zero_extents(inp), inp) def test_does_not_merge_differing_zero(self): inp = [ {"start": 0, "length": 16, "dirty": False, "zero": False}, {"start": 16, "length": 16, "dirty": False, "zero": True}, ] self.assertEqual(coalesce_dirty_zero_extents(inp), inp) class TestMergeDirtyZeroExtentsCoalescing(unittest.TestCase): def test_coalesces_adjacent_identical_flags_after_boundary_merge(self): """Boundary grid can split one logical run; coalesce should reunite.""" allocation = [(0, 200, False)] dirty = [(0, 100, False), (100, 100, False)] merged = merge_dirty_zero_extents(allocation, dirty, 200) self.assertEqual( merged, [{"start": 0, "length": 200, "dirty": False, "zero": False}], ) if __name__ == "__main__": unittest.main()