GGitee1
587c29e8创建于 2024年7月9日历史提交
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2023 Huawei Device Co., Ltd.
# 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 shutil
import subprocess
import os
import sys
import inspect
import pytest
import json

from mylogger import get_logger, parse_json

sys.path.append(os.path.join(os.getcwd(), "mylogger.py"))
Log = get_logger("build_gn")
log_info = Log.info
log_error = Log.error

config = parse_json().get("gn_template")
if not config:
    log_error("config file: build_example.json error")
    sys.exit(0)

CURRENT_OHOS_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
BUILD_SH_PATH = os.path.join(CURRENT_OHOS_ROOT, 'build.sh')

TEMPLATE_SOURCE_PATH = config.get("template_source_path")
RESULT_BUILT_FILE = config.get("result_build_file")
BUILD_RES_PATH = CURRENT_OHOS_ROOT + RESULT_BUILT_FILE
RESULT_OBJ_FILE = config.get("result_obj_file")
RESULT_PATH = CURRENT_OHOS_ROOT + RESULT_OBJ_FILE
RUST_PATH = config.get("rust_path")
RESULT_RUST_FILE = config.get("result_rust_file")
RUST_RESULT_IDL_PATH = CURRENT_OHOS_ROOT + RESULT_RUST_FILE
EXCLUDE_LIST = config.get("exclude")
TEST_BUILD = config.get("test_build")
CONFIG_PATH = CURRENT_OHOS_ROOT + TEST_BUILD
TIME_OUT = config.get("time_out")


def remove_dir():
    """
    Description: this function is used to delete files in the out folder other than reports
    """
    out_dir = os.path.join(CURRENT_OHOS_ROOT, "out")
    try:
        if not os.path.exists(out_dir):
            return
        for tmp_dir in os.listdir(out_dir):
            if tmp_dir in EXCLUDE_LIST:
                continue
            if os.path.isdir(os.path.join(out_dir, tmp_dir)):
                shutil.rmtree(os.path.join(out_dir, tmp_dir))
            else:
                os.remove(os.path.join(out_dir, tmp_dir))
    except Exception as e:
        log_error(e)


remove_dir()


@pytest.fixture()
def init_build_env():
    def find_top_dir():
        cur_dir = os.getcwd()
        while cur_dir != "/":
            build_scripts = os.path.join(
                cur_dir, 'build/scripts/build_package_list.json')
            if os.path.exists(build_scripts):
                return cur_dir
            cur_dir = os.path.dirname(cur_dir)

    os.chdir(find_top_dir())
    subprocess.run(['repo', 'forall', '-c', 'git reset --hard'],
                   stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    subprocess.run(['repo', 'forall', '-c', 'git clean -dfx'],
                   stdout=subprocess.PIPE, stderr=subprocess.PIPE)


def exec_command_communicate(cmd_path, res_path, res_def_name, rust=None):
    """
    Description : execute the cmd command to return the terminal output value
    @param cmd_path: the source code path for running commands
    @param res_path: the generated product path
    @param res_def_name: function name
    @param rust: judgment flags for running test cases
    @return True or False
    """
    if not rust == "rust":
        write_bundle_json(res_def_name, cmd_path)
    cmd = [BUILD_SH_PATH, '--product-name', 'rk3568', '--build-target', cmd_path]
    try:
        proc = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            encoding="utf-8",
            universal_newlines=True,
            cwd=CURRENT_OHOS_ROOT
        )
        out, error = proc.communicate(timeout=TIME_OUT)
        out_res = out.splitlines() + error.splitlines()
        log_info(f"*******************returncode:{proc.returncode}*********************")
        if proc.returncode == 0:
            for row, data in enumerate(out_res):
                log_info("【{}】:{}".format(row, data))
            if os.path.exists(res_path):
                log_info('*****************test succeed************************')
                return True
            else:
                log_info(f"{res_def_name} is not exist")
                return False
        else:
            for row, data in enumerate(out_res):
                log_error("【{}】:{}".format(row, data))
            return False
    except Exception as e:
        log_error("command execution failed: {}".format(e))
        raise Exception("command execution failed: {}".format(e))


