Esempio n. 1
0
 def run_cov_with_arg(self, args):
     MANAGER = cov_manager.CovManager()
     with MANAGER.temp_manager():
         c = cov_config.ConfigNamespace()
         cov_mod.parse_args(args, namespace=c)
         inference_extension.enable()
         klara.initialize(c)
         c.output_file = self.result
         cov_mod.run(c)
         return self.result.getvalue()
Esempio n. 2
0
import pytest

import os
import pathlib
import sys
import tempfile
import unittest
from textwrap import dedent

from klara.contract.__main__ import run
from klara.contract.config import ContractConfig
from klara.klara_z3 import cov_manager, inference_extension

from ..helper import base_test

MANAGER = cov_manager.CovManager()


class KlaraBaseTest(base_test.BaseTest):
    _TEST_MODULE_NAME = "contract_test"
    unique_id = 0

    @classmethod
    def setUpClass(cls) -> None:
        config = ContractConfig()
        MANAGER.initialize(config)
        inference_extension.enable()

    def setUp(self) -> None:
        super(KlaraBaseTest, self).setUp()
        self.cwd = os.getcwd()
Esempio n. 3
0
class BaseCovTest(BaseTestPatchCondResult):
    sample_data_xml = None
    cwd = os.getcwd()
    cov_manager = cov_manager.CovManager()

    def tearDown(self):
        prm_data.clear()

    @classmethod
    def setUpClass(cls):
        super(BaseCovTest, cls).setUpClass()

    @classmethod
    def tearDownClass(cls) -> None:
        super(BaseCovTest, cls).tearDownClass()

    def init_solver(self, **kwargs):
        prm_data.append(ET.parse(self.sample_data_xml.open()))
        config = self.setup_cov_config(py_version=3,
                                       analyze_procedure=True,
                                       entry_class="MyClass",
                                       entry_func="Top",
                                       enable_infer_sequence=True,
                                       overwrite=True,
                                       **kwargs)
        inference_extension.enable()
        return config

    def run_solver_with_cov(self,
                            ast_str,
                            max_iterations,
                            expected_coverage=100,
                            expected_return=None,
                            **kwargs):
        config = self.init_solver(**kwargs)
        MANAGER.config = config
        MANAGER.register_transform(nodes.FunctionDef, transform_init,
                                   lambda x: x.name == "init")
        MANAGER.register_transform(nodes.Subscript, _infer_end_subscript,
                                   is_cfg)
        result = cov_solve(ast_str, cov_config=config)
        self.assertLessEqual(len(result), max_iterations)
        _, filename = tempfile.mkstemp(prefix="test_sample", suffix=".py")
        with open(filename, "w") as file:
            file.write(ast_str)
        spec = importlib.util.spec_from_file_location("test_sample",
                                                      str(filename))
        module = importlib.util.module_from_spec(spec)
        sys.modules["test_sample"] = module
        coverage_instance = coverage.Coverage(include="*test_sample*")
        coverage_instance.start()
        spec.loader.exec_module(module)
        expected_return = expected_return or list()
        expected_return = list(expected_return)
        for r in result:
            c = module.MyClass()
            c.cfg = DictWrapper(r)
            c.init()
            val = c.Top()
            if val in expected_return:
                expected_return.remove(val)
        assert len(
            expected_return) == 0, "values: {} has not been return".format(
                expected_return)
        coverage_instance.stop()
        coverage_percentage = coverage_instance.report()
        if coverage_percentage < expected_coverage:
            parent_function = inspect.getframeinfo(
                inspect.currentframe().f_back).function
            output_dir = str(self.cwd / ("test_" + str(parent_function)))
            if os.path.exists(output_dir):
                shutil.rmtree(output_dir)
            os.makedirs(output_dir)
            with open(os.path.join(output_dir, "dump_result.json"),
                      "w") as json_file:
                json.dump(result, json_file, indent=4)
            coverage_instance.html_report(directory=output_dir)
            self.fail(
                "Coverage: {}%, does not match the expected coverage: {}%."
                "\nPlease check directory: {} for coverage information".format(
                    coverage_percentage, expected_coverage, output_dir))
        del sys.modules["test_sample"]
        del module
        os.remove(filename)

    def run_and_assert_line_fix(self,
                                ast_str,
                                linenos,
                                func,
                                minimal_len=None,
                                **kwargs):
        config = self.init_solver(**kwargs, cover_lines=linenos)
        MANAGER.register_transform(nodes.FunctionDef, transform_init,
                                   lambda x: x.name == "init")
        MANAGER.register_transform(nodes.Subscript, _infer_end_subscript,
                                   is_cfg)
        result = line_fix_solve(ast_str, config)
        minimal_len = len(linenos) if minimal_len is None else minimal_len
        assert len(linenos) >= len(result) >= minimal_len
        for res in result:
            assert func(res)
        return result

    def run_fix_all_and_assert_line_fix(self, ast_str, func, **kwargs):
        config = self.init_solver(**kwargs, cover_all=True)
        MANAGER.register_transform(nodes.FunctionDef, transform_init,
                                   lambda x: x.name == "init")
        MANAGER.register_transform(nodes.Subscript, _infer_end_subscript,
                                   is_cfg)
        result = line_fix_solve(ast_str, config)
        assert result
        for res in result:
            assert func(res)
        return result

    def run_cover_return(self,
                         ast_str,
                         max_iterations,
                         func,
                         lt_flag=False,
                         **kwargs):
        config = self.init_solver(**kwargs)
        MANAGER.register_transform(nodes.FunctionDef, transform_init,
                                   lambda x: x.name == "init")
        MANAGER.register_transform(nodes.Subscript, _infer_end_subscript,
                                   is_cfg)
        result = cov_solve(ast_str, cov_config=config)
        if lt_flag:
            assert len(result) <= max_iterations
        else:
            assert len(result) == max_iterations
        for res in result:
            assert func(res)

    def run_result_return(self, ast_str, **kwargs):
        config = self.init_solver(**kwargs)
        MANAGER.register_transform(nodes.FunctionDef, transform_init,
                                   lambda x: x.name == "init")
        MANAGER.register_transform(nodes.Subscript, _infer_end_subscript,
                                   is_cfg)
        with utilities.temp_config(MANAGER, config):
            as_tree = self.cov_manager.build_tree(ast_str)
            c = self.cov_manager.build_cfg(as_tree)
            df = solver.DepFinder(c, as_tree)
            df.solve_classdef()
            for cls in df.classes:
                top_level = cls.get_latest_stmt(df.entry_func)
                yield from top_level.infer_return_value(df.context)
Esempio n. 4
0
def initialize(config: Config = None, smt_disable: bool = False) -> None:
    """initialize klara to a different configuration
    :param config: a config object of type Klara.Config to fine tune configuration
    :param smt_disable: disable z3 solver support
    :return: None
    """
    if smt_disable:
        manager = _core_manager.AstManager()
        manager.initialize(config or Config())
        _infer_extension.disable()
    else:
        MANAGER.initialize(config or Config())
        _infer_extension.enable()


MANAGER = _manager.CovManager()
"""A Central manager responsible to cache result, and various common operation across module"""

initialize()


def parse(source: str, py2: bool = False) -> Module:
    """parse python code as ast, apply analysis transformation and return modified tree
    :param source: python source file as string
    :param py2: True if `source` is python 2, False if it's in python 3
    :return: a modified abstract syntax tree with inference support
    """
    MANAGER.config.py_version = 2 if py2 else 3
    tree = MANAGER.build_tree(source)
    MANAGER.build_cfg(tree)
    return tree