• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)