def exec_command_out_put(cmd_path, res_def_name, error_log):
    """
    Description: execute the cmd command to return the terminal output value
    @param cmd_path: the source code path for running commands
    @param res_def_name: function name
    @param error_log: use case judgment flag
    @return True or False
    """

    write_bundle_json(res_def_name, cmd_path)
    cmd = [BUILD_SH_PATH, '--product-name', 'rk3568', '--build-target', cmd_path]
    try:
        proc = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            encoding="utf-8",
            universal_newlines=True,
            cwd=CURRENT_OHOS_ROOT
        )
        out, error = proc.communicate(timeout=TIME_OUT)
        out_res = out.splitlines() + error.splitlines()
        log_info(f"*******************returncode:{proc.returncode}*********************")
        if proc.returncode != 0:
            for row, data in enumerate(out_res):
                log_info("【{}】:{}".format(row, data))
            if error_log in out_res:
                log_info('*****************test succeed************************')
                return True
            else:
                log_info(f"{res_def_name} failed")
                return False
        else:
            for row, data in enumerate(out_res):
                log_error("【{}】:{}".format(row, data))
            return False
    except Exception as e:
        log_error("command execution failed: {}".format(e))
        raise Exception("command execution failed: {}".format(e))


def exec_command_install_dir(cmd_path, res_def_name):
    """
    Description: execute the cmd command to return the terminal output value
    @param cmd_path: the source code path for running commands
    @param res_def_name: function name
    @return True or False
    """
    write_bundle_json(res_def_name, cmd_path)
    cmd = [BUILD_SH_PATH, '--product-name', 'rk3568', '--build-target', cmd_path]
    try:
        proc = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            encoding="utf-8",
            universal_newlines=True,
            cwd=CURRENT_OHOS_ROOT
        )
        out, error = proc.communicate(timeout=TIME_OUT)
        out_res = out.splitlines() + error.splitlines()
        log_info(f"*******************returncode:{proc.returncode}*********************")
        if proc.returncode == 0:
            for row, data in enumerate(out_res):
                log_info("【{}】:{}".format(row, data))
            config_path = RESULT_PATH + res_def_name + "/{}_module_info.json".format(res_def_name)
            with open(config_path, "r", encoding="utf-8") as json_file:
                data = json.load(json_file)
                res = str((data.get("dest"))[0])
                module_install_dir = res_def_name
            if module_install_dir in res:
                log_info('*****************test succeed************************')
                return True
            else:
                log_info(f"{res_def_name} is not exist")
                return False
        else:
            for row, data in enumerate(out_res):
                log_error("【{}】:{}".format(row, data))
            return False
    except Exception as e:
        log_error("command execution failed: {}".format(e))
        raise Exception("command execution failed: {}".format(e))


def write_bundle_json(res_def_name, cmd_path):
    """
    Description: write bundle.json
    @param res_def_name: function name
    @param cmd_path: the source code path for running commands
    """
    with open(CONFIG_PATH, "r", encoding="utf-8") as json_file:
        data = json.load(json_file)
        res = data.get("component").get("build").get("sub_component")
        res.append("//{}:{}".format(cmd_path, res_def_name))
        data["component"]["build"]["sub_component"] = res
    config_res = os.path.join(CURRENT_OHOS_ROOT, "build/common/bundle.json")
    with open(config_res, "w", encoding="utf-8") as json_file:
        json.dump(data, json_file, indent=4, ensure_ascii=False)


