<reponame>aaarsene/o3de
"""
Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.

SPDX-License-Identifier: Apache-2.0 OR MIT

Fixture that allows Idle check of the AP GUI
"""

# Import builtin libraries
import pytest
import os
import time

# Import fixtures
from . import ap_setup_fixture

# Import LyTestTools
import ly_test_tools.environment.waiter as waiter
from ly_test_tools.o3de.ap_log_parser import APLogParser


@pytest.mark.usefixtures("test_assets")
class TimestampChecker(object):
    def __init__(self, file_path, timeout) -> None:
        self.file = file_path
        self.timeout = timeout
        self.original_mod_time = int(round(time.time() * 1000))
        self.start_time = time.time()
        self.log = None

    def set_file_path(self, file_path):
        self.file = file_path

    def grab_current_timestamp(self) -> None:
        self.original_mod_time = int(round(time.time() * 1000))

    def check_if_idle(self, timeout=None, starttime=None, updatetime_max=30) -> None:
        if timeout is None:
            timeout = self.timeout
        if starttime:
            time.sleep(starttime)

        def log_reports_idle() -> bool:
            """
            Grabs the current log run and reads it line by line from the bottom up
            Returns whether the idle message appears later in the log than the latest "Processing [...]" message
            """
            if updatetime_max and os.path.exists(self.file):
                last_file_update = os.path.getmtime(self.file)
                timedelta = time.time() - last_file_update
                if timedelta > updatetime_max:  # Has the file exceeded the limit
                    # Additionally we want to make sure the test has exceeded the limit so we don't catch
                    # a log from a previous run where our current test hasn't engaged any action from AP
                    if time.time() - self.start_time > updatetime_max:
                        return True
            self.log = APLogParser(self.file)
            line_index = len(self.log.runs[-1]["Lines"]) - 1
            while line_index > 0:
                line = self.log.runs[-1]["Lines"][line_index]
                timestamp = self.log.runs[-1]["Timestamps"][line_index]
                if self.log.get_line_type(line) == "AssetProcessor":
                    message = self.log.remove_line_type(line)
                    if timestamp <= self.original_mod_time:
                        return False
                    elif message.startswith("Processing"):
                        return False
                    elif "Job processing completed. Asset Processor is currently idle." in message:
                        self.original_mod_time = timestamp
                        return True
                line_index -= 1

        waiter.wait_for(lambda: (log_reports_idle()), timeout=timeout or self.timeout)


@pytest.fixture
def ap_idle_fixture(request, workspace, timeout: int) -> TimestampChecker:
    """
    Allows checking the GUI for idle by grabbing the initial modified time of the log file
    and looking for new "idle" messages later
    """
    return TimestampChecker(workspace.paths.ap_gui_log(), timeout, workspace)

"""
Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.

SPDX-License-Identifier: Apache-2.0 OR MIT

Fixture that allows Idle check of the AP GUI
"""

# Import builtin libraries
import pytest
import os
import time

# Import fixtures
from . import ap_setup_fixture

# Import LyTestTools
import ly_test_tools.environment.waiter as waiter
from ly_test_tools.o3de.ap_log_parser import APLogParser


@pytest.mark.usefixtures("test_assets")
class TimestampChecker(object):
    def __init__(self, file_path, timeout) -> None:
        self.file = file_path
        self.timeout = timeout
        self.original_mod_time = int(round(time.time() * 1000))
        self.start_time = time.time()
        self.log = None

    def set_file_path(self, file_path):
        self.file = file_path

    def grab_current_timestamp(self) -> None:
        self.original_mod_time = int(round(time.time() * 1000))

    def check_if_idle(self, timeout=None, starttime=None, updatetime_max=30) -> None:
        if timeout is None:
            timeout = self.timeout
        if starttime:
            time.sleep(starttime)

        def log_reports_idle() -> bool:
            """
            Grabs the current log run and reads it line by line from the bottom up
            Returns whether the idle message appears later in the log than the latest "Processing [...]" message
            """
            if updatetime_max and os.path.exists(self.file):
                last_file_update = os.path.getmtime(self.file)
                timedelta = time.time() - last_file_update
                if timedelta > updatetime_max:  # Has the file exceeded the limit
                    # Additionally we want to make sure the test has exceeded the limit so we don't catch
                    # a log from a previous run where our current test hasn't engaged any action from AP
                    if time.time() - self.start_time > updatetime_max:
                        return True
            self.log = APLogParser(self.file)
            line_index = len(self.log.runs[-1]["Lines"]) - 1
            while line_index > 0:
                line = self.log.runs[-1]["Lines"][line_index]
                timestamp = self.log.runs[-1]["Timestamps"][line_index]
                if self.log.get_line_type(line) == "AssetProcessor":
                    message = self.log.remove_line_type(line)
                    if timestamp <= self.original_mod_time:
                        return False
                    elif message.startswith("Processing"):
                        return False
                    elif "Job processing completed. Asset Processor is currently idle." in message:
                        self.original_mod_time = timestamp
                        return True
                line_index -= 1

        waiter.wait_for(lambda: (log_reports_idle()), timeout=timeout or self.timeout)


@pytest.fixture
def ap_idle_fixture(request, workspace, timeout: int) -> TimestampChecker:
    """
    Allows checking the GUI for idle by grabbing the initial modified time of the log file
    and looking for new "idle" messages later
    """
    return TimestampChecker(workspace.paths.ap_gui_log(), timeout, workspace)
Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.  SPDX-License-Identifier: Apache-2.0 OR MIT  Fixture that allows Idle check of the AP GUI # Import builtin libraries # Import fixtures # Import LyTestTools Grabs the current log run and reads it line by line from the bottom up             Returns whether the idle message appears later in the log than the latest "Processing [...]" message # Has the file exceeded the limit # Additionally we want to make sure the test has exceeded the limit so we don't catch # a log from a previous run where our current test hasn't engaged any action from AP Allows checking the GUI for idle by grabbing the initial modified time of the log file     and looking for new "idle" messages later