diff --git a/automated_skeleton.py b/automated_skeleton.py index 98d4e324..df63808b 100644 --- a/automated_skeleton.py +++ b/automated_skeleton.py @@ -48,7 +48,7 @@ class Page: pid: int idx: int - in_swap: bool + on_disk: bool in_use: bool @property diff --git a/src/game_objects/page.py b/src/game_objects/page.py index 605e6ab7..ae33fbbd 100644 --- a/src/game_objects/page.py +++ b/src/game_objects/page.py @@ -1,5 +1,9 @@ +from typing import Optional + from engine.game_event_type import GameEventType from engine.game_object import GameObject +import game_monitor +from game_objects.page_slot import PageSlot from game_objects.views.page_view import PageView _BLINKING_INTERVAL_MS = 200 @@ -10,9 +14,17 @@ def __init__(self, pid, idx, page_manager): self._pid = pid self._idx = idx self._page_manager = page_manager + self._stage = page_manager.stage self._in_use = False - self._in_swap = False + + self._waiting_to_swap: bool = False + self._swapping_from: Optional[PageSlot] = None + self._swapping_to: Optional[PageSlot] = None + self._started_swap_at: Optional[int] = None + self._swap_percentage_completed: float = 0 + self._on_disk = False + self._display_blink_color = False super().__init__(PageView(self)) @@ -34,34 +46,78 @@ def in_use(self, value): self._in_use = value @property - def in_swap(self): - return self._in_swap + def swap_in_progress(self) -> bool: + return self._started_swap_at is not None + + @property + def swap_requested(self) -> bool: + return self._waiting_to_swap or self.swap_in_progress - @in_swap.setter - def in_swap(self, value): - self._in_swap = value + @property + def swap_percentage_completed(self) -> float: + return self._swap_percentage_completed + + @property + def on_disk(self): + return self._on_disk + + @on_disk.setter + def on_disk(self, value): + self._on_disk = value @property def display_blink_color(self): return self._display_blink_color - def swap(self, swap_whole_row : bool = False): + def request_swap(self, swap_whole_row : bool = False): + """The method called when the player clicks on the page.""" self._page_manager.swap_page(self, swap_whole_row) + def init_swap(self, swapping_from : PageSlot, swapping_to : PageSlot): + """The method called by the page manager to set the swap attributes.""" + self._swapping_from = swapping_from + self._swapping_to = swapping_to + self._waiting_to_swap = True + self._swap_percentage_completed = 0 + + def start_swap(self, current_time: int): + """The method called by the page manager to actually start the swap.""" + self._waiting_to_swap = False + self._started_swap_at = current_time + + def _update_swap(self, current_time): + """This method is called at each update. If a swap is in progress, it performs + appropriate checks and operations.""" + if self.swap_in_progress: + self._swap_percentage_completed = min(1, + (current_time - self._started_swap_at) + / self._stage.config.swap_delay_ms + ) + if self._swap_percentage_completed == 1: + self.view.set_xy(self._swapping_to.view.x, self._swapping_to.view.y) + self._swapping_from.page = None + self._swapping_from = None + self._swapping_to = None + self._started_swap_at = None + self._on_disk = not self._on_disk + self._swap_percentage_completed = 0 + game_monitor.notify_page_swap(self.pid, self.idx, self.on_disk) + def _check_if_clicked_on(self, event): if event.type in [GameEventType.MOUSE_LEFT_CLICK, GameEventType.MOUSE_LEFT_DRAG]: return self._view.collides(*event.get_property('position')) return False def _on_click(self, shift_down : bool): - self.swap(shift_down) + self.request_swap(shift_down) def update(self, current_time, events): for event in events: if self._check_if_clicked_on(event): self._on_click(event.get_property('shift')) - if self.in_use and self.in_swap: + self._update_swap(current_time) + if self.in_use and self.on_disk: self._display_blink_color = int(current_time / _BLINKING_INTERVAL_MS) % 2 == 1 else: self._display_blink_color = False diff --git a/src/game_objects/page_manager.py b/src/game_objects/page_manager.py index 2dce0955..88c288a3 100644 --- a/src/game_objects/page_manager.py +++ b/src/game_objects/page_manager.py @@ -1,4 +1,5 @@ -import game_monitor +from queue import Queue + from engine.game_object import GameObject from game_objects.views.page_manager_view import PageManagerView from game_objects.page import Page @@ -14,10 +15,10 @@ def __init__(self, stage): self._ram_slots = [] self._swap_slots = [] self._pages = {} + self._swap_queue = Queue() self._pages_in_ram_label_xy = (0, 0) - self._swap_is_enabled = True - self._pages_in_swap_label_xy = None + self._pages_on_disk_label_xy = None super().__init__(PageManagerView(self)) @@ -29,13 +30,17 @@ def get_total_rows(cls): def get_num_cols(cls): return cls._NUM_COLS + @property + def stage(self): + return self._stage + @property def pages_in_ram_label_xy(self): return self._pages_in_ram_label_xy @property - def pages_in_swap_label_xy(self): - return self._pages_in_swap_label_xy + def pages_on_disk_label_xy(self): + return self._pages_on_disk_label_xy def get_page(self, pid, idx): return self._pages[(pid, idx)] @@ -60,7 +65,7 @@ def setup(self): self.children.extend(self._ram_slots) if num_swap_rows > 0: - self._pages_in_swap_label_xy = ( + self._pages_on_disk_label_xy = ( self._stage.process_manager.view.width, 164 + num_ram_rows * PageSlot().view.height + num_ram_rows * 5) @@ -69,13 +74,11 @@ def setup(self): swap_slot = PageSlot() x = self._stage.process_manager.view.width + \ column * ram_slot.view.width + column * 5 - y = self._pages_in_swap_label_xy[1] + \ + y = self._pages_on_disk_label_xy[1] + \ 35 + row * ram_slot.view.height + row * 5 swap_slot.view.set_xy(x, y) self._swap_slots.append(swap_slot) self.children.extend(self._swap_slots) - else: - self._swap_is_enabled = False def create_page(self, pid, idx): page = Page(pid, idx, self) @@ -90,7 +93,7 @@ def create_page(self, pid, idx): for swap_slot in self._swap_slots: if not swap_slot.has_page: swap_slot.page = page - page.in_swap = True + page.on_disk = True page.view.set_xy(swap_slot.view.x, swap_slot.view.y) page_created = True break @@ -99,36 +102,42 @@ def create_page(self, pid, idx): return page def swap_page(self, page : Page, swap_whole_row : bool = False): - source_slots = self._swap_slots if page.in_swap else self._ram_slots - target_slots = self._ram_slots if page.in_swap else self._swap_slots + if page.swap_requested: + return + + source_slots = self._swap_slots if page.on_disk else self._ram_slots + target_slots = self._ram_slots if page.on_disk else self._swap_slots can_swap = False - previous_slot = None + swapping_from = None + swapping_to = None - for ram_slot in target_slots: - if not ram_slot.has_page: + for source_slot in source_slots: + if source_slot.page == page: + swapping_from = source_slot + break + for target_slot in target_slots: + if not target_slot.has_page: can_swap = True + swapping_to = target_slot break if can_swap: - for source_slot in source_slots: - if source_slot.page == page: - source_slot.page = None - previous_slot = source_slot - break - for target_slot in target_slots: - if not target_slot.has_page: - target_slot.page = page - page.view.set_xy(target_slot.view.x, target_slot.view.y) - break - page.in_swap = not page.in_swap - game_monitor.notify_page_swap(page.pid, page.idx, page.in_swap) + swapping_to.page = page + + queue_swap = bool([page for page in self._pages.values() if page.swap_in_progress]) + page.init_swap(swapping_from, swapping_to) + if queue_swap: + self._swap_queue.put(page) + else: + page.start_swap(self._stage.current_time) + if swap_whole_row: slots_on_same_row = [ slot for slot in source_slots if ( - slot.view.y == previous_slot.view.y - and slot != previous_slot + slot.view.y == swapping_from.view.y + and slot != swapping_from ) ] for slot in slots_on_same_row: @@ -146,3 +155,13 @@ def delete_page(self, page): break self.children.remove(page) del self._pages[(page.pid, page.idx)] + + def _handle_swap_queue(self): + if not self._swap_queue.empty(): + if not bool([page for page in self._pages.values() if page.swap_in_progress]): + page = self._swap_queue.get() + page.start_swap(self._stage.current_time) + + def update(self, current_time, events): + self._handle_swap_queue() + super().update(current_time, events) diff --git a/src/game_objects/process.py b/src/game_objects/process.py index 5eda439f..d12dc1c6 100644 --- a/src/game_objects/process.py +++ b/src/game_objects/process.py @@ -152,7 +152,7 @@ def use_cpu(self): for i in range(num_pages): page = self._page_manager.create_page(self._pid, i) self._pages.append(page) - game_monitor.notify_page_new(page.pid, page.idx, page.in_swap, page.in_use) + game_monitor.notify_page_new(page.pid, page.idx, page.on_disk, page.in_use) for page in self._pages: page.in_use = True game_monitor.notify_page_use(page.pid, page.idx, page.in_use) @@ -255,13 +255,13 @@ def _handle_events(self, events): if self._check_if_clicked_on(event): self._on_click() - def _handle_pages_in_swap(self): - pages_in_swap = 0 + def _handle_unavailable_pages(self): + unavailable_pages = 0 if self.has_cpu: for page in self._pages: - if page.in_swap: - pages_in_swap += 1 - self._set_waiting_for_page(pages_in_swap > 0) + if page.on_disk or page.swap_requested: + unavailable_pages += 1 + self._set_waiting_for_page(unavailable_pages > 0) def _update_starvation_level(self, current_time): if self.has_cpu and not self.is_blocked: @@ -297,7 +297,7 @@ def _handle_new_page_probability(self): self._pages.append(new_page) new_page.in_use = True game_monitor.notify_page_new( - new_page.pid, new_page.idx, new_page.in_swap, new_page.in_use) + new_page.pid, new_page.idx, new_page.on_disk, new_page.in_use) def _handle_graceful_termination_probability(self, current_time): if self.has_cpu and not self.is_blocked: @@ -319,7 +319,7 @@ def update(self, current_time, events): self._handle_events(events) if not self.has_ended: - self._handle_pages_in_swap() + self._handle_unavailable_pages() if current_time >= self._last_event_check_time + ONE_SECOND: self._last_event_check_time = current_time self._update_starvation_level(current_time) diff --git a/src/game_objects/views/page_manager_view.py b/src/game_objects/views/page_manager_view.py index 27b6a5ed..20650c2a 100644 --- a/src/game_objects/views/page_manager_view.py +++ b/src/game_objects/views/page_manager_view.py @@ -11,7 +11,7 @@ def __init__(self, page_manager): self._pages_in_ram_text_surface = FONT_PRIMARY_LARGE.render( 'Memory Pages in RAM :', False, Color.WHITE) - self._pages_in_swap_space_text_surface = FONT_PRIMARY_LARGE.render( + self._pages_on_disk_space_text_surface = FONT_PRIMARY_LARGE.render( 'Memory Pages on Disk :', False, Color.WHITE) @property @@ -25,6 +25,6 @@ def height(self): def draw(self, surface): surface.blit(self._pages_in_ram_text_surface, self._page_manager.pages_in_ram_label_xy) - if self._page_manager.pages_in_swap_label_xy is not None: - surface.blit(self._pages_in_swap_space_text_surface, - self._page_manager.pages_in_swap_label_xy) + if self._page_manager.pages_on_disk_label_xy is not None: + surface.blit(self._pages_on_disk_space_text_surface, + self._page_manager.pages_on_disk_label_xy) diff --git a/src/game_objects/views/page_view.py b/src/game_objects/views/page_view.py index c42e547f..617dd508 100644 --- a/src/game_objects/views/page_view.py +++ b/src/game_objects/views/page_view.py @@ -22,10 +22,22 @@ def height(self): def draw(self, surface): color = Color.DARK_GREY - if self._page.display_blink_color: + if self._page.swap_requested: + color = Color.TEAL + elif self._page.display_blink_color: color = Color.BLUE elif self._page.in_use: color = Color.WHITE pygame.draw.rect(surface, color, pygame.Rect( self._x, self._y, self.width, self.height)) surface.blit(self._pid_text_surface, (self._x + 1, self._y + 5)) + + if self._page.swap_in_progress: + progress_bar_width = (self.width - 4) * self._page.swap_percentage_completed + progress_bar_height = 2 + pygame.draw.rect(surface, Color.BLACK, pygame.Rect( + self._x + 2, + self._y + self.height - 4, + progress_bar_width, + progress_bar_height + )) diff --git a/src/scenes/stage.py b/src/scenes/stage.py index 9751e805..55468da5 100644 --- a/src/scenes/stage.py +++ b/src/scenes/stage.py @@ -192,7 +192,7 @@ def _process_script_events(self): event['pid']).toggle() elif event['type'] == 'page': self._page_manager.get_page( - event['pid'], event['idx']).swap() + event['pid'], event['idx']).request_swap() except Exception as exc: # pylint: disable=broad-exception-caught print(exc.__class__.__name__, *exc.args, event, file=sys.stderr) diff --git a/src/stage_config.py b/src/stage_config.py index 78504319..63b0a3fc 100644 --- a/src/stage_config.py +++ b/src/stage_config.py @@ -8,6 +8,7 @@ class StageConfig: num_processes_at_startup: int = 14 max_processes: int = MAX_PROCESSES num_ram_rows: int = 8 + swap_delay_ms: int = 100 new_process_probability: float = 0.05 priority_process_probability: float = 0.01 io_probability: float = 0.01 diff --git a/src/tests/game_objects/test_page.py b/src/tests/game_objects/test_page.py index e0a04b31..115d963e 100644 --- a/src/tests/game_objects/test_page.py +++ b/src/tests/game_objects/test_page.py @@ -4,6 +4,7 @@ from engine.game_event_type import GameEventType from game_objects.page import Page from game_objects.page_manager import PageManager +from game_objects.page_slot import PageSlot class TestPage: @pytest.fixture @@ -15,14 +16,14 @@ def test_initial_property_values(self, page_manager): assert page.pid == 1 assert page.idx == 1 assert not page.in_use - assert not page.in_swap + assert not page.on_disk - def test_in_swap_setter(self, page_manager): + def test_on_disk_setter(self, page_manager): page = Page(1, 1, page_manager) - page.in_swap = True - assert page.in_swap - page.in_swap = False - assert not page.in_swap + page.on_disk = True + assert page.on_disk + page.on_disk = False + assert not page.on_disk def test_in_use_setter(self, page_manager): page = Page(1, 1, page_manager) @@ -31,7 +32,7 @@ def test_in_use_setter(self, page_manager): page.in_use = False assert not page.in_use - def test_swap(self, page_manager, monkeypatch): + def test_request_swap(self, page_manager, monkeypatch): page_arg = None swap_whole_row_arg = None @@ -43,12 +44,61 @@ def swap_page_mock(page, swap_whole_row): monkeypatch.setattr(page_manager, 'swap_page', swap_page_mock) page = Page(1, 1, page_manager) - page.swap() + page.request_swap() assert page_arg == page assert not swap_whole_row_arg - def test_click_when_not_in_swap(self, page_manager, monkeypatch): + def test_swap(self, page_manager): + page = Page(1, 1, page_manager) + + swapping_from = PageSlot() + swapping_to = PageSlot() + swapping_from.page = page + swapping_to.page = page + + assert not page.swap_requested + assert not page.swap_in_progress + assert not page.on_disk + assert page.swap_percentage_completed == 0 + + page.init_swap(swapping_from, swapping_to) + + assert page.swap_requested + assert not page.swap_in_progress + assert not page.on_disk + assert page.swap_percentage_completed == 0 + assert swapping_from.page == page + assert swapping_to.page == page + + page.start_swap(0) + + assert page.swap_requested + assert page.swap_in_progress + assert not page.on_disk + assert page.swap_percentage_completed == 0 + assert swapping_from.page == page + assert swapping_to.page == page + + page.update(page_manager.stage.config.swap_delay_ms // 2, []) + + assert page.swap_requested + assert page.swap_in_progress + assert not page.on_disk + assert page.swap_percentage_completed == 0.5 + assert swapping_from.page == page + assert swapping_to.page == page + + page.update(page_manager.stage.config.swap_delay_ms, []) + + assert not page.swap_requested + assert not page.swap_in_progress + assert page.on_disk + assert page.swap_percentage_completed == 0 + assert swapping_from.page is None + assert swapping_to.page == page + + def test_click_when_not_on_disk(self, page_manager, monkeypatch): page_arg = None swap_whole_row_arg = None @@ -69,7 +119,7 @@ def swap_page_mock(page, swap_whole_row): assert page_arg == page assert not swap_whole_row_arg - def test_click_wnen_in_swap(self, page_manager, monkeypatch): + def test_click_wnen_on_disk(self, page_manager, monkeypatch): page_arg = None swap_whole_row_arg = None @@ -81,7 +131,7 @@ def swap_page_mock(page, swap_whole_row): monkeypatch.setattr(page_manager, 'swap_page', swap_page_mock) page = Page(1, 1, page_manager) - page.in_swap = True + page.on_disk = True page.view.set_xy(1000, 500) mouse_click_event = GameEvent(GameEventType.MOUSE_LEFT_CLICK, @@ -91,7 +141,7 @@ def swap_page_mock(page, swap_whole_row): assert page_arg == page assert not swap_whole_row_arg - def test_shift_click_when_not_in_swap(self, page_manager, monkeypatch): + def test_shift_click_when_not_on_disk(self, page_manager, monkeypatch): page_arg = None swap_whole_row_arg = None @@ -112,7 +162,7 @@ def swap_page_mock(page, swap_whole_row): assert page_arg == page assert swap_whole_row_arg - def test_shift_click_wnen_in_swap(self, page_manager, monkeypatch): + def test_shift_click_wnen_on_disk(self, page_manager, monkeypatch): page_arg = None swap_whole_row_arg = None @@ -124,7 +174,7 @@ def swap_page_mock(page, swap_whole_row): monkeypatch.setattr(page_manager, 'swap_page', swap_page_mock) page = Page(1, 1, page_manager) - page.in_swap = True + page.on_disk = True page.view.set_xy(1000, 500) mouse_click_event = GameEvent(GameEventType.MOUSE_LEFT_CLICK, @@ -137,7 +187,7 @@ def swap_page_mock(page, swap_whole_row): def test_blinking_animation(self, page_manager): page = Page(1, 1, page_manager) page.in_use = True - page.in_swap = True + page.on_disk = True previous_blink_value = page.display_blink_color for i in range(1, 5): @@ -148,7 +198,7 @@ def test_blinking_animation(self, page_manager): def test_blinking_animation_deactivation_after_stopping_use(self, page_manager): page = Page(1, 1, page_manager) page.in_use = True - page.in_swap = True + page.on_disk = True page.update(1000, []) page.update(1200, []) @@ -162,12 +212,12 @@ def test_blinking_animation_deactivation_after_stopping_use(self, page_manager): def test_blinking_animation_deactivation_after_removing_from_swap(self, page_manager): page = Page(1, 1, page_manager) page.in_use = True - page.in_swap = True + page.on_disk = True page.update(1000, []) page.update(1200, []) - page.in_swap = False + page.on_disk = False for i in range(1, 5): page.update(i * 200, []) @@ -176,12 +226,12 @@ def test_blinking_animation_deactivation_after_removing_from_swap(self, page_man def test_blinking_animation_deactivation_after_removing_from_swap_and_use(self, page_manager): page = Page(1, 1, page_manager) page.in_use = True - page.in_swap = True + page.on_disk = True page.update(1000, []) page.update(1200, []) - page.in_swap = False + page.on_disk = False page.in_use = False for i in range(1, 5): diff --git a/src/tests/game_objects/test_page_manager.py b/src/tests/game_objects/test_page_manager.py index a3bef63f..958cc4bf 100644 --- a/src/tests/game_objects/test_page_manager.py +++ b/src/tests/game_objects/test_page_manager.py @@ -30,7 +30,7 @@ def test_create_page_in_ram(self, page_manager): page1 = page_manager.create_page(5, 0) assert page1.pid == 5 assert page1.idx == 0 - assert not page1.in_swap + assert not page1.on_disk num_pages = len([child for child in page_manager.children if isinstance(child, Page)]) assert num_pages == 1 assert page1 == next(child for child in page_manager.children if isinstance(child, Page)) @@ -38,7 +38,7 @@ def test_create_page_in_ram(self, page_manager): page2 = page_manager.create_page(5, 1) assert page2.pid == 5 assert page2.idx == 1 - assert not page2.in_swap + assert not page2.on_disk num_pages = len([child for child in page_manager.children if isinstance(child, Page)]) assert num_pages == 2 assert page1 in [child for child in page_manager.children if isinstance(child, Page)] @@ -47,7 +47,7 @@ def test_create_page_in_ram(self, page_manager): page3 = page_manager.create_page(6, 0) assert page3.pid == 6 assert page3.idx == 0 - assert not page3.in_swap + assert not page3.on_disk num_pages = len([child for child in page_manager.children if isinstance(child, Page)]) assert num_pages == 3 assert page1 in [child for child in page_manager.children if isinstance(child, Page)] @@ -57,7 +57,7 @@ def test_create_page_in_ram(self, page_manager): assert page1.view.y == page2.view.y == page3.view.y assert page3.view.x > page2.view.x > page1.view.x - def test_create_page_in_swap(self, page_manager): + def test_create_page_on_disk(self, page_manager): pages_in_ram = [] for i in range(PageManager.get_num_cols()): pages_in_ram.append(page_manager.create_page(1, i)) @@ -68,19 +68,19 @@ def test_create_page_in_swap(self, page_manager): page1 = page_manager.create_page(2, 0) assert page1.pid == 2 assert page1.idx == 0 - assert page1.in_swap + assert page1.on_disk num_pages = len([child for child in page_manager.children if isinstance(child, Page)]) assert num_pages == PageManager.get_num_cols() + 1 - assert page1 == next(child for child in page_manager.children if isinstance(child, Page) and child.in_swap) + assert page1 == next(child for child in page_manager.children if isinstance(child, Page) and child.on_disk) page2 = page_manager.create_page(2, 1) assert page2.pid == 2 assert page2.idx == 1 - assert page2.in_swap + assert page2.on_disk num_pages = len([child for child in page_manager.children if isinstance(child, Page)]) assert num_pages == PageManager.get_num_cols() + 2 - assert page1 in [child for child in page_manager.children if isinstance(child, Page) and child.in_swap] - assert page2 in [child for child in page_manager.children if isinstance(child, Page) and child.in_swap] + assert page1 in [child for child in page_manager.children if isinstance(child, Page) and child.on_disk] + assert page2 in [child for child in page_manager.children if isinstance(child, Page) and child.on_disk] for ram_page in pages_in_ram: assert ram_page.view.y < page1.view.y @@ -95,18 +95,42 @@ def test_swap_page_when_can_swap(self, page_manager): for i in range(PageManager.get_num_cols() * 2): pages.append(page_manager.create_page(1, i)) + time = 2000 + page_manager.update(time, []) + page_manager.swap_page(pages[0]) - assert pages[0].in_swap + assert not pages[0].on_disk + assert pages[0].swap_requested + assert pages[0].swap_in_progress + time += 1000 + page_manager.update(time, []) + assert pages[0].on_disk + assert not pages[0].swap_requested + assert not pages[0].swap_in_progress assert pages[0].view.y > pages[PageManager.get_num_cols()].view.y assert pages[0].view.x == pages[PageManager.get_num_cols()].view.x page_manager.swap_page(pages[2]) - assert pages[2].in_swap + assert not pages[2].on_disk + assert pages[2].swap_requested + assert pages[2].swap_in_progress + time += 1000 + page_manager.update(time, []) + assert pages[2].on_disk + assert not pages[2].swap_requested + assert not pages[2].swap_in_progress assert pages[2].view.y > pages[PageManager.get_num_cols()].view.y assert pages[2].view.x == pages[PageManager.get_num_cols() + 1].view.x page_manager.swap_page(pages[2]) - assert not pages[2].in_swap + assert pages[2].on_disk + assert pages[2].swap_requested + assert pages[2].swap_in_progress + time += 1000 + page_manager.update(time, []) + assert not pages[2].on_disk + assert not pages[2].swap_requested + assert not pages[2].swap_in_progress assert pages[2].view.y == pages[1].view.y assert pages[2].view.x < pages[1].view.x @@ -116,13 +140,13 @@ def test_swap_page_when_cannot_swap(self, page_manager): for i in range(PageManager.get_num_cols() * 2): pages.append(page_manager.create_page(1, i)) - assert pages[PageManager.get_num_cols()].in_swap + assert pages[PageManager.get_num_cols()].on_disk (old_x, old_y) = (pages[PageManager.get_num_cols()].view.x, pages[PageManager.get_num_cols()].view.y) page_manager.swap_page(pages[PageManager.get_num_cols()]) - assert pages[PageManager.get_num_cols()].in_swap + assert pages[PageManager.get_num_cols()].on_disk assert pages[PageManager.get_num_cols()].view.x == old_x assert pages[PageManager.get_num_cols()].view.y == old_y @@ -132,25 +156,32 @@ def test_swap_whole_row(self, page_manager): for i in range(PageManager.get_num_cols() * 2): pages.append(page_manager.create_page(1, i)) + time = 10000 + page_manager.update(time, []) + page_manager.swap_page(pages[0], swap_whole_row=True) for i in range(PageManager.get_num_cols()): - assert pages[i].in_swap + time += page_manager.stage.config.swap_delay_ms + page_manager.update(time, []) + assert pages[i].on_disk assert pages[i].view.x == pages[PageManager.get_num_cols() + i].view.x assert pages[i].view.y > pages[PageManager.get_num_cols() + i].view.y new_page = page_manager.create_page(2, 0) - assert not new_page.in_swap + assert not new_page.on_disk old_y = pages[0].view.y page_manager.swap_page(pages[0], swap_whole_row=True) for i in range(PageManager.get_num_cols() - 1): - assert not pages[i].in_swap + time += page_manager.stage.config.swap_delay_ms + page_manager.update(time, []) + assert not pages[i].on_disk assert pages[i].view.x == pages[PageManager.get_num_cols() + i + 1].view.x assert pages[i].view.y == new_page.view.y - assert pages[PageManager.get_num_cols() - 1].in_swap + assert pages[PageManager.get_num_cols() - 1].on_disk assert pages[PageManager.get_num_cols() - 1].view.x == pages[PageManager.get_num_cols() - 1].view.x assert pages[PageManager.get_num_cols() - 1].view.y == old_y @@ -161,7 +192,7 @@ def test_delete_page_in_ram(self, page_manager): pages.append(page_manager.create_page(1, i)) page_to_delete = pages[1] - assert not page_to_delete.in_swap + assert not page_to_delete.on_disk containing_slot = next(( child for child in page_manager.children if isinstance(child, PageSlot) and child.page == page_to_delete @@ -175,14 +206,14 @@ def test_delete_page_in_ram(self, page_manager): ), None) assert containing_slot is None - def test_delete_page_in_swap(self, page_manager): + def test_delete_page_on_disk(self, page_manager): pages = [] for i in range(PageManager.get_num_cols() * 2): pages.append(page_manager.create_page(1, i)) page_to_delete = pages[PageManager.get_num_cols() + 1] - assert page_to_delete.in_swap + assert page_to_delete.on_disk containing_slot = next(( child for child in page_manager.children if isinstance(child, PageSlot) and child.page == page_to_delete diff --git a/src/tests/game_objects/test_process.py b/src/tests/game_objects/test_process.py index bc3f3c96..6c1dd352 100644 --- a/src/tests/game_objects/test_process.py +++ b/src/tests/game_objects/test_process.py @@ -368,8 +368,10 @@ def test_set_page_to_swap_while_running(self, stage, monkeypatch): process.use_cpu() - stage.page_manager.get_page(1, 0).swap() - assert stage.page_manager.get_page(1, 0).in_swap == True + + stage.page_manager.get_page(1, 0).request_swap() + stage.page_manager.update(1000, []) + assert stage.page_manager.get_page(1, 0).on_disk == True process.update(0, []) @@ -386,8 +388,9 @@ def test_set_page_to_swap_before_running(self, stage, monkeypatch): process.use_cpu() process.yield_cpu() - stage.page_manager.get_page(1, 0).swap() - assert stage.page_manager.get_page(1, 0).in_swap == True + stage.page_manager.get_page(1, 0).request_swap() + stage.page_manager.update(1000, []) + assert stage.page_manager.get_page(1, 0).on_disk == True process.use_cpu() @@ -405,11 +408,13 @@ def test_remove_page_from_swap_while_running(self, stage, monkeypatch): process.use_cpu() - stage.page_manager.get_page(1, 0).swap() + stage.page_manager.get_page(1, 0).request_swap() + stage.page_manager.update(1000, []) process.update(0, []) assert process.is_blocked == True - stage.page_manager.get_page(1, 0).swap() + stage.page_manager.get_page(1, 0).request_swap() + stage.page_manager.update(2000, []) process.update(0, []) assert process.is_blocked == False @@ -424,7 +429,8 @@ def test_yield_cpu_while_waiting_for_page(self, stage, monkeypatch): process.use_cpu() - stage.page_manager.get_page(1, 0).swap() + stage.page_manager.get_page(1, 0).request_swap() + stage.page_manager.update(1000, []) process.update(0, []) assert process.is_waiting_for_page == True @@ -443,7 +449,8 @@ def test_starvation_while_waiting_for_page(self, stage, monkeypatch): process.use_cpu() - stage.page_manager.get_page(1, 0).swap() + stage.page_manager.get_page(1, 0).request_swap() + stage.page_manager.update(1000, []) process.update(0, []) assert process.is_waiting_for_page == True @@ -462,7 +469,8 @@ def test_page_deletion_when_process_is_killed(self, stage, monkeypatch): process = Process(1, stage) process.use_cpu() - stage.page_manager.get_page(1, 0).swap() + stage.page_manager.get_page(1, 0).request_swap() + stage.page_manager.update(1000, []) for i in range(1, DEAD_STARVATION_LEVEL): process.update(i * process.time_between_starvation_levels, []) @@ -808,7 +816,7 @@ def test_blinking_animation(self, stage): process = Process(1, stage) process.use_cpu() - stage.page_manager.get_page(1, 0).swap() + stage.page_manager.get_page(1, 0).request_swap() previous_blink_value = process.display_blink_color for i in range(1, 5): @@ -820,10 +828,12 @@ def test_blinking_animation_deactivation(self, stage): process = Process(1, stage) process.use_cpu() - stage.page_manager.get_page(1, 0).swap() + stage.page_manager.get_page(1, 0).request_swap() + stage.page_manager.update(1000, []) process.update(1000, []) - stage.page_manager.get_page(1, 0).swap() + stage.page_manager.get_page(1, 0).request_swap() + stage.page_manager.update(2000, []) process.update(2000, []) for i in range(1, 5):