class TestModuleBuild:

    def test_ohos_shared_library_output_dir(self):
        """
        test output dir
        """
        res_def_name = inspect.currentframe().f_code.co_name
        error_log = "[OHOS INFO] output_dir is not allowed to be defined."
        cmd_path = TEMPLATE_SOURCE_PATH + res_def_name
        result = exec_command_out_put(cmd_path, res_def_name, error_log)
        assert result, "build test_ohos_shared_library_output_dir failed"

    def test_ohos_shared_library_testonly(self):
        """
        test testonly
        """
        error_log = "[OHOS INFO] ERROR at //build/ohos/ohos_part.gni:54:3: Test-only dependency not allowed."
        res_def_name = inspect.currentframe().f_code.co_name
        cmd_path = TEMPLATE_SOURCE_PATH + res_def_name
        result = exec_command_out_put(cmd_path, res_def_name, error_log)
        assert result, "build test_ohos_shared_library_testonly failed"

    def test_ohos_shared_library(self):
        """
        test shared library
        """
        res_def_name = inspect.currentframe().f_code.co_name
        cmd_path = TEMPLATE_SOURCE_PATH + res_def_name
        res_path = os.path.join(BUILD_RES_PATH, "libtest_ohos_shared_library.z.so")
        result = exec_command_communicate(cmd_path, res_path, res_def_name)
        assert result, "build test_ohos_shared_library failed"

    def test_ohos_shared_library_output_name(self):
        """
        test output name
        """
        res_def_name = inspect.currentframe().f_code.co_name
        cmd_path = TEMPLATE_SOURCE_PATH + res_def_name
        res_path = BUILD_RES_PATH + "lib{}.{}".format(res_def_name, res_def_name)
        result = exec_command_communicate(cmd_path, res_path, res_def_name)
        assert result, " ohos_shared_library  template output_name and output_extension invalid"

    def test_ohos_shared_library_output_extension(self):
        """
        test extension
        """
        res_def_name = "test_ohos_shared_library_output_name"
        cmd_path = TEMPLATE_SOURCE_PATH + res_def_name
        res_path = BUILD_RES_PATH + "lib{}.{}".format(res_def_name, res_def_name)
        result = exec_command_communicate(cmd_path, res_path, res_def_name)
        assert result, " ohos_shared_library  template output_name and output_extension invalid"

    def test_ohos_shared_library_module_install_dir(self):
        """
        test module install dir
        """
        res_def_name = inspect.currentframe().f_code.co_name
        cmd_path = TEMPLATE_SOURCE_PATH + res_def_name
        result = exec_command_install_dir(cmd_path, res_def_name)
        assert result, " test_ohos_shared_library_module_install_dir fail"

    def test_ohos_shared_library_relative_install_dir(self):
        """
        test relative install dir
        """
        res_def_name = inspect.currentframe().f_code.co_name
        cmd_path = TEMPLATE_SOURCE_PATH + res_def_name
        result = exec_command_install_dir(cmd_path, res_def_name)
        assert result, " test_ohos_shared_library_relative_install_dir fail"

    def test_ohos_static_library(self):
        """
        test static library
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = TEMPLATE_SOURCE_PATH + function_name
        res_path = os.path.join(RESULT_PATH, "src", function_name, "hello.o")
        result = exec_command_communicate(cmd_path, res_path, function_name)
        assert result, "build test_ohos_static_library failed"

    def test_ohos_source_set(self):
        """
        test source set
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = TEMPLATE_SOURCE_PATH + function_name
        res_path = os.path.join(RESULT_PATH, "src", function_name, "adder.o")
        result = exec_command_communicate(cmd_path, res_path, function_name)
        assert result, "build test_ohos_source_set failed"

    def test_ohos_executable(self):
        """
        test ohos executable
        """
        function_name = inspect.currentframe().f_code.co_name
        common_res_def = TEMPLATE_SOURCE_PATH + function_name
        res_path = BUILD_RES_PATH + function_name
        result = exec_command_communicate(common_res_def, res_path, function_name)
        assert result, "build test_ohos_executable failed"


