2024-08-26 14:55:36 -04:00
|
|
|
#!/usr/bin/env python3
|
2026-03-11 23:15:07 -04:00
|
|
|
# © 2021-2026 TechnoLibre (http://www.technolibre.ca)
|
2024-08-26 14:55:36 -04:00
|
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
2022-01-24 14:00:47 -05:00
|
|
|
import argparse
|
|
|
|
|
import asyncio
|
2022-02-03 22:44:08 -05:00
|
|
|
import configparser
|
2022-01-24 14:00:47 -05:00
|
|
|
import datetime
|
2025-04-13 12:58:46 -04:00
|
|
|
import json
|
2022-01-24 14:00:47 -05:00
|
|
|
import logging
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
2022-02-03 22:44:08 -05:00
|
|
|
import tempfile
|
2022-01-24 14:00:47 -05:00
|
|
|
import time
|
|
|
|
|
import uuid
|
2024-01-23 22:04:15 -05:00
|
|
|
from collections import defaultdict
|
2025-04-13 12:58:46 -04:00
|
|
|
from typing import Tuple
|
2022-01-24 14:00:47 -05:00
|
|
|
|
2022-02-03 22:44:08 -05:00
|
|
|
import aioshutil
|
2023-01-02 22:07:49 -05:00
|
|
|
import git
|
2024-02-23 13:01:10 -05:00
|
|
|
from colorama import Fore, Style
|
2022-01-24 14:00:47 -05:00
|
|
|
|
2023-02-18 23:20:42 -05:00
|
|
|
new_path = os.path.normpath(
|
|
|
|
|
os.path.join(os.path.dirname(__file__), "..", "..")
|
|
|
|
|
)
|
|
|
|
|
sys.path.append(new_path)
|
|
|
|
|
|
|
|
|
|
from script import lib_asyncio
|
|
|
|
|
|
2022-01-24 14:00:47 -05:00
|
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
2025-04-23 04:38:45 -04:00
|
|
|
FILENAME_ODOO_VERSION = ".odoo-version"
|
|
|
|
|
if not os.path.isfile(FILENAME_ODOO_VERSION):
|
|
|
|
|
_logger.error(f"Missing file {FILENAME_ODOO_VERSION}")
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
2025-08-07 06:28:34 -04:00
|
|
|
with open(FILENAME_ODOO_VERSION, "r") as f:
|
2025-04-23 04:38:45 -04:00
|
|
|
ODOO_VERSION = f.readline()
|
|
|
|
|
|
2025-05-05 04:43:13 -04:00
|
|
|
LOG_FILE = "./.venv.erplibre/make_test.log"
|
2025-04-23 04:38:45 -04:00
|
|
|
CONFIG_TESTCASE_JSON = f"./script/test/config_testcase.odoo{ODOO_VERSION}.json"
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_config():
|
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
|
|
|
description="""\
|
2022-02-03 22:44:08 -05:00
|
|
|
Run code generator test in parallel (asyncio).
|
2022-01-24 14:00:47 -05:00
|
|
|
""",
|
|
|
|
|
epilog="""\
|
|
|
|
|
""",
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--ignore_init_check_git",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Will not stop or init check if contain git change.",
|
|
|
|
|
)
|
2022-02-03 22:44:08 -05:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--no_parallel",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Will run in serial.",
|
|
|
|
|
)
|
2022-04-23 00:27:38 -04:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--coverage",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Execute coverage file.",
|
|
|
|
|
)
|
2022-02-03 22:44:08 -05:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--keep_cache",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help=(
|
|
|
|
|
"Will not delete the temporary directory, check in print and log."
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"-p",
|
|
|
|
|
"--max_process",
|
|
|
|
|
type=int,
|
|
|
|
|
default=0,
|
|
|
|
|
help="Max processor to use. If 0, use max.",
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--debug",
|
|
|
|
|
action="store_true",
|
|
|
|
|
help="Enable asyncio debugging",
|
|
|
|
|
)
|
2024-01-23 22:04:15 -05:00
|
|
|
parser.add_argument(
|
|
|
|
|
"--json_model",
|
|
|
|
|
help="Model of data to run test in json",
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
"--output_result_dir",
|
|
|
|
|
help=(
|
|
|
|
|
"A path of existing directory, will export a file per test with"
|
|
|
|
|
" status/result and log."
|
|
|
|
|
),
|
|
|
|
|
)
|
2022-01-24 14:00:47 -05:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
return args
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lst_ignore_warning = [
|
|
|
|
|
"have the same label:",
|
|
|
|
|
"odoo.addons.code_generator.extractor_module_file: Ignore next error about"
|
|
|
|
|
" ALTER TABLE DROP CONSTRAINT.",
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
lst_ignore_error = [
|
|
|
|
|
"fetchmail_notify_error_to_sender",
|
|
|
|
|
'odoo.sql_db: bad query: ALTER TABLE "db_backup" DROP CONSTRAINT'
|
|
|
|
|
' "db_backup_db_backup_name_unique"',
|
|
|
|
|
'ERROR: constraint "db_backup_db_backup_name_unique" of relation'
|
|
|
|
|
' "db_backup" does not exist',
|
|
|
|
|
'odoo.sql_db: bad query: ALTER TABLE "db_backup" DROP CONSTRAINT'
|
|
|
|
|
' "db_backup_db_backup_days_to_keep_positive"',
|
|
|
|
|
'ERROR: constraint "db_backup_db_backup_days_to_keep_positive" of relation'
|
|
|
|
|
' "db_backup" does not exist',
|
|
|
|
|
"odoo.addons.code_generator.extractor_module_file: Ignore next error about"
|
|
|
|
|
" ALTER TABLE DROP CONSTRAINT.",
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extract_result(result, test_name, lst_error, lst_warning):
|
|
|
|
|
lst_log = result[0].split("\n")
|
|
|
|
|
for log_line in lst_log:
|
|
|
|
|
is_ignore_error = False
|
|
|
|
|
if "error" in log_line.lower():
|
|
|
|
|
# Remove ignore error
|
|
|
|
|
for ignore_error in lst_ignore_error:
|
|
|
|
|
if ignore_error in log_line:
|
|
|
|
|
is_ignore_error = True
|
|
|
|
|
break
|
|
|
|
|
if not is_ignore_error:
|
|
|
|
|
lst_error.append(log_line)
|
|
|
|
|
|
|
|
|
|
is_ignore_warning = False
|
|
|
|
|
if "warning" in log_line.lower():
|
|
|
|
|
# Remove ignore warning
|
|
|
|
|
for ignore_warning in lst_ignore_warning:
|
|
|
|
|
if ignore_warning in log_line:
|
|
|
|
|
is_ignore_warning = True
|
|
|
|
|
break
|
|
|
|
|
if not is_ignore_warning:
|
|
|
|
|
lst_warning.append(log_line)
|
|
|
|
|
if result[1]:
|
2025-04-23 04:38:45 -04:00
|
|
|
if len(result[0].split("\n")) == 1:
|
|
|
|
|
lst_error.append(
|
|
|
|
|
f"Return status error for test {test_name} : {result[0]}"
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
lst_error.append(f"Return status error for test {test_name}")
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_result(task_list, tpl_result):
|
2023-02-14 16:47:04 -05:00
|
|
|
status = True
|
2022-01-24 14:00:47 -05:00
|
|
|
lst_error = []
|
|
|
|
|
lst_warning = []
|
|
|
|
|
|
|
|
|
|
for i, result in enumerate(tpl_result):
|
|
|
|
|
extract_result(
|
|
|
|
|
result, task_list[i].cr_code.co_name, lst_error, lst_warning
|
|
|
|
|
)
|
|
|
|
|
|
2023-02-14 16:47:04 -05:00
|
|
|
if lst_error:
|
|
|
|
|
status = False
|
|
|
|
|
|
2022-01-24 14:00:47 -05:00
|
|
|
if lst_warning:
|
2024-02-23 13:01:10 -05:00
|
|
|
print(f"{Fore.YELLOW}{len(lst_warning)} WARNING{Style.RESET_ALL}")
|
2022-01-24 14:00:47 -05:00
|
|
|
i = 0
|
|
|
|
|
for warning in lst_warning:
|
|
|
|
|
i += 1
|
|
|
|
|
print(f"[{i}]{warning}")
|
|
|
|
|
|
|
|
|
|
if lst_error:
|
2024-02-23 13:01:10 -05:00
|
|
|
print(f"{Fore.RED}{len(lst_error)} ERROR{Style.RESET_ALL}")
|
2022-01-24 14:00:47 -05:00
|
|
|
i = 0
|
|
|
|
|
for error in lst_error:
|
|
|
|
|
i += 1
|
|
|
|
|
print(f"[{i}]{error}")
|
|
|
|
|
|
|
|
|
|
if lst_error or lst_warning:
|
|
|
|
|
str_result = (
|
2024-02-23 13:01:10 -05:00
|
|
|
f"{Fore.RED}{len(lst_error)} ERROR{Style.RESET_ALL}"
|
|
|
|
|
f" {Fore.YELLOW}{len(lst_warning)} WARNING{Style.RESET_ALL}"
|
2022-01-24 14:00:47 -05:00
|
|
|
)
|
|
|
|
|
else:
|
2024-02-23 13:01:10 -05:00
|
|
|
str_result = f"{Fore.GREEN}SUCCESS{Style.RESET_ALL} 🍰"
|
2022-01-24 14:00:47 -05:00
|
|
|
|
2024-02-23 13:01:10 -05:00
|
|
|
print(f"{Fore.BLUE}Summary TEST {str_result}{Style.RESET_ALL}")
|
2023-02-14 16:47:04 -05:00
|
|
|
return status
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def print_log(lst_task, tpl_result):
|
|
|
|
|
if len(lst_task) != len(tpl_result):
|
|
|
|
|
_logger.error("Different length for log... What happen?")
|
|
|
|
|
return
|
|
|
|
|
with open(LOG_FILE, "w") as f:
|
|
|
|
|
for i, task in enumerate(lst_task):
|
|
|
|
|
result = tpl_result[i]
|
2024-02-23 13:01:10 -05:00
|
|
|
status_str = (
|
|
|
|
|
f"{Fore.GREEN}PASS{Style.RESET_ALL}"
|
|
|
|
|
if not result[1]
|
|
|
|
|
else f"{Fore.RED}FAIL{Style.RESET_ALL}"
|
|
|
|
|
)
|
2022-01-24 14:00:47 -05:00
|
|
|
f.write(
|
|
|
|
|
f"\nTest execution {i + 1} - {status_str} -"
|
|
|
|
|
f" {task.cr_code.co_name}\n\n"
|
|
|
|
|
)
|
|
|
|
|
if result[0]:
|
|
|
|
|
f.write(result[0])
|
|
|
|
|
f.write("\n")
|
|
|
|
|
|
|
|
|
|
|
2024-01-23 22:04:15 -05:00
|
|
|
def print_log_output_into_dir(tpl_result, output_dir):
|
|
|
|
|
date_now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
|
for i, result in enumerate(tpl_result):
|
|
|
|
|
log = result[0]
|
|
|
|
|
status = result[1]
|
|
|
|
|
test_name = result[2]
|
|
|
|
|
test_name_file_name = test_name.replace(" ", "")
|
|
|
|
|
time_execution = result[3]
|
|
|
|
|
log_file = os.path.join(output_dir, test_name_file_name)
|
|
|
|
|
with open(log_file, "w") as f:
|
|
|
|
|
f.write(f"{status}\n")
|
|
|
|
|
f.write(f"{test_name}\n")
|
|
|
|
|
f.write(f"{time_execution}\n")
|
|
|
|
|
f.write(f"{date_now}\n")
|
2024-02-23 13:01:10 -05:00
|
|
|
status_str = (
|
|
|
|
|
f"{Fore.GREEN}PASS{Style.RESET_ALL}"
|
|
|
|
|
if not status
|
|
|
|
|
else f"{Fore.RED}FAIL{Style.RESET_ALL}"
|
|
|
|
|
)
|
2024-01-23 22:04:15 -05:00
|
|
|
f.write(
|
|
|
|
|
f"\nTest execution {i + 1} - {status_str} - {test_name}\n\n"
|
|
|
|
|
)
|
|
|
|
|
if log:
|
|
|
|
|
f.write(log)
|
|
|
|
|
f.write("\n")
|
|
|
|
|
|
|
|
|
|
|
2022-01-24 14:00:47 -05:00
|
|
|
async def run_command(*args, test_name=None):
|
|
|
|
|
# Create subprocess
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
cmd_str = " ".join(args)
|
|
|
|
|
process = await asyncio.create_subprocess_exec(
|
|
|
|
|
*args,
|
|
|
|
|
# stdout must a pipe to be accessible as process.stdout
|
|
|
|
|
stdout=asyncio.subprocess.PIPE,
|
|
|
|
|
stderr=asyncio.subprocess.PIPE,
|
|
|
|
|
)
|
|
|
|
|
# Wait for the subprocess to finish
|
|
|
|
|
stdout, stderr = await process.communicate()
|
|
|
|
|
end_time = time.time()
|
|
|
|
|
diff_sec = end_time - start_time
|
|
|
|
|
# Return stdout + stderr, returncode
|
|
|
|
|
str_out = "\n" + stdout.decode().strip() + "\n" if stdout else ""
|
|
|
|
|
str_err = "\n" + stderr.decode().strip() + "\n" if stderr else ""
|
2024-02-23 13:01:10 -05:00
|
|
|
status_str = (
|
|
|
|
|
f"{Fore.RED}FAIL{Style.RESET_ALL}"
|
|
|
|
|
if process.returncode
|
|
|
|
|
else f"{Fore.GREEN}PASS{Style.RESET_ALL}"
|
|
|
|
|
)
|
2022-01-24 14:00:47 -05:00
|
|
|
if test_name:
|
|
|
|
|
str_output_init = (
|
|
|
|
|
f"\n\n{status_str} [{test_name}] [{diff_sec:.3f}s] Execute"
|
|
|
|
|
f' "{cmd_str}"\n\n'
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
str_output_init = (
|
|
|
|
|
f'\n\n{status_str} [{diff_sec:.3f}s] Execute "{cmd_str}"\n\n'
|
|
|
|
|
)
|
|
|
|
|
all_output = str_out + str_err
|
|
|
|
|
print(str_output_init)
|
|
|
|
|
if process.returncode:
|
|
|
|
|
lst_error = []
|
|
|
|
|
lst_warning = []
|
|
|
|
|
extract_result(
|
|
|
|
|
(all_output, process.returncode), test_name, lst_error, lst_warning
|
|
|
|
|
)
|
|
|
|
|
for error in lst_error:
|
|
|
|
|
print(f"\t{error}")
|
|
|
|
|
for warning in lst_warning:
|
|
|
|
|
print(f"\t{warning}")
|
|
|
|
|
return str_output_init + all_output, process.returncode
|
|
|
|
|
|
|
|
|
|
|
2022-02-03 22:44:08 -05:00
|
|
|
def update_config(
|
|
|
|
|
origin_config,
|
|
|
|
|
new_path_config,
|
|
|
|
|
lst_path_to_add_config=None,
|
|
|
|
|
lst_path_to_remove_config=None,
|
|
|
|
|
module_name=None,
|
|
|
|
|
):
|
|
|
|
|
config_parser = configparser.ConfigParser()
|
|
|
|
|
config_parser.read(origin_config)
|
|
|
|
|
str_path = config_parser["options"]["addons_path"].strip(",")
|
|
|
|
|
lst_path = str_path.split(",")
|
|
|
|
|
|
|
|
|
|
# Clean path from test
|
|
|
|
|
if lst_path_to_remove_config:
|
|
|
|
|
for remove_key in lst_path_to_remove_config:
|
|
|
|
|
if remove_key.startswith("./"):
|
|
|
|
|
remove_key = remove_key[2:]
|
|
|
|
|
if module_name and remove_key.endswith(module_name):
|
|
|
|
|
remove_key = remove_key[: -(len(module_name) + 1)]
|
|
|
|
|
for s_path in lst_path:
|
|
|
|
|
if s_path.endswith(remove_key):
|
|
|
|
|
lst_path.remove(s_path)
|
|
|
|
|
break
|
|
|
|
|
if lst_path_to_add_config:
|
|
|
|
|
for add_path in lst_path_to_add_config:
|
|
|
|
|
if module_name and add_path.endswith(module_name):
|
|
|
|
|
add_path = add_path[: -(len(module_name) + 1)]
|
|
|
|
|
lst_path.insert(0, add_path)
|
|
|
|
|
s_new_path = ",".join(lst_path)
|
|
|
|
|
config_parser["options"]["addons_path"] = s_new_path
|
|
|
|
|
with open(new_path_config, "w") as configfile:
|
|
|
|
|
config_parser.write(configfile)
|
|
|
|
|
|
|
|
|
|
|
2022-01-24 14:00:47 -05:00
|
|
|
async def test_exec(
|
|
|
|
|
path_module_check: str,
|
|
|
|
|
generated_module=None,
|
2022-02-03 22:44:08 -05:00
|
|
|
generate_path=None,
|
2022-01-24 14:00:47 -05:00
|
|
|
tested_module=None,
|
|
|
|
|
search_class_module=None,
|
|
|
|
|
script_after_init_check=None,
|
|
|
|
|
lst_init_module_name=None,
|
2024-01-23 22:04:15 -05:00
|
|
|
file_to_restore=None,
|
|
|
|
|
file_to_restore_origin=False,
|
2022-01-24 14:00:47 -05:00
|
|
|
test_name=None,
|
|
|
|
|
install_path=None,
|
2024-01-23 22:04:15 -05:00
|
|
|
run_in_sandbox=True,
|
2025-04-23 03:19:10 -04:00
|
|
|
restore_db_image_name="odoo12.0_base",
|
2024-01-22 20:17:55 -05:00
|
|
|
keep_cache=False,
|
|
|
|
|
coverage=False,
|
2024-01-23 22:04:15 -05:00
|
|
|
) -> Tuple[str, int, str, float]:
|
|
|
|
|
time_init = datetime.datetime.now()
|
2022-01-24 14:00:47 -05:00
|
|
|
test_result = ""
|
|
|
|
|
test_status = 0
|
2024-01-23 22:04:15 -05:00
|
|
|
origin_path_module_check = path_module_check
|
2022-02-03 22:44:08 -05:00
|
|
|
if search_class_module:
|
|
|
|
|
if install_path is not None:
|
|
|
|
|
path_template_to_generate = os.path.join(
|
|
|
|
|
install_path, tested_module
|
|
|
|
|
)
|
|
|
|
|
elif generate_path:
|
|
|
|
|
path_template_to_generate = os.path.join(
|
|
|
|
|
generate_path, tested_module
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
path_template_to_generate = os.path.join(
|
|
|
|
|
path_module_check, tested_module
|
|
|
|
|
)
|
|
|
|
|
if generate_path is not None:
|
|
|
|
|
path_module_to_generate = os.path.join(
|
|
|
|
|
generate_path, search_class_module
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
path_module_to_generate = os.path.join(
|
|
|
|
|
path_module_check, search_class_module
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
path_template_to_generate = None
|
|
|
|
|
path_module_to_generate = None
|
|
|
|
|
|
|
|
|
|
use_test_path_generic = False
|
|
|
|
|
destination_path = None
|
|
|
|
|
temp_dir_name = None
|
|
|
|
|
if run_in_sandbox:
|
2024-01-22 20:17:55 -05:00
|
|
|
if keep_cache:
|
2022-02-03 22:44:08 -05:00
|
|
|
temp_dir = tempfile.mkdtemp()
|
|
|
|
|
temp_dir_name = temp_dir
|
|
|
|
|
else:
|
|
|
|
|
temp_dir = tempfile.TemporaryDirectory()
|
|
|
|
|
temp_dir_name = temp_dir.name
|
|
|
|
|
print(temp_dir_name)
|
|
|
|
|
temp_dir_name = os.path.join(temp_dir_name, "workspace")
|
|
|
|
|
os.mkdir(temp_dir_name)
|
|
|
|
|
|
|
|
|
|
lst_path_to_add_config = []
|
|
|
|
|
lst_path_to_remove_config = []
|
|
|
|
|
if not os.path.exists(path_module_check):
|
2024-01-23 22:04:15 -05:00
|
|
|
# TODO wrong return
|
2022-02-03 22:44:08 -05:00
|
|
|
return (
|
2024-02-23 13:01:10 -05:00
|
|
|
f"{Fore.RED}Error{Style.RESET_ALL} var path_module_check"
|
|
|
|
|
f" '{path_module_check}' not exist.",
|
2022-02-03 22:44:08 -05:00
|
|
|
-1,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
copy_path_module_check = path_module_check
|
|
|
|
|
path_module_check = os.path.normpath(
|
|
|
|
|
os.path.join(temp_dir_name, path_module_check)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if generated_module and path_module_check.endswith(
|
|
|
|
|
"/" + generated_module
|
|
|
|
|
):
|
|
|
|
|
use_test_path_generic = True
|
|
|
|
|
destination_path = path_module_check[
|
|
|
|
|
: -(len(generated_module) + 1)
|
|
|
|
|
]
|
|
|
|
|
copy_path = copy_path_module_check[: -(len(generated_module) + 1)]
|
|
|
|
|
elif search_class_module and path_module_check.endswith(
|
|
|
|
|
"/" + search_class_module
|
|
|
|
|
):
|
|
|
|
|
destination_path = path_module_check[
|
|
|
|
|
: -(len(search_class_module) + 1)
|
|
|
|
|
]
|
|
|
|
|
copy_path = copy_path_module_check[
|
|
|
|
|
: -(len(search_class_module) + 1)
|
|
|
|
|
]
|
|
|
|
|
else:
|
|
|
|
|
destination_path = path_module_check
|
|
|
|
|
copy_path = copy_path_module_check
|
|
|
|
|
|
|
|
|
|
lst_path_to_add_config.append(destination_path)
|
|
|
|
|
lst_path_to_remove_config.append(copy_path)
|
|
|
|
|
|
|
|
|
|
ignore_tree = await aioshutil.ignore_patterns(".git", "setup")
|
|
|
|
|
await aioshutil.copytree(
|
|
|
|
|
copy_path, destination_path, ignore=ignore_tree
|
|
|
|
|
)
|
|
|
|
|
# destination_path_with_git = os.path.join(destination_path, ".git")
|
|
|
|
|
# if os.path.exists(destination_path_with_git):
|
|
|
|
|
# await aioshutil.rmtree(destination_path_with_git)
|
|
|
|
|
# destination_path_with_setup = os.path.join(destination_path, "setup")
|
|
|
|
|
# if os.path.exists(destination_path_with_setup):
|
|
|
|
|
# await aioshutil.rmtree(destination_path_with_setup)
|
|
|
|
|
|
|
|
|
|
if tested_module:
|
|
|
|
|
lst_module_to_test = tested_module.split(",")
|
|
|
|
|
for module_name in lst_module_to_test:
|
|
|
|
|
# Update path to change new emplacement
|
2023-02-18 23:20:42 -05:00
|
|
|
s_lst_path_tested_module = (
|
|
|
|
|
await lib_asyncio.run_command_get_output(
|
2025-04-23 04:38:45 -04:00
|
|
|
"find",
|
2025-08-07 06:28:34 -04:00
|
|
|
f"./odoo{ODOO_VERSION}/addons/",
|
2025-04-23 04:38:45 -04:00
|
|
|
"-name",
|
|
|
|
|
module_name,
|
2023-02-18 23:20:42 -05:00
|
|
|
)
|
2022-02-03 22:44:08 -05:00
|
|
|
)
|
|
|
|
|
if not s_lst_path_tested_module:
|
2024-01-23 22:04:15 -05:00
|
|
|
# TODO wrong return
|
2022-02-03 22:44:08 -05:00
|
|
|
return (
|
2024-02-23 13:01:10 -05:00
|
|
|
f"{Fore.RED}Error{Style.RESET_ALL} cannot find module"
|
|
|
|
|
f" '{path_module_check}' not exist.",
|
2022-02-03 22:44:08 -05:00
|
|
|
-1,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
lst_path_tested_module = (
|
|
|
|
|
s_lst_path_tested_module.strip().split("\n")
|
|
|
|
|
)
|
|
|
|
|
s_first_path = lst_path_tested_module[0]
|
2025-08-07 06:28:34 -04:00
|
|
|
# parent_dir = os.path.dirname(s_first_path).replace("addons/", f"odoo{ODOO_VERSION}/addons/")
|
2022-02-03 22:44:08 -05:00
|
|
|
parent_dir = os.path.dirname(s_first_path)
|
|
|
|
|
# Copy it
|
|
|
|
|
if copy_path != parent_dir:
|
|
|
|
|
os.path.basename(parent_dir)
|
|
|
|
|
new_destination_path = os.path.join(
|
|
|
|
|
os.path.dirname(destination_path),
|
|
|
|
|
os.path.basename(parent_dir),
|
|
|
|
|
)
|
|
|
|
|
ignore_tree = await aioshutil.ignore_patterns(
|
|
|
|
|
".git", "setup"
|
|
|
|
|
)
|
|
|
|
|
await aioshutil.copytree(
|
|
|
|
|
parent_dir,
|
|
|
|
|
new_destination_path,
|
|
|
|
|
ignore=ignore_tree,
|
|
|
|
|
)
|
|
|
|
|
# destination_path_with_git = os.path.join(
|
|
|
|
|
# new_destination_path, ".git"
|
|
|
|
|
# )
|
|
|
|
|
# if os.path.exists(destination_path_with_git):
|
|
|
|
|
# await aioshutil.rmtree(destination_path_with_git)
|
|
|
|
|
lst_path_to_add_config.append(new_destination_path)
|
|
|
|
|
lst_path_to_remove_config.append(parent_dir)
|
|
|
|
|
|
|
|
|
|
new_s_first_path = os.path.normpath(
|
|
|
|
|
os.path.join(temp_dir_name, s_first_path)
|
|
|
|
|
)
|
|
|
|
|
|
2023-02-18 23:20:42 -05:00
|
|
|
s_lst_path_generated_module = (
|
|
|
|
|
await lib_asyncio.run_command_get_output(
|
|
|
|
|
"find",
|
|
|
|
|
"./addons/",
|
|
|
|
|
"-name",
|
|
|
|
|
generated_module,
|
|
|
|
|
cwd=temp_dir_name,
|
|
|
|
|
)
|
2022-02-03 22:44:08 -05:00
|
|
|
)
|
|
|
|
|
if s_lst_path_generated_module:
|
|
|
|
|
lst_path_generated_module = (
|
|
|
|
|
s_lst_path_generated_module.strip().split("\n")
|
|
|
|
|
)
|
|
|
|
|
s_first_path = os.path.normpath(
|
|
|
|
|
os.path.join(
|
|
|
|
|
temp_dir_name,
|
|
|
|
|
os.path.dirname(lst_path_generated_module[0]),
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
# TODO This is wrong... bug in template if reach this case
|
|
|
|
|
s_first_path = destination_path
|
|
|
|
|
|
|
|
|
|
hook_file = os.path.join(new_s_first_path, "hooks.py")
|
2024-03-14 22:57:30 -04:00
|
|
|
if not os.path.exists(hook_file):
|
|
|
|
|
test_status += 1
|
|
|
|
|
test_result += f"Hook file '{hook_file}' not exist."
|
|
|
|
|
delta = datetime.datetime.now() - time_init
|
|
|
|
|
total_time = delta.total_seconds()
|
|
|
|
|
return test_result, test_status, test_name, total_time
|
2022-02-03 22:44:08 -05:00
|
|
|
with open(hook_file) as hook:
|
|
|
|
|
hook_line = hook.read()
|
|
|
|
|
has_template = (
|
|
|
|
|
"template_dir = os.path.normpath" in hook_line
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Goal, update path_module_generate, maybe commented
|
|
|
|
|
# Goal, update template_dir, maybe not exist
|
|
|
|
|
# TODO need to refactor this and use AST and not string research
|
|
|
|
|
|
|
|
|
|
# try find nb space indentation
|
|
|
|
|
lst_f_key = [
|
|
|
|
|
"# path_module_generate = ",
|
|
|
|
|
"#path_module_generate = ",
|
|
|
|
|
"path_module_generate = ",
|
|
|
|
|
]
|
|
|
|
|
nb_space_indentation = None
|
|
|
|
|
first_index = None
|
|
|
|
|
for f_key in lst_f_key:
|
|
|
|
|
if f_key in hook_line:
|
|
|
|
|
first_index = hook_line.find(f_key)
|
|
|
|
|
f_begin_index = (
|
|
|
|
|
hook_line.rfind("\n", 0, first_index) + 1
|
|
|
|
|
)
|
|
|
|
|
nb_space_indentation = (
|
|
|
|
|
first_index - f_begin_index
|
|
|
|
|
)
|
|
|
|
|
break
|
|
|
|
|
if nb_space_indentation is None:
|
2024-01-23 22:04:15 -05:00
|
|
|
# TODO wrong return
|
2022-02-03 22:44:08 -05:00
|
|
|
return (
|
|
|
|
|
f"Cannot find keys '{lst_f_key}' in"
|
|
|
|
|
f" {hook_file}",
|
|
|
|
|
-1,
|
|
|
|
|
)
|
|
|
|
|
end_string = "\n\n"
|
|
|
|
|
index_end_string = hook_line.find(
|
|
|
|
|
end_string, first_index
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if has_template:
|
|
|
|
|
new_hook_line = (
|
|
|
|
|
hook_line[: first_index + len(f_key)]
|
|
|
|
|
+ f'"{s_first_path}"\n'
|
|
|
|
|
+ f'{nb_space_indentation * " "}template_dir ='
|
|
|
|
|
f' "{s_first_path}/" + MODULE_NAME\n\n'
|
|
|
|
|
+ hook_line[index_end_string:]
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
new_hook_line = (
|
|
|
|
|
hook_line[: first_index + len(f_key)]
|
2025-04-23 04:38:45 -04:00
|
|
|
+ f'"{s_first_path}"'
|
2022-02-03 22:44:08 -05:00
|
|
|
+ hook_line[index_end_string:]
|
|
|
|
|
)
|
|
|
|
|
new_hook_line = new_hook_line.replace(
|
|
|
|
|
"# path_module_generate = ",
|
|
|
|
|
"path_module_generate = ",
|
|
|
|
|
)
|
|
|
|
|
new_hook_line = new_hook_line.replace(
|
|
|
|
|
'# "path_sync_code": path_module_generate,',
|
|
|
|
|
'"path_sync_code": path_module_generate,',
|
|
|
|
|
)
|
|
|
|
|
with open(hook_file, "w") as hook:
|
|
|
|
|
hook.write(new_hook_line)
|
|
|
|
|
|
|
|
|
|
# Format editing code before commit
|
2023-12-02 14:05:49 -05:00
|
|
|
# await lib_asyncio.run_command_get_output(
|
|
|
|
|
# "./script/maintenance/format.sh", temp_dir_name
|
|
|
|
|
# )
|
2022-02-03 22:44:08 -05:00
|
|
|
|
|
|
|
|
# init repo with git
|
|
|
|
|
for dir_to_git in lst_path_to_add_config:
|
2023-02-18 23:20:42 -05:00
|
|
|
await lib_asyncio.run_command_get_output(
|
|
|
|
|
"git", "init", ".", cwd=dir_to_git
|
|
|
|
|
)
|
|
|
|
|
await lib_asyncio.run_command_get_output(
|
|
|
|
|
"git", "add", ".", cwd=dir_to_git
|
|
|
|
|
)
|
|
|
|
|
await lib_asyncio.run_command_get_output(
|
2022-02-03 22:44:08 -05:00
|
|
|
"git", "commit", "-am", "'first commit'", cwd=dir_to_git
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
new_config_path = os.path.join(temp_dir_name, "config.conf")
|
|
|
|
|
update_config(
|
|
|
|
|
"./config.conf",
|
|
|
|
|
new_config_path,
|
|
|
|
|
lst_path_to_add_config=lst_path_to_add_config,
|
|
|
|
|
lst_path_to_remove_config=lst_path_to_remove_config,
|
|
|
|
|
module_name=generated_module,
|
|
|
|
|
)
|
2024-03-14 22:57:30 -04:00
|
|
|
if not os.path.exists(new_config_path):
|
|
|
|
|
test_status += 1
|
|
|
|
|
test_result += f"Config file '{new_config_path}' not exist."
|
|
|
|
|
delta = datetime.datetime.now() - time_init
|
|
|
|
|
total_time = delta.total_seconds()
|
|
|
|
|
return test_result, test_status, test_name, total_time
|
2022-02-03 22:44:08 -05:00
|
|
|
else:
|
|
|
|
|
new_config_path = None
|
|
|
|
|
|
2022-01-24 14:00:47 -05:00
|
|
|
if install_path is None:
|
|
|
|
|
install_path = path_module_check
|
2022-02-03 22:44:08 -05:00
|
|
|
elif run_in_sandbox:
|
|
|
|
|
install_path = os.path.normpath(
|
|
|
|
|
os.path.join(temp_dir_name, install_path)
|
|
|
|
|
)
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
# Check code, init module to install
|
|
|
|
|
if lst_init_module_name:
|
|
|
|
|
for module_name in lst_init_module_name:
|
|
|
|
|
res, status = await run_command(
|
|
|
|
|
"./script/code_generator/check_git_change_code_generator.sh",
|
|
|
|
|
path_module_check,
|
|
|
|
|
module_name,
|
|
|
|
|
test_name=test_name,
|
|
|
|
|
)
|
|
|
|
|
test_result += res
|
|
|
|
|
test_status += status
|
|
|
|
|
|
|
|
|
|
# Check code, module to generate
|
|
|
|
|
if tested_module:
|
|
|
|
|
res, status = await run_command(
|
|
|
|
|
"./script/code_generator/check_git_change_code_generator.sh",
|
|
|
|
|
path_module_check,
|
|
|
|
|
tested_module,
|
|
|
|
|
test_name=test_name,
|
|
|
|
|
)
|
|
|
|
|
test_result += res
|
|
|
|
|
test_status += status
|
|
|
|
|
|
|
|
|
|
# Leave when detect anomaly in check before start
|
|
|
|
|
if test_status:
|
2024-01-23 22:04:15 -05:00
|
|
|
delta = datetime.datetime.now() - time_init
|
|
|
|
|
total_time = delta.total_seconds()
|
|
|
|
|
return test_result, test_status, test_name, total_time
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
# Execute script before start
|
|
|
|
|
if script_after_init_check and not test_status:
|
|
|
|
|
res, status = await run_command(script_after_init_check)
|
|
|
|
|
test_result += res
|
|
|
|
|
test_status += status
|
|
|
|
|
|
|
|
|
|
is_db_create = False
|
|
|
|
|
unique_database_name = f"test_demo_{uuid.uuid4()}"[:63]
|
|
|
|
|
if not test_status:
|
2022-02-03 22:44:08 -05:00
|
|
|
# Create database
|
2022-01-24 14:00:47 -05:00
|
|
|
res, status = await run_command(
|
2023-01-02 20:33:57 -05:00
|
|
|
"./script/database/db_restore.py",
|
2022-01-24 14:00:47 -05:00
|
|
|
"--database",
|
|
|
|
|
unique_database_name,
|
2022-04-26 01:52:35 -04:00
|
|
|
"--image",
|
|
|
|
|
restore_db_image_name,
|
2022-01-24 14:00:47 -05:00
|
|
|
test_name=test_name,
|
|
|
|
|
)
|
|
|
|
|
test_result += res
|
|
|
|
|
test_status += status
|
|
|
|
|
is_db_create = not status
|
|
|
|
|
|
|
|
|
|
if not test_status and lst_init_module_name:
|
2022-02-03 22:44:08 -05:00
|
|
|
# Install required module
|
2022-01-24 14:00:47 -05:00
|
|
|
str_test = ",".join(lst_init_module_name)
|
2024-01-22 20:17:55 -05:00
|
|
|
if coverage:
|
2022-04-23 00:27:38 -04:00
|
|
|
script_name = (
|
|
|
|
|
"./script/addons/coverage_install_addons_dev.sh"
|
|
|
|
|
if tested_module
|
|
|
|
|
else "./script/addons/coverage_install_addons.sh"
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
script_name = (
|
|
|
|
|
"./script/addons/install_addons_dev.sh"
|
|
|
|
|
if tested_module
|
|
|
|
|
else "./script/addons/install_addons.sh"
|
|
|
|
|
)
|
2022-02-03 22:44:08 -05:00
|
|
|
if new_config_path:
|
|
|
|
|
res, status = await run_command(
|
|
|
|
|
script_name,
|
|
|
|
|
unique_database_name,
|
|
|
|
|
str_test,
|
|
|
|
|
new_config_path,
|
|
|
|
|
test_name=test_name,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
res, status = await run_command(
|
|
|
|
|
script_name,
|
|
|
|
|
unique_database_name,
|
|
|
|
|
str_test,
|
|
|
|
|
test_name=test_name,
|
|
|
|
|
)
|
2022-01-24 14:00:47 -05:00
|
|
|
test_result += res
|
|
|
|
|
test_status += status
|
|
|
|
|
|
|
|
|
|
if not test_status and search_class_module and generated_module:
|
2022-02-03 22:44:08 -05:00
|
|
|
# Update template with class/model/inherit
|
2022-01-24 14:00:47 -05:00
|
|
|
res, status = await run_command(
|
|
|
|
|
"./script/code_generator/search_class_model.py",
|
|
|
|
|
"--quiet",
|
|
|
|
|
"-d",
|
|
|
|
|
path_module_to_generate,
|
|
|
|
|
"-t",
|
|
|
|
|
path_template_to_generate,
|
|
|
|
|
test_name=test_name,
|
|
|
|
|
)
|
|
|
|
|
test_result += res
|
|
|
|
|
test_status += status
|
|
|
|
|
|
2022-12-21 22:45:04 -05:00
|
|
|
# test_generated_path = (
|
|
|
|
|
# install_path if destination_path is None else new_destination_path
|
|
|
|
|
# )
|
2022-02-03 22:44:08 -05:00
|
|
|
test_generated_path = (
|
|
|
|
|
destination_path if use_test_path_generic else install_path
|
|
|
|
|
)
|
|
|
|
|
# if destination_path is None:
|
|
|
|
|
# destination_path = install_path
|
2022-01-24 14:00:47 -05:00
|
|
|
|
2022-02-03 22:44:08 -05:00
|
|
|
if not test_status and tested_module and generated_module:
|
2022-04-23 00:27:38 -04:00
|
|
|
cmd = (
|
|
|
|
|
"./script/code_generator/coverage_install_and_test_code_generator.sh"
|
2024-01-22 20:17:55 -05:00
|
|
|
if coverage
|
2022-04-23 00:27:38 -04:00
|
|
|
else "./script/code_generator/install_and_test_code_generator.sh"
|
|
|
|
|
)
|
2022-02-03 22:44:08 -05:00
|
|
|
# Finally, the test
|
|
|
|
|
if new_config_path:
|
|
|
|
|
res, status = await run_command(
|
2022-04-23 00:27:38 -04:00
|
|
|
cmd,
|
2022-02-03 22:44:08 -05:00
|
|
|
unique_database_name,
|
|
|
|
|
tested_module,
|
|
|
|
|
test_generated_path,
|
|
|
|
|
generated_module,
|
|
|
|
|
new_config_path,
|
|
|
|
|
test_name=test_name,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
res, status = await run_command(
|
2022-04-23 00:27:38 -04:00
|
|
|
cmd,
|
2022-02-03 22:44:08 -05:00
|
|
|
unique_database_name,
|
|
|
|
|
tested_module,
|
|
|
|
|
install_path,
|
|
|
|
|
generated_module,
|
|
|
|
|
test_name=test_name,
|
|
|
|
|
)
|
2022-01-24 14:00:47 -05:00
|
|
|
test_result += res
|
|
|
|
|
test_status += status
|
|
|
|
|
|
|
|
|
|
if is_db_create:
|
|
|
|
|
res, status = await run_command(
|
2025-05-04 23:10:34 -04:00
|
|
|
"./odoo_bin.sh",
|
2022-01-24 14:00:47 -05:00
|
|
|
"db",
|
|
|
|
|
"--drop",
|
|
|
|
|
"--database",
|
|
|
|
|
unique_database_name,
|
|
|
|
|
test_name=test_name,
|
|
|
|
|
)
|
|
|
|
|
test_result += res
|
|
|
|
|
test_status += status
|
|
|
|
|
|
2024-01-23 22:04:15 -05:00
|
|
|
if file_to_restore:
|
|
|
|
|
lst_file_to_ignore = file_to_restore.strip().split(",")
|
|
|
|
|
if file_to_restore_origin:
|
|
|
|
|
repo_demo_portal = git.Repo(origin_path_module_check)
|
|
|
|
|
else:
|
|
|
|
|
repo_demo_portal = git.Repo(path_module_check)
|
|
|
|
|
|
|
|
|
|
status_to_check = repo_demo_portal.git.status("-s")
|
|
|
|
|
if all([f"D {a}" in status_to_check for a in lst_file_to_ignore]):
|
|
|
|
|
# Revert it
|
|
|
|
|
for file_name in lst_file_to_ignore:
|
|
|
|
|
repo_demo_portal.git.checkout(file_name)
|
|
|
|
|
else:
|
|
|
|
|
test_status += 1
|
|
|
|
|
test_result += (
|
2024-02-23 13:01:10 -05:00
|
|
|
f"\n\n{Fore.RED}FAIL{Style.RESET_ALL} - inspect to delete file"
|
|
|
|
|
f" {lst_file_to_ignore}"
|
2024-01-23 22:04:15 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
delta = datetime.datetime.now() - time_init
|
|
|
|
|
total_time = delta.total_seconds()
|
|
|
|
|
return test_result, test_status, test_name, total_time
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
|
2025-11-20 02:44:44 -05:00
|
|
|
async def check_git_change():
|
2022-01-24 14:00:47 -05:00
|
|
|
"""
|
|
|
|
|
return True if success
|
|
|
|
|
"""
|
|
|
|
|
loop = asyncio.get_event_loop()
|
|
|
|
|
task_list = [
|
|
|
|
|
run_command(
|
|
|
|
|
"./script/code_generator/check_git_change_code_generator.sh",
|
2025-08-07 06:28:34 -04:00
|
|
|
f"./odoo{ODOO_VERSION}/addons/TechnoLibre_odoo-code-generator-template",
|
2023-01-23 23:26:01 -05:00
|
|
|
test_name=(
|
|
|
|
|
"Init check_git_change"
|
|
|
|
|
" TechnoLibre_odoo-code-generator-template"
|
|
|
|
|
),
|
2023-01-04 08:02:07 -05:00
|
|
|
),
|
|
|
|
|
run_command(
|
|
|
|
|
"./script/code_generator/check_git_change_code_generator.sh",
|
2025-08-07 06:28:34 -04:00
|
|
|
f"./odoo{ODOO_VERSION}/addons/OCA_server-tools",
|
2023-01-04 08:02:07 -05:00
|
|
|
test_name="Init check_git_change OCA_server-tools",
|
2023-01-23 23:26:01 -05:00
|
|
|
),
|
2022-01-24 14:00:47 -05:00
|
|
|
]
|
2025-11-20 02:44:44 -05:00
|
|
|
tpl_result = await asyncio.gather(*task_list)
|
2022-01-24 14:00:47 -05:00
|
|
|
status = any([a[1] for a in tpl_result])
|
|
|
|
|
return not status
|
|
|
|
|
|
|
|
|
|
|
2024-01-23 22:04:15 -05:00
|
|
|
async def run_test_command(
|
|
|
|
|
script_path: str, test_name: str
|
|
|
|
|
) -> Tuple[str, int, str, float]:
|
|
|
|
|
time_init = datetime.datetime.now()
|
|
|
|
|
res, status = await run_command(script_path, test_name=test_name)
|
|
|
|
|
delta = datetime.datetime.now() - time_init
|
|
|
|
|
total_time = delta.total_seconds()
|
|
|
|
|
return res, status, test_name, total_time
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
|
2024-01-23 22:04:15 -05:00
|
|
|
def run_all_test(config) -> bool:
|
|
|
|
|
if config.json_model:
|
|
|
|
|
json_model = config.json_model
|
|
|
|
|
else:
|
|
|
|
|
with open(CONFIG_TESTCASE_JSON) as config_json:
|
|
|
|
|
json_model = config_json.read()
|
|
|
|
|
dct_model_test = json.loads(json_model)
|
|
|
|
|
lst_test = dct_model_test.get("lst_test")
|
|
|
|
|
if not lst_test:
|
|
|
|
|
_logger.error("Model missing attribute 'lst_test'.")
|
|
|
|
|
return False
|
|
|
|
|
# Sort test by sequence
|
|
|
|
|
dct_task = defaultdict(list)
|
|
|
|
|
dct_task_name = defaultdict(list)
|
|
|
|
|
for dct_test in lst_test:
|
2025-04-23 03:19:10 -04:00
|
|
|
if dct_test.get("disable"):
|
|
|
|
|
continue
|
2025-04-23 04:38:45 -04:00
|
|
|
# Force change addons path
|
|
|
|
|
# if "path_module_check" in dct_test.keys():
|
2025-08-07 06:28:34 -04:00
|
|
|
# # dct_test["path_module_check"] = dct_test["path_module_check"].replace("addons/", f"odoo{ODOO_VERSION}/addons/")
|
2025-04-23 04:38:45 -04:00
|
|
|
# dct_test["path_module_check"] = dct_test["path_module_check"]
|
2024-01-23 22:04:15 -05:00
|
|
|
sequence = dct_test.get("sequence", 0)
|
|
|
|
|
cb_coroutine = None
|
|
|
|
|
test_name = None
|
|
|
|
|
if dct_test.get("run_command"):
|
|
|
|
|
test_name = dct_test.get("test_name")
|
|
|
|
|
if not test_name:
|
|
|
|
|
raise ValueError(
|
|
|
|
|
"Missing attribute 'test_name' into the json_model."
|
|
|
|
|
)
|
|
|
|
|
script = dct_test.get("script")
|
|
|
|
|
if not script:
|
|
|
|
|
raise ValueError(
|
|
|
|
|
"Missing attribute 'script' into the json_model."
|
|
|
|
|
)
|
|
|
|
|
cb_coroutine = run_test_command(script, test_name)
|
|
|
|
|
elif dct_test.get("run_test_exec"):
|
|
|
|
|
path_module_check = dct_test.get("path_module_check")
|
|
|
|
|
if not path_module_check:
|
|
|
|
|
raise ValueError(
|
|
|
|
|
"Missing attribute 'path_module_check' into the"
|
|
|
|
|
" json_model."
|
|
|
|
|
)
|
|
|
|
|
generated_module = dct_test.get("generated_module")
|
|
|
|
|
generate_path = dct_test.get("generate_path")
|
|
|
|
|
tested_module = dct_test.get("tested_module")
|
|
|
|
|
search_class_module = dct_test.get("search_class_module")
|
|
|
|
|
script_after_init_check = dct_test.get("script_after_init_check")
|
|
|
|
|
init_module_name = dct_test.get("init_module_name")
|
|
|
|
|
lst_init_module_name = None
|
|
|
|
|
if init_module_name:
|
|
|
|
|
lst_init_module_name = init_module_name.split(",")
|
|
|
|
|
test_name = dct_test.get("test_name")
|
|
|
|
|
if not test_name:
|
|
|
|
|
raise ValueError(
|
|
|
|
|
"Missing attribute 'test_name' into the json_model."
|
|
|
|
|
)
|
|
|
|
|
file_to_restore = dct_test.get("file_to_restore")
|
|
|
|
|
file_to_restore_origin = dct_test.get(
|
|
|
|
|
"file_to_restore_origin", False
|
2022-12-21 22:45:04 -05:00
|
|
|
)
|
2024-01-23 22:04:15 -05:00
|
|
|
install_path = dct_test.get("install_path")
|
|
|
|
|
run_in_sandbox = dct_test.get("run_in_sandbox", True)
|
|
|
|
|
restore_db_image_name = dct_test.get(
|
2025-04-23 03:19:10 -04:00
|
|
|
"restore_db_image_name", "odoo12.0_base"
|
2024-01-23 22:04:15 -05:00
|
|
|
)
|
|
|
|
|
keep_cache = config.keep_cache
|
|
|
|
|
coverage = config.coverage
|
|
|
|
|
cb_coroutine = test_exec(
|
|
|
|
|
path_module_check,
|
|
|
|
|
generated_module=generated_module,
|
|
|
|
|
generate_path=generate_path,
|
|
|
|
|
tested_module=tested_module,
|
|
|
|
|
search_class_module=search_class_module,
|
|
|
|
|
script_after_init_check=script_after_init_check,
|
|
|
|
|
lst_init_module_name=lst_init_module_name,
|
|
|
|
|
file_to_restore=file_to_restore,
|
|
|
|
|
file_to_restore_origin=file_to_restore_origin,
|
|
|
|
|
test_name=test_name,
|
|
|
|
|
install_path=install_path,
|
|
|
|
|
run_in_sandbox=run_in_sandbox,
|
|
|
|
|
restore_db_image_name=restore_db_image_name,
|
|
|
|
|
keep_cache=keep_cache,
|
|
|
|
|
coverage=coverage,
|
|
|
|
|
)
|
|
|
|
|
if cb_coroutine:
|
|
|
|
|
dct_task[sequence].append(cb_coroutine)
|
|
|
|
|
dct_task_name[sequence].append(test_name)
|
|
|
|
|
lst_sequence = sorted(list(dct_task.keys()))
|
|
|
|
|
# Print summary
|
|
|
|
|
total_tpl_result = []
|
|
|
|
|
total_tpl_task = []
|
|
|
|
|
# Print summary
|
|
|
|
|
for sequence in lst_sequence:
|
|
|
|
|
lst_task = dct_task[sequence]
|
|
|
|
|
lst_task_name = dct_task_name[sequence]
|
|
|
|
|
print(f"sequence {sequence}")
|
|
|
|
|
lib_asyncio.print_summary_task(lst_task, lst_task_name=lst_task_name)
|
|
|
|
|
# Execute in sequence
|
|
|
|
|
for sequence in lst_sequence:
|
|
|
|
|
lst_task = dct_task[sequence]
|
|
|
|
|
tpl_result, has_asyncio_error = lib_asyncio.execute(config, lst_task)
|
2024-02-23 17:20:09 -05:00
|
|
|
if tpl_result:
|
|
|
|
|
total_tpl_result.extend(tpl_result)
|
|
|
|
|
else:
|
|
|
|
|
_logger.error("tpl_result is empty.")
|
|
|
|
|
if lst_task:
|
|
|
|
|
total_tpl_task.extend(lst_task)
|
|
|
|
|
else:
|
|
|
|
|
_logger.error("tpl_task is empty.")
|
|
|
|
|
|
2024-01-23 22:04:15 -05:00
|
|
|
print_log(total_tpl_task, total_tpl_result)
|
|
|
|
|
status = check_result(total_tpl_task, total_tpl_result)
|
2023-02-14 16:47:04 -05:00
|
|
|
if status:
|
|
|
|
|
log_file_print = LOG_FILE
|
|
|
|
|
else:
|
2024-02-23 13:01:10 -05:00
|
|
|
log_file_print = f"{Fore.RED}{LOG_FILE}{Style.RESET_ALL}"
|
2023-02-14 16:47:04 -05:00
|
|
|
|
2024-01-23 22:04:15 -05:00
|
|
|
if config.output_result_dir:
|
|
|
|
|
print_log_output_into_dir(total_tpl_result, config.output_result_dir)
|
|
|
|
|
|
2023-02-14 16:47:04 -05:00
|
|
|
print(f"Log file {log_file_print}")
|
2024-01-23 22:04:15 -05:00
|
|
|
return status
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
2022-02-03 22:44:08 -05:00
|
|
|
# TODO configure logger with thread
|
|
|
|
|
# logging.basicConfig(
|
|
|
|
|
# level=logging.INFO,
|
|
|
|
|
# format='%(threadName)10s %(name)18s: %(message)s',
|
|
|
|
|
# stream=sys.stderr,
|
|
|
|
|
# )
|
2022-01-24 14:00:47 -05:00
|
|
|
config = get_config()
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
if not config.ignore_init_check_git:
|
2025-11-20 02:44:44 -05:00
|
|
|
success = asyncio.run(check_git_change())
|
2022-01-24 14:00:47 -05:00
|
|
|
else:
|
|
|
|
|
success = True
|
2024-01-23 22:04:15 -05:00
|
|
|
status = False
|
2022-01-24 14:00:47 -05:00
|
|
|
if success:
|
2024-01-23 22:04:15 -05:00
|
|
|
status = run_all_test(config)
|
2022-01-24 14:00:47 -05:00
|
|
|
end_time = time.time()
|
|
|
|
|
diff_sec = end_time - start_time
|
|
|
|
|
# print(f"Time execution {diff_sec:.3f}s")
|
|
|
|
|
print(f"Time execution {datetime.timedelta(seconds=diff_sec)}")
|
|
|
|
|
|
2024-01-23 22:04:15 -05:00
|
|
|
return int(not status)
|
2022-01-24 14:00:47 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
sys.exit(main())
|