diff --git a/test/scripts/email_config.yaml b/test/scripts/email_config.yaml
index 77a779d374bd56457f52577dcd3a8fd7b33e4dfd..10e9b8c9ed1d9ee26260c17e0b31216ce8a41bb0 100644
--- a/test/scripts/email_config.yaml
+++ b/test/scripts/email_config.yaml
@@ -11,17 +11,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-sender_email_address :
-auth_code :
-receiver_list :
-smtp_server :
-smtp_port :
+user_name : ""
+sender_email_address : ""
+auth_code : ""
+receiver_list :
+ - ""
+smtp_server: ""
+smtp_port: "25"
-xts_report_file : ".\\auto_xts_test\\result\\summary_report.html"
-sdk_report_file : ".\\sdk_test\\sdk_test_report.html"
-perf_report_file : ""
+xts_report_file : "./auto_xts_test/result/summary_report.html"
+sdk_report_file : "./sdk_test/sdk_test_report.html"
+perf_report_file : "./performance_test/mail_data/email_msg.html"
attatchment_files :
- - ".\\auto_xts_test\\result\\details_report.html"
- - ".\\auto_xts_test\\result\\failures_report.html"
- - ".\\sdk_test\\sdk_test_report.html"
- - ".\\sdk_test\\sdk_test_log.txt"
+ - "./auto_xts_test/result/details_report.html"
+ - "./auto_xts_test/result/failures_report.html"
+ - "./performance_test/mail_data/performance_logs.zip"
+image_files:
+ "./performance_test/mail_data/debug_full_time.jpg": performance00
+ "./performance_test/mail_data/debug_incremental_time.jpg": performance01
+ "./performance_test/mail_data/release_full_time.jpg": performance10
+ "./performance_test/mail_data/release_incremental_time.jpg": performance11
diff --git a/test/scripts/performance_test/performance_build.py b/test/scripts/performance_test/performance_build.py
new file mode 100644
index 0000000000000000000000000000000000000000..a4d7572c569e41ebc8b4b7c48932a404d1a95593
--- /dev/null
+++ b/test/scripts/performance_test/performance_build.py
@@ -0,0 +1,429 @@
+#!/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 os
+import subprocess
+import stat
+import time
+import zipfile
+
+import performance_config
+
+
+class PerformanceBuild():
+ def __init__(self, config_input, mail_obj):
+ self.config = None
+ self.first_line_in_avg_excel = ""
+ self.time_avg_dic = {}
+ self.all_time_dic = {}
+ self.size_avg_dic = {}
+ self.all_size_dic = {}
+ self.mail_helper = None
+ self.built_times = 0
+ self.mail_msg = ''
+ # If developing_test_mode is True, the project will not be built and use following test data
+ self.developing_test_mode = False
+ self.developing_test_data = 'entry:clean|18 ms :clean|1 ms total build cost|1 s 204 ms ' + \
+ 'entry:default@OneTime|1 s 204 ms ' + \
+ 'entry:default@MergeProfile|4 ms entry:default@BuildNativeWithCmake|1 ms ' + \
+ 'entry:default@GenerateLoaderJson|2 ms entry:default@MakePackInfo|8 ms ' + \
+ 'entry:default@ProcessProfile|85 ms entry:default@BuildNativeWithNinja|1 ms ' + \
+ 'entry:default@ProcessResource|2 ms entry:default@ProcessLibs|3 ms entry:default@CompileResource|78 ms ' + \
+ 'entry:default@CompileJS|2 ms entry:default@CompileArkTS|2 s 591 ms entry:default@PackageHap|924 ms ' + \
+ 'entry:default@SignHap|2 ms entry:assembleHap|1 ms total build cost|4 s 886 ms ' + \
+ 'entry:default@BuildNativeWithCmake|1 ms entry:default@BuildNativeWithNinja|1 ms ' + \
+ 'entry:default@CompileJS|4 ms entry:default@CompileArkTS|2 s 472 ms entry:default@PackageHap|919 ms ' + \
+ 'entry:assembleHap|1 ms entry:default@SignHap|2 ms total build cost|4 s 632 ms ' + \
+ 'entry:clean|18 ms :clean|1 ms total build cost|1 s 204 ms entry:default@MergeProfile|4 ms ' + \
+ 'entry:default@BuildNativeWithCmake|1 ms entry:default@GenerateLoaderJson|2 ms ' + \
+ 'entry:default@MakePackInfo|8 ms entry:default@ProcessProfile|85 ms ' + \
+ 'entry:default@BuildNativeWithNinja|1 ms entry:default@ProcessResource|2 ms ' + \
+ 'entry:default@ProcessLibs|3 ms entry:default@CompileResource|78 ms entry:default@CompileJS|2 ms ' + \
+ 'entry:default@CompileArkTS|2 s 591 ms entry:default@PackageHap|924 ms entry:default@SignHap|2 ms ' + \
+ 'entry:assembleHap|1 ms total build cost|4 s 886 ms entry:default@BuildNativeWithCmake|1 ms ' + \
+ 'entry:default@BuildNativeWithNinja|1 ms entry:default@CompileJS|4 ms ' + \
+ 'entry:default@CompileArkTS|2 s 472 ms entry:default@PackageHap|919 ms entry:default@SignHap|2 ms ' + \
+ 'entry:assembleHap|1 ms total build cost|4 s 632 ms entry:clean|18 ms :clean|1 ms ' + \
+ 'total build cost|1 s 204 ms entry:default@MergeProfile|4 ms entry:default@BuildNativeWithCmake|1 ms' + \
+ ' entry:default@GenerateLoaderJson|2 ms entry:default@MakePackInfo|8 ms ' + \
+ 'entry:default@ProcessProfile|85 ms entry:default@BuildNativeWithNinja|1 ms' + \
+ ' entry:default@ProcessResource|2 ms entry:default@ProcessLibs|3 ms entry:default@CompileResource|78 ms' + \
+ ' entry:default@CompileJS|2 ms entry:default@CompileArkTS|2 s 591 ms ' + \
+ 'entry:default@PackageHap|924 ms entry:default@SignHap|2 ms entry:assembleHap|1 ms ' + \
+ 'total build cost|4 s 886 ms entry:default@BuildNativeWithCmake|1 ms ' + \
+ 'entry:default@BuildNativeWithNinja|1 ms entry:default@CompileJS|4 ms ' + \
+ 'entry:default@CompileArkTS|2 s 472 ms entry:default@PackageHap|919 ms entry:default@SignHap|2 ms ' + \
+ 'entry:assembleHap|1 ms total build cost|4 s 632 ms '
+ self.mail_helper = mail_obj
+ self.config = config_input
+
+ def start(self):
+ self.init()
+ self.start_test()
+ self.write_mail_msg()
+ os.chdir(self.config.project_path)
+
+ @staticmethod
+ def append_into_dic(key, value, dic):
+ if key not in dic:
+ dic[key] = []
+ dic[key].append(value)
+
+ def init(self):
+ self.developing_test_mode = self.config.developing_test_mode
+ if self.config.ide == performance_config.IdeType.DevEco:
+ os.environ['path'] = self.config.node_js_path + ";" + os.environ['path']
+ os.chdir(self.config.project_path)
+ os.environ['path'] = os.path.join(self.config.jbr_path, "bin") + ";" + os.environ['path']
+ os.environ['JAVA_HOME'] = self.config.jbr_path
+ self.config.cmd_prefix = os.path.join(self.config.project_path, self.config.cmd_prefix)
+ self.config.log_direct = os.path.join(self.config.project_path, self.config.log_direct)
+ self.config.temp_filename = os.path.join(self.config.log_direct, self.config.temp_filename)
+ self.config.debug_package_path = os.path.join(self.config.project_path, self.config.debug_package_path)
+ self.config.release_package_path = os.path.join(self.config.project_path, self.config.release_package_path)
+ self.config.incremental_code_path = os.path.join(self.config.project_path, self.config.incremental_code_path)
+ if not os.path.exists(self.config.log_direct):
+ os.makedirs(self.config.log_direct)
+ self.config.log_direct = os.path.join(self.config.log_direct,
+ time.strftime(self.config.log_direct_data_format,
+ time.localtime()))
+ if not os.path.exists(self.config.log_direct):
+ os.makedirs(self.config.log_direct)
+ self.config.log_direct = os.path.join(self.config.project_path, self.config.log_direct)
+ if self.developing_test_mode:
+ self.config.build_times = 3
+
+ def clean_temp_log(self):
+ if os.path.exists(self.config.temp_filename):
+ os.remove(self.config.temp_filename)
+
+ @staticmethod
+ def add_code(code_path, start_pos, end_pos, code_str, lines):
+ with open(code_path, 'r+', encoding='UTF-8') as modified_file:
+ content = modified_file.read()
+ add_str_end_pos = content.find(end_pos)
+ if add_str_end_pos == -1:
+ print('Can not find code : {end_pos} in {code_path}, please check config')
+ return
+ add_str_start_pos = content.find(start_pos)
+ if add_str_start_pos == -1:
+ if lines == 0:
+ return
+ add_str_start_pos = add_str_end_pos
+ content_add = ""
+ for i in range(lines, 0, -1):
+ if "%d" in code_str:
+ content_add = content_add + code_str % i
+ else:
+ content_add = content_add + code_str
+ content = content[:add_str_start_pos] + content_add + content[add_str_end_pos:]
+ modified_file.seek(0)
+ modified_file.write(content)
+ modified_file.truncate()
+
+ def add_incremental_code(self, lines):
+ PerformanceBuild.add_code(self.config.incremental_code_path,
+ self.config.incremental_code_start_pos,
+ self.config.incremental_code_end_pos,
+ self.config.incremental_code_str,
+ lines)
+
+ def revert_incremental_code(self):
+ self.add_incremental_code(0)
+
+ def reset(self):
+ self.first_line_in_avg_excel = ""
+ self.time_avg_dic = {}
+ self.all_time_dic = {}
+ self.size_avg_dic = {}
+ self.all_size_dic = {}
+ self.built_times = 0
+ self.clean_temp_log()
+ self.revert_incremental_code()
+
+ def clean_project(self):
+ if not self.developing_test_mode:
+ print(self.config.cmd_prefix + " clean --no-daemon")
+ subprocess.Popen(self.config.cmd_prefix + " clean --no-daemon").wait()
+
+ def get_bytecode_size(self, is_debug):
+ if self.developing_test_mode:
+ # test data for size
+ PerformanceBuild.append_into_dic("ets/mudules.abc rawSize", 44444, self.all_size_dic)
+ PerformanceBuild.append_into_dic("ets/mudules.abc Compress_size", 33333, self.all_size_dic)
+ PerformanceBuild.append_into_dic("ets/mudules2.abc rawSize", 44444, self.all_size_dic)
+ PerformanceBuild.append_into_dic("ets/mudules2.abc Compress_size", 33333, self.all_size_dic)
+ return
+ package_path = self.config.debug_package_path if is_debug else self.config.release_package_path
+ package = zipfile.ZipFile(package_path)
+ extension_name = ".abc" if self.config.ide == performance_config.IdeType.DevEco else ".dex"
+ for info in package.infolist():
+ if info.filename.endswith(extension_name):
+ name_str1 = info.filename + " rawSize"
+ name_str2 = info.filename + " compress_size"
+ PerformanceBuild.append_into_dic(name_str1, info.file_size, self.all_size_dic)
+ PerformanceBuild.append_into_dic(name_str2, info.compress_size, self.all_size_dic)
+
+ def start_build(self, is_debug):
+ if self.developing_test_mode:
+ return
+ cmd_suffix = self.config.cmd_debug_suffix if is_debug else self.config.cmd_release_suffix
+ print(self.config.cmd_prefix + cmd_suffix)
+ subprocess.Popen(self.config.cmd_prefix + cmd_suffix).wait()
+
+ def get_millisecond(self, time_string):
+ if self.config.ide != performance_config.IdeType.DevEco and not self.developing_test_mode:
+ return int(time_string)
+ else:
+ cost_time = 0
+ res = time_string.split(" min ")
+ target_str = ""
+ if len(res) > 1:
+ cost_time = int(res[0]) * 60000
+ target_str = res[1]
+ else:
+ target_str = res[0]
+ res = target_str.split(" s ")
+ if len(res) > 1:
+ cost_time = cost_time + int(res[0]) * 1000
+ target_str = res[1]
+ else:
+ target_str = res[0]
+
+ res = target_str.split(" ms")
+ if len(res) > 1:
+ cost_time = cost_time + int(res[0])
+ return cost_time
+
+ def cal_incremental_avg_time(self):
+ self.first_line_in_avg_excel = self.first_line_in_avg_excel + "\n"
+ content = ""
+ if self.developing_test_mode:
+ content = self.developing_test_data.split("\t")
+ else:
+ src = open(self.config.temp_filename, "r", encoding='UTF-8')
+ content = src.read().split("\t")
+ src.close()
+ clean_filter = False
+ for task_build_time_str in content:
+ if len(task_build_time_str) == 0:
+ continue
+ pair = task_build_time_str.split("|")
+ key_str = pair[0]
+ if clean_filter:
+ if "total" in key_str:
+ clean_filter = False
+ continue
+ if "clean" in key_str:
+ clean_filter = True
+ continue
+ cost_time = self.get_millisecond(pair[1])
+ PerformanceBuild.append_into_dic(key_str, cost_time, self.all_time_dic)
+ for key in self.all_time_dic:
+ task_count = len(self.all_time_dic[key])
+ has_task = True
+ if task_count != 2 * self.config.build_times:
+ if task_count == self.config.build_times:
+ has_task = False
+ else:
+ continue
+ # average of first build
+ sum_build_time = 0
+ for i in range(0, self.config.build_times):
+ index = i * 2
+ if not has_task:
+ self.all_time_dic[key].insert(index + 1, 0)
+ sum_build_time = sum_build_time + self.all_time_dic[key][index]
+ cost = "%.2f s" % (sum_build_time / self.config.build_times / 1000)
+ PerformanceBuild.append_into_dic(key, cost, self.time_avg_dic)
+ # average of incremental build
+ sum_build_time = 0
+ for i in range(1, len(self.all_time_dic[key]), 2):
+ sum_build_time = sum_build_time + self.all_time_dic[key][i]
+ cost = "%.2f s" % (sum_build_time / self.config.build_times / 1000)
+ PerformanceBuild.append_into_dic(key, cost, self.time_avg_dic)
+
+ def cal_incremental_avg_size(self):
+ total_raw_size = []
+ total_compressed_size = []
+ for i in range(0, self.config.build_times * 2):
+ total_raw_size.append(0)
+ total_compressed_size.append(0)
+ for key in self.all_size_dic:
+ if "raw" in key:
+ total_raw_size[i] += self.all_size_dic[key][i]
+ else:
+ total_compressed_size[i] += self.all_size_dic[key][i]
+ self.all_size_dic["total_raw_size"] = total_raw_size
+ self.all_size_dic["total_compressed_size"] = total_compressed_size
+ for key in self.all_size_dic:
+ # sizes should be the same, just check
+ is_size_the_same = True
+ full_first_size = self.all_size_dic[key][0]
+ for i in range(0, len(self.all_size_dic[key]), 2):
+ if full_first_size != self.all_size_dic[key][i]:
+ is_size_the_same = False
+ break
+ is_size_the_same = is_size_the_same and full_first_size != -1
+ full_avg_size = f"{full_first_size} Byte" if is_size_the_same else "size is not the same"
+ PerformanceBuild.append_into_dic(key, full_avg_size, self.size_avg_dic)
+
+ is_size_the_same = True
+ incremental_first_size = self.all_size_dic[key][1]
+ for i in range(1, len(self.all_size_dic[key]), 2):
+ if incremental_first_size != self.all_size_dic[key][i]:
+ is_size_the_same = False
+ break
+ is_size_the_same = is_size_the_same and incremental_first_size != -1
+ incremental_avg_size = f"{incremental_first_size} Byte" if is_size_the_same else "size is not the same"
+ PerformanceBuild.append_into_dic(key, incremental_avg_size, self.size_avg_dic)
+
+ def cal_incremental_avg(self):
+ self.cal_incremental_avg_time()
+ self.cal_incremental_avg_size()
+ self.clean_temp_log()
+
+ @staticmethod
+ def add_row(context):
+ return rf'
{context}
'
+
+ @staticmethod
+ def add_td(context):
+ return rf'{context} | '
+
+ @staticmethod
+ def add_th(context):
+ return rf'{context} | '
+
+ @staticmethod
+ def test_type_title(context):
+ return rf'{context} |
'
+
+ @staticmethod
+ def app_title(context):
+ return rf'{context} | '
+
+ def write_mail_files(self, file_path, first_line, dic, mail_table_title="", is_debug=""):
+ msg = PerformanceBuild.test_type_title(mail_table_title)
+ if first_line:
+ first_row = ""
+ first_line_res = first_line.replace("\n", "").split("\t")
+ for i in first_line_res:
+ first_row += PerformanceBuild.add_th(i)
+ rows = PerformanceBuild.add_row(first_row)
+
+ for key in dic:
+ content_row = PerformanceBuild.add_th(key)
+ if "total" in key:
+ for v in dic[key]:
+ content_row += PerformanceBuild.add_td(v)
+ rows += PerformanceBuild.add_row(content_row)
+ if is_debug != '':
+ full_time = dic[key][0]
+ full_time = float(full_time[:len(full_time) - 2])
+ incremental_time = dic[key][1]
+ incremental_time = float(incremental_time[:len(incremental_time) - 2])
+ self.mail_helper.add_pic_data(is_debug, [full_time, incremental_time])
+ msg += rows
+ return msg
+
+ def write_from_dic(self, file_path, first_line, dic, mail_table_title="", is_debug=""):
+ content_list = []
+ if first_line:
+ content_list.append(first_line)
+ for key in dic:
+ content_list.append(key)
+ for v in dic[key]:
+ content_list.append("\t")
+ content_list.append(str(v))
+ content_list.append("\n")
+ excel_path = os.path.join(self.config.log_direct, os.path.basename(file_path))
+ content = "".join(content_list)
+ with os.fdopen(os.open(excel_path,
+ os.O_WRONLY | os.O_CREAT,
+ stat.S_IRWXU | stat.S_IRWXO | stat.S_IRWXG), 'w') as excel:
+ excel.write(content)
+ self.mail_helper.add_logs_file(file_path, content.encode())
+
+ if mail_table_title:
+ return self.write_mail_files(file_path, first_line, dic, mail_table_title, is_debug)
+ else:
+ return ""
+
+ def generate_full_and_incremental_results(self, is_debug):
+ path_prefix = self.config.output_split.join(
+ (self.config.ide_filename[self.config.ide - 1],
+ self.config.debug_or_release[0 if is_debug else 1],
+ self.config.build_type_of_log[0])
+ )
+ prj_name = os.path.basename(self.config.project_path)
+ temp_mail_msg = ""
+ # sizeAll
+ file_path = self.config.output_split.join((path_prefix, self.config.log_filename[0]))
+ file_path = os.path.join(prj_name, file_path)
+ self.write_from_dic(file_path, None, self.all_size_dic)
+ # sizeAvg and mailmsg
+ file_path = self.config.output_split.join((path_prefix, self.config.log_filename[1]))
+ file_path = os.path.join(prj_name, file_path)
+ temp_mail_msg += self.write_from_dic(file_path, self.first_line_in_avg_excel, self.size_avg_dic, "Size")
+ # timeAll
+ file_path = self.config.output_split.join((path_prefix, self.config.log_filename[2]))
+ file_path = os.path.join(prj_name, file_path)
+ self.write_from_dic(file_path, None, self.all_time_dic)
+ # timeAvg and mailmsg
+ file_path = self.config.output_split.join((path_prefix, self.config.log_filename[3]))
+ file_path = os.path.join(prj_name, file_path)
+ temp_mail_msg += self.write_from_dic(file_path, self.first_line_in_avg_excel,
+ self.time_avg_dic, "Time", is_debug)
+ # mail files
+ if self.config.send_mail:
+ temp_mail_msg = '' + \
+ PerformanceBuild.app_title(prj_name + (' Debug' if is_debug else ' Release')) + \
+ temp_mail_msg + '
'
+ self.mail_msg += temp_mail_msg
+
+ def full_and_incremental_build(self, is_debug):
+ self.reset()
+ self.first_line_in_avg_excel = self.first_line_in_avg_excel + "\tfirst build\tincremental build"
+ for i in range(self.config.build_times):
+ self.clean_project()
+ self.start_build(is_debug)
+ self.get_bytecode_size(is_debug)
+ self.add_incremental_code(1)
+ self.start_build(is_debug)
+ self.get_bytecode_size(is_debug)
+ self.revert_incremental_code()
+ self.cal_incremental_avg()
+ self.generate_full_and_incremental_results(is_debug)
+
+ def start_test(self):
+ self.full_and_incremental_build(True)
+ self.full_and_incremental_build(False)
+
+ def write_mail_msg(self):
+ if self.config.send_mail:
+ self.mail_helper.add_msg(self.mail_msg)
+
+
+def run(config_input, mail_obj):
+ start_time = time.time()
+ PerformanceBuild(config_input, mail_obj).start()
+ print("Test [%s] finished at: %s\n"\
+ "total cost: %ds"
+ % (os.path.basename(config_input.project_path),
+ time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
+ time.time() - start_time))
\ No newline at end of file
diff --git a/test/scripts/performance_test/performance_config.py b/test/scripts/performance_test/performance_config.py
new file mode 100644
index 0000000000000000000000000000000000000000..3135e38839f4316b41342328bab15d7c8aa37d51
--- /dev/null
+++ b/test/scripts/performance_test/performance_config.py
@@ -0,0 +1,179 @@
+#!/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 os
+
+
+class IdeType():
+ AS = 1
+ DevEco = 2
+
+
+class Config():
+ log_direct = "buildTestData"
+ log_direct_data_format = "%Y-%m-%d-%H-%M-%S"
+ temp_filename = "temp.txt"
+ send_mail = True
+
+ def __init__(self):
+ # Default config settings for all projects, if it's not what you need, config them in application_configs
+ self.cmd_prefix = r"hvigorw.bat"
+
+ self.output_split = "_"
+ self.ide_filename = ["AS", "DevEco"]
+ self.debug_or_release = ["Debug", "Release"]
+ self.build_type_of_log = ["full_then_incremental", "add_code_and_ui"]
+ self.log_filename = ["sizeAll.csv", "sizeAvg.csv",
+ "timeAll.csv", "timeAvg.csv"]
+ self.ide = IdeType.DevEco
+ self.incremental_code_str = "let index = 5 + 6\n"
+ self.incremental_code_start_pos = "let index = 5 + 6\n"
+ self.incremental_code_end_pos = 'this.num = num'
+ self.cmd_debug_suffix = r' --mode module -p product=default assembleHap --no-daemon'
+ self.cmd_release_suffix = r' --mode project -p product=default assembleApp --no-daemon'
+ self.debug_package_path = r'entry/build/default/outputs/default/entry-default-signed.hap'
+ self.release_package_path = r'entry/build/default/outputs/default/app/entry-default.hap'
+ self.incremental_code_path = r'entry/src/main/ets/pages/Index.ets'
+
+ # build serveral times then calculate the average value
+ self.build_times = 3
+ # Do not build the project,use the test data if you need to debug the scripts
+ self.developing_test_mode = False
+ # set your node_js path, it should be the same to the setting in your IDE
+ self.node_js_path = r"%s/nodejs" % os.environ['USERPROFILE']
+ # Must set according environment
+ self.jbr_path = r'xxx/DevEco Studio/jbr'
+
+ # If Default config is not what you need, you can set here!
+ application_configs = dict(
+ [
+ (
+ "FTB", dict
+ (
+ project_path=r"D:/FTB",
+ )
+ ),
+ (
+ "FDY", dict
+ (
+ project_path=r"D:/FDY",
+ )
+ ),
+ (
+ "FWX", dict
+ (
+ project_path=r"D:/FWX",
+ )
+ ),
+ (
+ "HelloWorld", dict
+ (
+ # The following params must be set according you environment
+ project_path=r"D:/HelloWorld",
+
+ # The following params is not neccessary to be modified
+ debug_package_path=r'entry/build/default/outputs/default/entry-default-unsigned.hap',
+ release_package_path=r'entry/build/default/outputs/default/app/entry-default.hap',
+ incremental_code_path=r'entry/src/main/ets/pages/Index.ets',
+ incremental_code_end_pos='build() {',
+ incremental_code_str="a: number=5 + 6\n",
+ incremental_code_start_pos="a: number=5 + 6\n",
+ )
+ )
+ ]
+ )
+
+
+def get_config(index):
+ config = Config()
+ res = config.application_configs.get(index)
+ if not res:
+ print("No key in config, please check: " + index)
+ return res
+ for k in res:
+ setattr(config, k, res[k])
+ return config
+
+
+def get_html_prefix():
+ return '' + \
+ 'Daily Performance Test |
---|
'
+
+
+def get_html_suffix():
+ return '

