# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2015, ARM Limited and contributors.
#
# Licensed 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.
#

import logging
import os

from test import LisaTest

import trappy
from bart.common.Analyzer import Analyzer

TESTS_DIRECTORY = os.path.dirname(os.path.realpath(__file__))
TESTS_CONF = os.path.join(TESTS_DIRECTORY, "smoke_test_ramp.config")

class STune(LisaTest):
    """Tests for SchedTune framework"""

    @classmethod
    def setUpClass(cls, *args, **kwargs):
        super(STune, cls)._init(TESTS_CONF, *args, **kwargs)

    def test_boosted_utilization_signal(self):
        """The boosted utilization signal is appropriately boosted

        The margin should match the formula
        (sched_load_scale - util) * boost"""

        for tc in self.conf["confs"]:
            test_id = tc["tag"]

            wload_idx = self.conf["wloads"].keys()[0]
            run_dir = os.path.join(self.te.res_dir,
                                   "rtapp:{}:{}".format(test_id, wload_idx),
                                   "1")

            ftrace_events = ["sched_boost_task"]
            ftrace = trappy.FTrace(run_dir, scope="custom",
                                   events=ftrace_events)

            first_task_params = self.conf["wloads"][wload_idx]["conf"]["params"]
            first_task_name = first_task_params.keys()[0]
            rta_task_name = "task_{}".format(first_task_name)

            sbt_dfr = ftrace.sched_boost_task.data_frame
            boost_task_rtapp = sbt_dfr[sbt_dfr.comm == rta_task_name]

            # Avoid the first period as the task starts with a very
            # high load and it overutilizes the CPU
            rtapp_period = first_task_params[first_task_name]["params"]["period_ms"]
            task_start = boost_task_rtapp.index[0]
            after_first_period = task_start + (rtapp_period / 1000.)
            boost_task_rtapp = boost_task_rtapp.ix[after_first_period:]

            sched_load_scale = 1024
            boost = tc["cgroups"]["conf"]["schedtune"]["/stune"]["boost"] / 100.
            util = boost_task_rtapp["util"]
            expected_margin = (sched_load_scale - util) * boost
            expected_margin = expected_margin.astype(int)
            boost_task_rtapp["expected_margin"] = expected_margin
            ftrace.add_parsed_event("boost_task_rtapp", boost_task_rtapp)

            analyzer = Analyzer(ftrace, {})
            statement = "boost_task_rtapp:margin == boost_task_rtapp:expected_margin"
            error_msg = "task was not boosted to the expected margin: {}".\
                        format(boost)
            self.assertTrue(analyzer.assertStatement(statement), msg=error_msg)

# vim :set tabstop=4 shiftwidth=4 expandtab

@@ -2052,16 +2052,90 @@
 sk_name%5D
+%0A            ftrace.add_parsed_event(%22boost_task_rtapp%22, boost_task_rtapp)
 %0A%0A      
@@ -2457,597 +2457,418 @@
 0.)%0A
-            boost_task_rtapp = boost_task_rtapp.ix%5Bafter_first_period:%5D%0A%0A            sched_load_scale = 1024%0A            boost = tc%5B%22cgroups%22%5D%5B%22conf%22%5D%5B%22schedtune%22%5D%5B%22/stune%22%5D%5B%22boost%22%5D / 100.%0A            util = boost_task_rtapp%5B%22util%22%5D%0A            expected_margin = (sched_load_scale - util) * boost%0A            expected_margin = expected_margin.astype(int)%0A            boost_task_rtapp%5B%22expected_margin%22%5D = expected_margin%0A            ftrace.add_parsed_event(%22boost_task_rtapp%22, boost_task_rtapp)%0A%0A            analyzer = Analyzer(ftrace, %7B%7D)%0A            statement = %22boost_task_rtapp:margin
+%0A            boost = tc%5B%22cgroups%22%5D%5B%22conf%22%5D%5B%22schedtune%22%5D%5B%22/stune%22%5D%5B%22boost%22%5D / 100.%0A            analyzer_const = %7B%0A                %22SCHED_LOAD_SCALE%22: 1024,%0A                %22BOOST%22: boost,%0A            %7D%0A            analyzer = Analyzer(ftrace, analyzer_const,%0A                                window=(after_first_period, None))%0A            statement = %22(((SCHED_LOAD_SCALE - boost_task_rtapp:util) * BOOST) // 100)
  == 
@@ -2888,17 +2888,8 @@
 app:
-expected_
 marg

simplify stune's boosted utilization signal test