1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright (C) 2025 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15import os 16import time 17import multiprocessing 18import logging 19import pytest 20 21from utils import GP, check_hdc_cmd, check_shell, check_version, get_shell_result, run_command_with_timeout, load_gp, \ 22 get_hdcd_pss, get_end_symbol 23 24 25logger = logging.getLogger(__name__) 26 27 28class TestShellHilog: 29 #子进程执行函数 30 @staticmethod 31 def new_process_run(cmd): 32 # 重定向 stdout 和 stderr 到 /dev/null 33 with open(os.devnull, 'w') as devnull: 34 old_stdout = os.dup2(devnull.fileno(), 1) # 重定向 stdout 35 old_stderr = os.dup2(devnull.fileno(), 2) # 重定向 stderr 36 try: 37 # 这里是子进程的代码,不会有任何输出到控制台 38 check_shell(f'{cmd}') 39 finally: 40 # 恢复原始的 stdout 和 stderr 41 os.dup2(old_stdout, 1) 42 os.dup2(old_stderr, 2) 43 44 @pytest.mark.L0 45 def test_hilog_exit_after_hdc_kill(self): 46 # 新开进程执行hdc shell hilog,防止阻塞主进程 47 p = multiprocessing.Process(target=self.new_process_run, args=("shell hilog",)) 48 p.start() 49 time.sleep(1) 50 hilog_pid = get_shell_result(f'shell pidof hilog') 51 hilog_pid = hilog_pid.replace(get_end_symbol(), "") 52 assert hilog_pid.isdigit() 53 assert check_hdc_cmd("start") 54 assert check_hdc_cmd(f'-l5 kill -r', "Kill server finish") 55 time.sleep(3) # sleep 3s to wait for the device to connect channel 56 run_command_with_timeout(f"{GP.hdc_head} wait", 3) # wait 3s for the device to connect channel 57 hilog_pid2 = get_shell_result(f'shell pidof hilog') 58 assert hilog_pid2 == '' 59 p.join() 60 61 62class TestShellBundleOption: 63 pss = 0 64 a_long = "a" * 129 65 a_short = "a" * 8 66 data_storage_el2_path = "data/storage/el2/base" 67 test_bundle_fail_data = [ 68 ("bundle name unknown", "-b ""com.XXXX.not.exist.app", "pwd", "[Fail][E003001]"), 69 ("bundle name with path ../", "-b ""../../../../", "pwd", "[Fail][E003001]"), 70 ("bundle name with path ./", "-b ""././././pwd", "pwd", "[Fail][E003001]"), 71 ("bundle name with path /", "-b ""/", "pwd", "[Fail][E003001]"), 72 ("bundle name without command", "-b "f"{GP.debug_app}", "", "[Fail][E003002]"), 73 ("bundle name too long: length > 128", f"-b {a_long}", "pwd", "[Fail][E003001]"), 74 ("bundle name too short: length < 9", f"-b {a_short}", "pwd", "[Fail][E003001]"), 75 ("bundle name with unsupport symbol: #", "-b #########", "pwd", "[Fail][E003001]"), 76 ("option: -param", "-param 1234567890", "pwd", "[Fail][E003003]"), 77 ("option: -basd", "-basd {GP.debug_app}", "pwd", "[Fail][E003003]"), 78 ("parameter missing", "- {GP.debug_app}", "ls", "[Fail][E003003]"), 79 ("bundle name missing", "-b", "ls", "[Fail][E003001]"), 80 ("bundle name & command missing", "-b", "", "[Fail][E003005]"), 81 ("option: -t -b", "-t -b {GP.debug_app}", "ls", "[Fail][E003003]"), 82 ("command with similar parameter: ls -b", "ls -b {GP.debug_app}", "", "No such file or directory"), 83 ("option: -b -b", "-b -b {GP.debug_app}", "ls", "[Fail][E003001]"), 84 ("option: --b", "--b {GP.debug_app}", "", "[Fail][E003003]"), 85 ] 86 87 test_bundle_normal_data = [ 88 ("mkdir", f"shell mkdir -p mnt/debug/100/debug_hap/{GP.debug_app}/{data_storage_el2_path}", None, True), 89 ("pwd", f"shell -b {GP.debug_app} pwd", f"mnt/debug/100/debug_hap/{GP.debug_app}", True), 90 ("cd_pwd", f"shell -b {GP.debug_app} cd {data_storage_el2_path}; pwd", 91 f"mnt/debug/100/debug_hap/{GP.debug_app}/{data_storage_el2_path}", True), 92 ("touch", f"shell -b {GP.debug_app} touch {data_storage_el2_path}/test01", None, True), 93 ("touch_denied", f"shell -b {GP.debug_app} touch {data_storage_el2_path}/test01", "denied", False), 94 ("touch_a_denied", f"shell -b {GP.debug_app} touch -a {data_storage_el2_path}/test01", "denied", False), 95 ("ls_test01", f"shell -b {GP.debug_app} ls {data_storage_el2_path}/", "test01", True), 96 ("echo_123", f"shell -b {GP.debug_app} echo 123", "123", True), 97 ("echo_to_test02", f"shell -b {GP.debug_app} \"echo 123 > {data_storage_el2_path}/test02\"", None, True), 98 ("cat_test02", f"shell -b {GP.debug_app} cat {data_storage_el2_path}/test02", "123", True), 99 ("mkdir_test03", f"shell -b {GP.debug_app} mkdir {data_storage_el2_path}/test03", None, True), 100 ("stat_test03", f"shell -b {GP.debug_app} stat {data_storage_el2_path}/test03", "Access", True), 101 ("rm_rf", f"shell -b {GP.debug_app} rm -rf {data_storage_el2_path}/test01 " 102 f"{data_storage_el2_path}/test02 {data_storage_el2_path}/test03", None, True), 103 ("ls_test01_not_exist", f"shell -b {GP.debug_app} ls {data_storage_el2_path}/test01", 104 "test01: No such file or directory", True), 105 ("ls_test02_not_exist", f"shell -b {GP.debug_app} ls {data_storage_el2_path}/test02", 106 "test02: No such file or directory", True), 107 ("ls_test03_not_exist", f"shell -b {GP.debug_app} ls {data_storage_el2_path}/test03", 108 "test03: No such file or directory", True), 109 ] 110 111 def setup_class(self): 112 data_storage_el2_path = "data/storage/el2/base" 113 check_shell(f"shell mkdir -p mnt/debug/100/debug_hap/{GP.debug_app}/{data_storage_el2_path}") 114 check_shell(f"shell rm -rf -p mnt/debug/100/debug_hap/{GP.debug_app}/{data_storage_el2_path}/it_*") 115 self.pss = get_hdcd_pss() 116 if self.pss == 0: 117 logger.error("get hdcd mem pss failed") 118 119 120 @pytest.mark.L0 121 @check_version("Ver: 3.1.0e") 122 @pytest.mark.parametrize("test_name, bundle_option, command, expected_output", test_bundle_fail_data, 123 ids=[name for name, _, _, _ in test_bundle_fail_data]) 124 def test_bundle_option_error(self, test_name, bundle_option, command, expected_output): 125 test_command = f"shell {bundle_option} {command}" 126 assert check_shell(test_command, expected_output) 127 128 @pytest.mark.L0 129 @check_version("Ver: 3.1.0e") 130 @pytest.mark.parametrize("test_name, command, expected_output, assert_bool", test_bundle_normal_data, 131 ids=[name for name, _, _, _ in test_bundle_normal_data]) 132 def test_shell_option_bundle_normal(self, test_name, command, expected_output, assert_bool): 133 if assert_bool: 134 assert check_shell(f"{command}", expected_output) 135 else: 136 assert not check_shell(f"{command}", expected_output) 137 138 @pytest.mark.L0 139 @check_version("Ver: 3.1.0e") 140 def test_shell_pss_leak(self): 141 pss_now = get_hdcd_pss() 142 if self.pss == 0 or pss_now == 0: 143 logger.error("get hdcd mem pss failed") 144 assert False 145 if pss_now > (self.pss + 50): 146 logger.warning("hdcd mem pss leak, original value %d, now value %d", self.pss, pss_now) 147 assert False 148 149 150class TestShellNormalFuction: 151 end_symbol_data = get_end_symbol() 152 test_bundle_fail_data = [ 153 ("shell echo test1", "shell echo test", f"test{end_symbol_data}", True), 154 ("shell echo test2", "shell echo 测试", f"测试{end_symbol_data}", True), 155 ("shell echo test3", "shell echo test 测试", f"test 测试{end_symbol_data}", True), 156 ] 157 158 @pytest.mark.L0 159 @pytest.mark.parametrize("test_name, command, expected_output, assert_bool", test_bundle_fail_data, 160 ids=[name for name, _, _, _ in test_bundle_fail_data]) 161 def test_shell_end(self, test_name, command, expected_output, assert_bool): 162 if assert_bool: 163 assert check_shell(f"{command}", expected_output) 164 else: 165 assert not check_shell(f"{command}", expected_output)