' + \
+ '

'
+
+
+class BuildMode():
+ DEBUG = 0
+ RELEASE = 1
+
+
+class BuildType():
+ FULL = 0
+ INCREMENTAL = 1
+
+
+class MailPicConfig():
+ mail_data_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ 'mail_data',
+ )
+
+ html_file_path = os.path.join(
+ mail_data_path,
+ "email_msg.html"
+ )
+
+ attach_path = os.path.join(
+ mail_data_path,
+ "performance_logs.zip"
+ )
+
+ # Count of days which will be add into the email picture
+ mail_pic_table_name = {
+ BuildMode.DEBUG: {
+ BuildType.FULL: os.path.join(mail_data_path, 'debug_full_time.csv'),
+ BuildType.INCREMENTAL: os.path.join(mail_data_path, 'debug_incremental_time.csv')
+ },
+ BuildMode.RELEASE:{
+ BuildType.FULL: os.path.join(mail_data_path, 'release_full_time.csv'),
+ BuildType.INCREMENTAL: os.path.join(mail_data_path, 'release_incremental_time.csv')
+ }
+ }
+
+ mail_pic_name = {
+ BuildMode.DEBUG: {
+ BuildType.FULL:os.path.join(mail_data_path, 'debug_full_time.jpg'),
+ BuildType.INCREMENTAL: os.path.join(mail_data_path, 'debug_incremental_time.jpg')
+ },
+ BuildMode.RELEASE:{
+ BuildType.FULL: os.path.join(mail_data_path, 'release_full_time.jpg'),
+ BuildType.INCREMENTAL: os.path.join(mail_data_path, 'release_incremental_time.jpg')
+ }
+ }
+
+ mail_pic_table_lable = {
+ BuildMode.DEBUG: {
+ BuildType.FULL: 'Debug Full Build',
+ BuildType.INCREMENTAL: 'Debug Incremental Build'
+ },
+ BuildMode.RELEASE:{
+ BuildType.FULL: 'Release Full Build',
+ BuildType.INCREMENTAL: 'Release Incremental Time'
+ }
+ }
\ No newline at end of file
diff --git a/test/scripts/performance_test/performance_entry.py b/test/scripts/performance_test/performance_entry.py
new file mode 100644
index 0000000000000000000000000000000000000000..be8c89f3c79c995e53ccc087fbd9af337877dab4
--- /dev/null
+++ b/test/scripts/performance_test/performance_entry.py
@@ -0,0 +1,187 @@
+#!/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 os
+import stat
+import time
+import zipfile
+
+import pandas as pd
+import numpy as np
+
+
+import performance_build
+import performance_config
+
+
+class MailHelper():
+ def __init__(self):
+ self.pic_table = {}
+ self.head_line = []
+ self.current_add_prj = ''
+ self.mail_msg = performance_config.get_html_prefix()
+ self.logs_file = {}
+ if os.path.exists(performance_config.MailPicConfig.html_file_path):
+ os.remove(performance_config.MailPicConfig.html_file_path)
+ if os.path.exists(performance_config.MailPicConfig.attach_path):
+ os.remove(performance_config.MailPicConfig.attach_path)
+ if not os.path.exists(performance_config.MailPicConfig.mail_data_path):
+ os.mkdir(performance_config.MailPicConfig.mail_data_path)
+ for build_mode in range(2):
+ for build_type in range(2):
+ pic_path = MailHelper.find_in_double_map(build_mode,
+ build_type,
+ performance_config.MailPicConfig.mail_pic_name,
+ "mail_pic_name")
+ if not pic_path:
+ return
+ if os.path.exists(pic_path):
+ os.remove(pic_path)
+
+ def create(self, prj_name):
+ self.pic_table[prj_name] = {
+ performance_config.BuildMode.DEBUG:[np.nan, np.nan],
+ performance_config.BuildMode.RELEASE:[np.nan, np.nan]
+ }
+ self.head_line.append(prj_name)
+ self.current_add_prj = prj_name
+ self.time_index = [time.strftime("%Y/%m/%d", time.localtime())]
+
+ @staticmethod
+ def find_in_double_map(key_1, key_2, double_dic, error_table_name):
+ it_1 = double_dic.get(key_1)
+ if it_1:
+ it_2 = it_1.get(key_2)
+ if not it_2:
+ print(f"Can not find key_2: {key_2} in {error_table_name}, please check")
+ return it_2
+ else:
+ print(f"Can not find key_1: {key_1} in {error_table_name}, please check")
+ return it_1
+
+ def add_msg(self, msg):
+ self.mail_msg += msg
+
+ def add_logs_file(self, filename, buffer):
+ self.logs_file[filename] = buffer
+
+ def add_pic_data(self, is_debug, time_list):
+ build_type = performance_config.BuildMode.DEBUG if is_debug else performance_config.BuildMode.RELEASE
+ prj_table = self.pic_table.get(self.current_add_prj)
+ if prj_table:
+ prj_table.update({build_type: time_list})
+ else:
+ print(f"Can not find {self.current_add_prj} in pic_table, please check")
+
+ def create_msg_file(self):
+ with os.fdopen(
+ os.open(performance_config.MailPicConfig.html_file_path,
+ os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
+ stat.S_IRWXU | stat.S_IRWXO | stat.S_IRWXG),
+ 'w'
+ ) as msg_file:
+ msg_file.write(self.mail_msg + performance_config.get_html_suffix())
+
+ def create_logs_file(self):
+ mail_zip = zipfile.ZipFile(performance_config.MailPicConfig.attach_path, 'w')
+ for file in self.logs_file:
+ mail_zip.writestr(file, self.logs_file.get(file))
+ mail_zip.close()
+
+ def create_pic(self):
+ for build_mode in range(2):
+ for build_type in range(2):
+ title_name = MailHelper.find_in_double_map(build_mode,
+ build_type,
+ performance_config.MailPicConfig.mail_pic_table_lable,
+ "mail_pic_table_lable")
+ if not title_name:
+ continue
+ pic_name = MailHelper.find_in_double_map(build_mode,
+ build_type,
+ performance_config.MailPicConfig.mail_pic_name,
+ "mail_pic_name")
+ if not pic_name:
+ continue
+ df = None
+ csv_filename = MailHelper.find_in_double_map(build_mode,
+ build_type,
+ performance_config.MailPicConfig.mail_pic_table_name,
+ "pic_table_name")
+ if not csv_filename:
+ continue
+ if os.path.exists(csv_filename):
+ df = pd.read_csv(csv_filename, index_col=0)
+ else:
+ df = pd.DataFrame(columns=self.head_line)
+ dic = {}
+ for prj_name in self.pic_table:
+ dic[prj_name] = [self.pic_table[prj_name][build_mode][build_type]]
+ df_inserted = pd.DataFrame(dic, index=self.time_index)
+ df = df._append(df_inserted)
+ if len(df) > 5:
+ df = df[1:len(df)]
+ df.to_csv(csv_filename)
+ df.plot(
+ linestyle='-',
+ linewidth=2,
+ marker='o',
+ markersize=6,
+ markeredgecolor='black',
+ title=title_name,
+ ylabel='build time (s)',
+ grid=True
+ ).get_figure().savefig(pic_name)
+
+ def create_mail_files(self):
+ self.create_msg_file()
+ self.create_pic()
+ self.create_logs_file()
+
+
+class PerformanceEntry():
+ def __init__(self) -> None:
+ self.mail_helper = MailHelper()
+
+ def run(self):
+ self.init()
+ # You can control which project you need to test here, the first param is the key in performance_config.py
+ self.start_test("FDY")
+ self.start_test("FTB")
+ self.start_test("FWX")
+ os.chdir(os.path.dirname(__file__))
+ self.create_mail_files()
+
+ def start_test(self, index):
+ config = performance_config.get_config(index)
+ if not config:
+ return
+ self.mail_helper.create(os.path.basename(config.project_path))
+ performance_build.run(config, self.mail_helper)
+
+ def create_mail_files(self):
+ if performance_config.Config.send_mail:
+ self.mail_helper.create_mail_files()
+
+ def init(self):
+ self.mail_helper = MailHelper()
+
+
+if __name__ == '__main__':
+ strat_time = time.time()
+ PerformanceEntry().run()
+ print("All test finished at %s\ntotal cost: %ds"
+ % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), time.time() - strat_time))
\ No newline at end of file
diff --git a/test/scripts/send_email.py b/test/scripts/send_email.py
index 44cfdd000f8e43d98d45dd3dce49efee63d74b86..27243c19e4d63eda829a0cf6363191890fe03c65 100755
--- a/test/scripts/send_email.py
+++ b/test/scripts/send_email.py
@@ -17,9 +17,10 @@
import os
import smtplib
-import socket
-from email.message import EmailMessage
+from email.mime.image import MIMEImage
+from email.mime.multipart import MIMEMultipart
+from email.mime.text import MIMEText
import yaml
@@ -38,13 +39,25 @@ def add_content(content, file_name, test_part):
def add_attachment(msg, file_list):
for file in file_list:
if os.path.exists(file):
- with open(file, 'r', encoding='utf-8') as f:
- msg.add_attachment(f.read(), 'html', filename=os.path.basename(file))
+ with open(file, 'rb') as f:
+ attachment = MIMEText(f.read(), 'base64', 'utf-8')
+ attachment['Content-Disposition'] = f'attachment; filename="{os.path.basename(file)}"'
+ msg.attach(attachment)
+
+
+def add_image(msg, img_dic):
+ for path in img_dic:
+ if os.path.exists(path):
+ with open(path, 'rb') as f:
+ img = MIMEImage(f.read())
+ img.add_header('Content-ID', img_dic[path])
+ msg.attach(img)
def send_email():
yl = open(r".\email_config.yaml", 'r')
data = yaml.safe_load(yl.read())
+ user_name = data["user_name"]
sender = data["sender_email_address"]
auth_code = data["auth_code"]
receiver = data["receiver_list"]
@@ -54,9 +67,10 @@ def send_email():
sdk_test = data["sdk_report_file"]
perf_test = data["perf_report_file"]
attachment_files = data["attatchment_files"]
+ image_files = data["image_files"]
yl.close()
- msg = EmailMessage()
+ msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = ", ".join(receiver)
msg['Subject'] = "Arkcompiler Test"
@@ -68,12 +82,11 @@ def send_email():
html = add_content(html, sdk_test, "sdk_test")
html += dividing_line
html = add_content(html, perf_test, "perf_test")
- msg.add_related(html, "html")
-
+ msg.attach(MIMEText(html, 'html', 'utf-8'))
add_attachment(msg, attachment_files)
-
+ add_image(msg, image_files)
smtp = smtplib.SMTP(smtp_server, smtp_port)
- smtp.login(sender, auth_code)
+ smtp.login(user_name, auth_code)
smtp.sendmail(sender, receiver, msg.as_string())
smtp.quit()
diff --git a/test/scripts/timer.py b/test/scripts/timer.py
index f27fca80a3ca79c0324a821bc85453ffaa1f3532..82a593883f6f21784667bd33c997d58c90f3a5f3 100755
--- a/test/scripts/timer.py
+++ b/test/scripts/timer.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
-# Copyright (c) 2023 Huawei Device Co., Ltd.
+# Copyright (c) 0123 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
@@ -28,11 +28,14 @@ def job(cmd):
if __name__ == "__main__":
os.chdir(os.path.dirname(os.path.realpath(__file__)))
- #do preparations
- schedule.every().day.at("20:00").do(job, cmd=r'.\auto_xts_test\run.bat').tag('daily_xts_task')
- schedule.every().day.at("20:00").do(job, cmd=r'python .\sdk_test\entry.py').tag('daily_sdk_task')
- #do perf_test
- schedule.every().day.at("20:00").do(job, cmd=r'python .\send_email.py').tag("send_email")
+ # do preparations
+ schedule.every().day.at("01:00").do(job, cmd=r'./auto_xts_test/run.bat').tag('daily_xts_task')
+ # do sdk_test
+ schedule.every().day.at("01:00").do(job, cmd=r'python ./sdk_test/entry.py').tag('daily_sdk_task')
+ # do perf_test
+ schedule.every().day.at("01:00").do(job, cmd=r'python ./performance_test/performance_entry.py')
+ # send mail
+ schedule.every().day.at("01:00").do(job, cmd=r'python ./send_email.py').tag("send_email")
schedule.run_all()
while True:
schedule.run_pending()