class TestPrecompiledBuild:

    def test_ohos_prebuilt_executable(self):
        """
        test prebuilt executable
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_common = TEMPLATE_SOURCE_PATH + function_name
        res_path = os.path.join(RESULT_PATH, function_name, "test_ohos_prebuilt_executable.stamp")
        result = exec_command_communicate(cmd_common, res_path, function_name)
        assert result, "build test_ohos_prebuilt_executable failed"

    def test_ohos_prebuilt_shared_library(self):
        """
        test _prebuilt shared library
        """
        function_name = inspect.currentframe().f_code.co_name
        common_res_def = TEMPLATE_SOURCE_PATH + function_name
        res_path = os.path.join(RESULT_PATH, function_name, "test_ohos_prebuilt_shared_library.stamp")
        result = exec_command_communicate(common_res_def, res_path, function_name)
        assert result, "build test_ohos_prebuilt_shared_library failed"

    def test_ohos_prebuilt_static_library(self):
        """
        test prebuilt static library
        """
        function_name = inspect.currentframe().f_code.co_name
        common_res_def = TEMPLATE_SOURCE_PATH + function_name
        res_path = os.path.join(RESULT_PATH, function_name, "test_ohos_prebuilt_static_library.stamp")
        result = exec_command_communicate(common_res_def, res_path, function_name)
        assert result, "build test_ohos_prebuilt_static_library failed"


class TestOtherPrebuilt:

    def test_ohos_sa_profile(self):
        """
        test ohos_sa_profile
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = TEMPLATE_SOURCE_PATH + function_name
        profile_result_path = RESULT_PATH + function_name
        result = exec_command_communicate(cmd_path, profile_result_path, function_name)
        assert result, "build test_ohos_sa_profile failed"

    def test_ohos_prebuilt_etc(self):
        """
        test ohos_prebuilt_etc
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = TEMPLATE_SOURCE_PATH + function_name
        rebuilt_result_path = RESULT_PATH + function_name
        result = exec_command_communicate(cmd_path, rebuilt_result_path, function_name)
        assert result, "build test_ohos_prebuilt_etc failed"


class TestRustBuild:

    def test_bin_cargo_crate(self):
        """
        test bin_cargo_crate
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name
        res_path = os.path.join(BUILD_RES_PATH, function_name)
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_bin_cargo_crate failed"

    def test_bin_crate(self):
        """
        test bin_crate
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name
        res_path = os.path.join(BUILD_RES_PATH, function_name)
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_bin_crate failed"

    def test_extern_c(self):
        """
        test extern_c
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + "test_bindgen_test/test_for_extern_c:test_extern_c"
        res_path = os.path.join(BUILD_RES_PATH, function_name)
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_extern_c failed"

    def test_for_h(self):
        """
        test for_h
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + "test_bindgen_test/test_for_h:bindgen_test_for_h"
        res_path = os.path.join(BUILD_RES_PATH, 'bindgen_test_for_h')
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build bindgen_test_for_h failed"

    def test_for_hello_world(self):
        """
        test for_hello_world
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + "test_bindgen_test/test_for_hello_world:bindgen_test"
        res_path = os.path.join(BUILD_RES_PATH, 'bindgen_test')
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_for_hello_world failed"

    def test_for_hpp(self):
        """
        test for_hpp
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + "test_bindgen_test/test_for_hpp:bindgen_test_hpp"
        res_path = os.path.join(BUILD_RES_PATH, 'bindgen_test_hpp')
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build bindgen_test_hpp failed"

    def test_cdylib_crate(self):
        """
        test cdylib_crate
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name
        res_path = os.path.join(BUILD_RES_PATH, function_name)
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_cdylib_crate failed"

    def test_cxx_exe(self):
        """
        test cxx_exe
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + "test_cxx" + ":" + function_name
        res_path = os.path.join(BUILD_RES_PATH, function_name)
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_cxx_exe failed"

    def test_cxx_rust(self):
        """
        test cxx_rust
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name
        res_path = os.path.join(BUILD_RES_PATH, function_name)
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')

        assert result, "build test_cxx_rust failed"

    def test_dylib_crate(self):
        """
        test dylib_crate
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name
        res_path = os.path.join(BUILD_RES_PATH, function_name)
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_cxx_rust failed"

    def test_idl(self):
        """
        test test_idl
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + "test_idl"
        res_path = os.path.join(RUST_RESULT_IDL_PATH, function_name, 'test_idl.stamp')
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_idl failed"

    def test_rlib_cargo_crate(self):
        """
        test rlib_cargo_crate
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name + ':' + 'test_rlib_crate_associated_bin'
        res_path = os.path.join(BUILD_RES_PATH, 'test_rlib_crate_associated_bin')
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_rlib_cargo_crate failed"

    def test_rlib_crate(self):
        """
        test rlib_crate
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name
        res_path = os.path.join(BUILD_RES_PATH, function_name)
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_rlib_crate failed"

    def test_rust_st(self):
        """
        test rust_st
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name
        res_path = os.path.join(BUILD_RES_PATH, 'libtest_rust_st_add.dylib.so')
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_rust_st failed"

    def test_rust_ut(self):
        """
        test rust_ut
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name
        res_path = os.path.join(BUILD_RES_PATH, 'libtest_rust_ut_add.dylib.so')
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_rust_ut failed"

    def test_static_link(self):
        """
        test static_link
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name
        res_path = os.path.join(BUILD_RES_PATH, function_name)
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_static_link failed"

    def test_staticlib_crate(self):
        """
        test staticlib_crate
        """
        function_name = inspect.currentframe().f_code.co_name
        cmd_path = RUST_PATH + function_name
        res_path = os.path.join(BUILD_RES_PATH, function_name)
        result = exec_command_communicate(cmd_path, res_path, function_name, rust='rust')
        assert result, "build test_staticlib_crate failed"


def write_initial_bundle_json():
    """
    Description: write initial bundle.json
    """
    with open(CONFIG_PATH, "r", encoding="utf-8") as json_file:
        data = json.load(json_file)
    config_res = os.path.join(CURRENT_OHOS_ROOT, "build/common/bundle.json")
    
    with open(config_res, "w", encoding="utf-8") as json_file:
        json.dump(data, json_file, indent=4, ensure_ascii=False)


write_initial_bundle_json()