提交 c2c469f6 编写于 作者: M mamingshuai

update openharmony 1.0.1

上级 9d2c8093
### 该问题是怎么引起的?
### 重现步骤
### 报错信息
### 相关的Issue
### 原因(目的、解决的问题等)
### 描述(做了什么,变更了什么)
### 测试用例(新增、改动、可能影响的功能)
*.pyc
/extension/
\ No newline at end of file
# Copyright (c) 2020 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("//test/xts/tools/build/suite_lite.gni")
deploy_suite("xdevice"){
suite_name = "acts"
# Copyright (c) 2020 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("//test/xts/tools/lite/build/suite_lite.gni")
deploy_suite("xdevice") {
suite_name = "acts,hits,ssts"
}
文件模式从 100755 更改为 100644
# XDevice<a name="EN-US_TOPIC_0000001083129731"></a>
- [Introduction](#section15701932113019)
- [Directory Structure](#section1791423143211)
- [Constraints](#section118067583303)
- [Usage](#section2036431583)
- [Repositories Involved](#section260848241)
## Introduction<a name="section15701932113019"></a>
XDevice, a core module of the OpenHarmony test framework, provides services on which test case execution depends.
XDevice consists of the following sub-modules:
- **command**: enables command-based interactions between users and the test platform. It parses and processes user commands.
- **config**: sets test framework configurations and provides different configuration options for the serial port connection and USB connection modes.
- **driver**: functions as a test case executor, which defines main test steps, such as test case distribution, execution, and result collection.
- **report**: parses test results and generates test reports.
- **scheduler**: schedules various test case executors in the test framework.
- **environment**: configures the test framework environment, enabling device discovery and device management.
- **testkit**: provides test tools to implement JSON parsing, network file mounting, etc.
- **resource**: provides the device connection configuration file and report template definitions.
- **adapter**: adapts the test framework to open-source software.
## Directory Structure<a name="section1791423143211"></a>
```
xdevice
├── config # XDevice configuration
│ ├── user_config.xml # XDevice environment configuration
├── resource # XDevice resources
│ ├── tools # Burning tools
├── src # Source code
│ ├── xdevice
├── extension # XDevice extension
│ ├── src # Source code of the extension
│ └── setup.py # Installation script of the extension
```
## Constraints<a name="section118067583303"></a>
The environment requirements for using this module are as follows:
- Python version: 3.7.5 or later
- pySerial version: 3.3 or later
- Paramiko version: 2.7.1 or later
- RSA version: 4.0 or later
## Usage<a name="section2036431583"></a>
- **Installing XDevice**
1. Go to the installation directory of XDevice.
2. Open the console window and run the following command:
```
python setup.py install
```
- **Installing the extension**
1. Go to the installation directory of the XDevice extension.
2. Open the console and run the following command:
```
python setup.py install
```
- **Modifying the user\_config.xml file**
Configure information about your environment in the **user\_config.xml** file.
**1. Configure the environment.**
- For devices that support hdc connection, refer to the following note to configure the environment.
>![](figures/icon-note.gif) **NOTE:**
>**ip/port**: IP address and port of a remote device. By default, the parameter is left blank, indicating that the local device \(IP address: 127.0.0.1; port: the one used for hdc startup\) is used as the test device.
>**sn**: SN of the test devices specified for command execution. If this parameter is set to **SN1**, only device SN1 can execute the subsequent **run** commands. In this case, other devices are set as **Ignored** and not involved in the command execution. You can run the **list devices** command and check the value of **Allocation** to view the **sn** values. You can set multiple SNs and separate each two of them with a semicolon \(;\).
- For devices that support serial port connection, refer to the following note to configure the environment.
>![](figures/icon-note.gif) **NOTE:**
>**type**: device connection mode. The **com** mode indicates that the device is connected through the serial port.
>**label**: device type, for example, **wifiiot**
>**serial**: serial port
>- **serial/com**: serial port for local connection, for example, **COM20**
>- **serial/type**: serial port type. The value can be **cmd** \(serial port for test case execution\) or **deploy** \(serial port for system upgrade\).
> For the open-source project, the **cmd** and **deploy** serial ports are the same, and their **com** values are the same too.
>**serial/baud\_rate, data\_bits, stop\_bits** and **timeout**: serial port parameters. You can use the default values.
**2. Set the test case directory.**
**dir**: test case directory
**3. Mount the NFS.**
>![](figures/icon-note.gif) **NOTE:**
>**server**: NFS mounting configuration. Set the value to **NfsServer**.
>**server/ip**: IP address of the mounting environment
>**server/port**: port number of the mounting environment
>**server/username**: user name for logging in to the server
>**server/password**: password for logging in to the server
>**server/dir**: external mount path
>**server/remote**: whether the NFS server and the XDevice executor are deployed on different devices. If yes, set this parameter to **true**. Otherwise, set it to **false**.
- **Specify the task type.**
- **Start the test framework.**
- **Execute test commands.**
Test framework commands can be classified into three groups: **help**, **list**, and **run**. Among them, **run** commands are most commonly used in the instruction sequence.
**help**
Queries help information about test framework commands.
```
help:
Use help to get information.
usage:
run: Display a list of supported run commands.
list: Display a list of supported devices and task records.
Examples:
help run
help list
```
>![](figures/icon-note.gif) **NOTE:**
>**help run**: displays the description of **run** commands.
>**help list**: displays the description of **list** commands.
**list**
Displays device information and related task information.
```
list:
Display device list and task records.
usage:
list
list history
list <id>
Introduction:
list: Display the device list.
list history: Display historical records of a series of tasks.
list <id>: Display historical records of tasks with the specified IDs.
Examples:
list
list history
list 6e****90
```
>![](figures/icon-note.gif) **NOTE:**
>**list**: displays device information.
>**list history**: displays historical task information.
>**list <id\>**: displays historical information about tasks with specified IDs.
**run**
Executes test tasks.
```
run:
Execute the selected test cases.
The command execution process includes use case compilation, execution, and result collection.
usage: run [-l TESTLIST [TESTLIST ...] | -tf TESTFILE
[TESTFILE ...]] [-tc TESTCASE] [-c CONFIG] [-sn DEVICE_SN]
[-rp REPORT_PATH [REPORT_PATH ...]]
[-respath RESOURCE_PATH [RESOURCE_PATH ...]]
[-tcpath TESTCASES_PATH [TESTCASES_PATH ...]]
[-ta TESTARGS [TESTARGS ...]] [-pt]
[-env TEST_ENVIRONMENT [TEST_ENVIRONMENT ...]]
[-e EXECTYPE] [-t [TESTTYPE [TESTTYPE ...]]]
[-td TESTDRIVER] [-tl TESTLEVEL] [-bv BUILD_VARIANT]
[-cov COVERAGE] [--retry RETRY] [--session SESSION]
[--dryrun] [--reboot-per-module] [--check-device]
[--repeat REPEAT]
action task
Specify tests to run.
positional arguments:
action Specify the action to do.
task Specify the task name, such as ssts, acts, and hits.
```
>![](figures/icon-note.gif) **NOTE:**
>The structure of a basic **run** command is as follows:
>```
>run [task name] -l module1;moudle2
>```
>**task name**: task type. This parameter is optional. Generally, the value is **ssts**, **acts**, or **hits**.
>**-l**: test cases to execute. Use semicolons \(;\) to separate each two test cases.
>**module**: module to test. Generally, there is a **.json** file of the module in the **testcases** directory.
>In addition, other parameters can be attached to this command as constraints. Common parameters are as follows:
>**-sn**: specifies the devices for test case execution. If this parameter is set to **SN1**, only device SN1 executes the test cases.
>**-c**: specifies a new **user\_config.xml** file.
>**-rp**: indicates the path where the report is generated. The default directory is **xxx/xdevice/reports**. Priority of a specified directory is higher than that of the default one.
>**-tcpath**: indicates the environment directory, which is **xxx/xdevice/testcases** by default. Priority of a specified directory is higher than that of the default one.
>**-respath**: indicates the test suite directory, which is **xxx/xdevice/resource** by default. Priority of a specified directory is higher than that of the default one.
>**--reboot-per-module**: restarts the device before test case execution.
- **View the execution result.**
After executing the **run** commands, the test framework displays the corresponding logs on the console, and generates the execution report in the directory specified by the **-rp** parameter. If the parameter is not set, the report will be generated in the default directory.
```
Structure of the report directory (the default or the specified one)
├── result # Test case execution results of the module
│ ├── module name.xml
│ ├── ...
├── log # Running logs of devices and tasks
│ ├── device 1.log
│ ├── ...
│ ├── task.log
├── summary_report.html # Visual report
├── summary_report.html # Statistical report
└── ...
```
## Repositories Involved<a name="section260848241"></a>
test\_xdevice
test\_xdevice\_extension
# xdevice组件<a name="ZH-CN_TOPIC_0000001083129731"></a>
- [简介](#section15701932113019)
- [目录](#section1791423143211)
- [约束](#section118067583303)
- [使用](#section2036431583)
- [相关仓](#section260848241)
## 简介<a name="section15701932113019"></a>
xdevice是OpenHarmony中为测试框架的核心组件,提供用例执行所依赖的相关服务。
xdevice主要包括以下几个主要模块:
- command,用户与测试平台命令行交互模块,提供用户输入命令解析,命令处理。
- config,测试框架配置模块,提供测试平台串口连接方式和USB连接方式的不同配置选项。
- driver,测试用例执行器,提供测试用例分发,执行,结果收集等主要测试步骤定义。
- report,测试报告模块,提供测试结果解析和测试报告生成。
- scheduler,测试框架调度模块,提供不同类型的测试执行器调度的调度功能。
- environment,测试框架的环境配置模块,提供设备发现,设备管理的功能。
- testkit,测试框架工具模块,提供json解析,网络文件挂载等操作。
- resource,测试框架资源模块,提供设备连接配置文件和报告模板定义。
- adapter,测试框架适配开源软件的模块。
## 目录<a name="section1791423143211"></a>
```
xdevice
├── config # xdevice组件配置
│ ├── user_config.xml # xdevice环境配置
├── resource # xdevice组件资源
│ ├── tools # 版本烧录工具
├── src # 组件源码目录
│ ├── xdevice
├── extension # xdevice扩展模块
│ ├── src # 扩展模块源码
│ └── setup.py # xdevice扩展模块安装脚本
```
## 约束<a name="section118067583303"></a>
运行环境要求:
- python版本\>=3.7.5
- pyserial\>=3.3
- paramiko\>=2.7.1
- rsa\>=4.0
## 使用<a name="section2036431583"></a>
- **安装xdevice**
1. 打开xdevice安装目录。
2. 打开控制台,执行如下命令:
```
python setup.py install
```
- **安装extension**
1. 打开extension安装目录。
2. 打开控制台,执行如下命令:
```
python setup.py install
```
- **修改user\_config.xml**
user\_config.xml是框架提供的用户配置文件,用户可以根据自身环境信息配置相关内容,具体介绍如下:
**1、environment环境相关配置:**
- 设备类型一
>![](figures/icon-note.gif) **说明:**
>ip/port: 表示远程设备地址,默认情况为空,表示使用本地设备,ip地址为127.0.0.1,port为本机hdc启动端口号;
>​sn: 过滤执行测试设备,若设置为SN1,则表示只有设备SN1能够支持后续run命令执行,其他设备分配状态设置为Ignored,不参与命令执行,可通过list devices命令中Allocation字段来查看sn设置,可配置多个sn,中间以;隔开;
- 设备类型二
>![](figures/icon-note.gif) **说明:**
>type: 设备连接方式,com表示连接方式是串口
>label: 表示设备种类,如wifiiot
>serial: 表示一个串口定义
>serial/com 表示本地连接的串口,如COM20 serial/type 表示串口类型,cmd是命令串口,deploy是刷机串口,社区版本cmd和deploy使用同一个串口,com值相同
>serial/baud\_rate、data\_bits、stop\_bits、timeout: 为串口波特率等串口参数 ,一般采用默认值即可。
**2、测试用例目录设置**
dir: 指定测试用例目录。
**3、nfs挂载**
>![](figures/icon-note.gif) **说明:**
>server: nfs挂载配置,label取值为NfsServer。
>server/ip: 挂载环境IP地址。
>server/port: 挂载环境端口。
>server/username: 登录用户名。
>server/password: 登录用户密码。
>server/dir: 对应挂载的外部路径。
>server/remote: nfs服务器与xDevice执行机不在同一台机器时,remote配置为true,否则为false。
- **选定任务类型**
- **启动框架**
- **执行指令**
框架指令可以分为三组:help、list、run。在指令序列中,以run为最常用的执行指令。
**1、help**
输入help指令可以查询框架指令帮助信息。
```
help:
use help to get information.
usage:
run: Display a list of supported run command.
list: Display a list of supported device and task record.
Examples:
help run
help list
```
>![](figures/icon-note.gif) **说明:**
>help run:展示run指令相关说明
>help list:展示 list指令相关说明
**2、list**
list指令用来展示设备和相关的任务信息
```
list:
This command is used to display device list and task record.
usage:
list
list history
list <id>
Introduction:
list: display device list
list history: display history record of a serial of tasks
list <id>: display history record about task what contains specific id
Examples:
list
list history
list 6e****90
```
>![](figures/icon-note.gif) **说明:**
>list: 展示设备信息
>list history: 展示任务历史信息
>list <id\>: 展示特定id的任务其历史信息
**3、run**
run指令主要用于执行测试任务
```
run:
This command is used to execute the selected testcases.
It includes a series of processes such as use case compilation, execution, and result collection.
usage: run [-l TESTLIST [TESTLIST ...] | -tf TESTFILE
[TESTFILE ...]] [-tc TESTCASE] [-c CONFIG] [-sn DEVICE_SN]
[-rp REPORT_PATH [REPORT_PATH ...]]
[-respath RESOURCE_PATH [RESOURCE_PATH ...]]
[-tcpath TESTCASES_PATH [TESTCASES_PATH ...]]
[-ta TESTARGS [TESTARGS ...]] [-pt]
[-env TEST_ENVIRONMENT [TEST_ENVIRONMENT ...]]
[-e EXECTYPE] [-t [TESTTYPE [TESTTYPE ...]]]
[-td TESTDRIVER] [-tl TESTLEVEL] [-bv BUILD_VARIANT]
[-cov COVERAGE] [--retry RETRY] [--session SESSION]
[--dryrun] [--reboot-per-module] [--check-device]
[--repeat REPEAT]
action task
Specify tests to run.
positional arguments:
action Specify action
task Specify task name,such as "ssts", "acts", "hits"
```
>![](figures/icon-note.gif) **说明:**
>一个基本的run指令结构如下:
>```
>run [task name] -l module1;moudle2
>```
>task name:任务类型。一般为ssts、acts、hits。非必选项
>-l :指定执行测试用例,多个测试用例,中间用;隔开
>module:被测试的模块。一般在testcases目录下存在对应的\\.json文件
>此外,其他参数可以作为约束条件,附加到这个基本指令之上使用。常用的如:
>-sn: 过滤执行测试设备,若设置为SN1,则表示只有设备SN1执行用例
>-c: 重新指定user\_config.xml。
>-rp: 报告生成路径。默认为xxx/xdevice/reports目录。指定目录后,优先级:指定目录\>xxx/xdevice/reports目录。
>-tcpath:环境目录,默认为xxx/xdevice/testcases目录。指定目录后,优先级:指定目录\>xxx/xdevice/testcases目录
>-respath:测试套目录,默认为xxx/xdevice/resource目录。指定目录后,优先级:指定目录\>xxx/xdevice/resource目录
>--reboot-per-module: 执行前先重启设备
- **查看执行结果**
框架执行run指令,控制台会输出对应的log打印,还会生成对应的执行结果报告。如果使用了-rp参数指定报告路径,那么报告就会生成在指定的路径下。否则报告会存放在默认目录。
```
当前报告目录(默认目录/指定目录)
├── result(模块执行结果存放目录)
│ ├── <模块名>.xml
│ ├── ... ...
├── log (设备和任务运行log存放目录)
│ ├── <设备1>.log
│ ├── ... ...
│ ├── <任务>.log
├── summary_report.html(测试任务可视化报告)
├── summary_report.html(测试任务数据化报告)
└── ... ...
```
## 相关仓<a name="section260848241"></a>
test\_xdevice
test\_xdevice\_extension
Copyright (c) 2021 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.
***************************************************************
Copyright (C) 2011 The Android Open Source Project
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
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.
\ No newline at end of file
#!/usr/bin/env python3
# coding=utf-8
#
# Copyright (c) 2021 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.
#
#!/usr/bin/env python3
# coding=utf-8
#
# Copyright (c) 2021 Huawei Device Co., Ltd.
# Copyright (c) 2013 The Android Open Source Project
# 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.
#
from dataclasses import dataclass
__all__ = ["UsbConst", "AppConst"]
@dataclass
class UsbConst:
connector = "adb"
connector_type = "usb-adb"
push = "adb push"
pull = "adb pull"
shell = "adb shell"
server_port = "ANDROID_ADB_SERVER_PORT"
kill_server = "adb kill-server"
start_server = "adb start-server"
reboot = "adb reboot"
@dataclass
class AppConst:
entry_app = "Entry.apk"
app_ext = ".apk"
app_name = "APK"
wifi_app = "xDeviceService-wifi.apk"
......@@ -11,6 +11,12 @@
}
],
"query" : "/test_root/tools/query.bin"
},
{
"type": "RootFsKit",
"command": "./bin/checksum /bin",
"hash_file_name": "checksum.hash",
"device_label": "ipcamera"
}
]
}
{
"description": "Config for hits test suites",
"kits": [
{
"type": "QueryKit",
"server": "NfsServer",
"mount": [
{
"source": "resource/tools/query.bin",
"target": "/test_root/tools"
}
],
"query" : "/test_root/tools/query.bin"
}
]
}
{
"description": "Runs a STS plan from a pre-existing STS installation",
"kits": [
{
"type": "QueryKit",
"server": "NfsServer",
"mount": [
{
"source": "resource/tools/query.bin",
"target": "/test_root/tools"
}
],
"query" : "/test_root/tools/query.bin",
"properties": {
"version": "",
"spt": ""
}
}
]
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2020 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
......@@ -15,14 +15,12 @@
-->
<user_config>
<environment>
<support_device>
<device_lite>true</device_lite>
</support_device>
<device type="com" label="wifiiot">
<device type="com"
label="wifiiot">
<serial>
<com></com>
<type>cmd</type>
<baund_rate>115200</baund_rate>
<baud_rate>115200</baud_rate>
<data_bits>8</data_bits>
<stop_bits>1</stop_bits>
<timeout>20</timeout>
......@@ -30,20 +28,22 @@
<serial>
<com></com>
<type>deploy</type>
<baund_rate>115200</baund_rate>
<baud_rate>115200</baud_rate>
</serial>
</device>
<device type="com" label="ipcamera">
<device type="com"
label="ipcamera">
<serial>
<com></com>
<type>cmd</type>
<baund_rate>115200</baund_rate>
<baud_rate>115200</baud_rate>
<data_bits>8</data_bits>
<stop_bits>1</stop_bits>
<timeout>1</timeout>
</serial>
</device>
<device type="com" label="ipcamera">
<device type="com"
label="ipcamera">
<ip></ip>
<port></port>
</device>
......@@ -62,4 +62,5 @@
<resource>
<dir></dir>
</resource>
<loglevel>INFO</loglevel>
</user_config>
# Copyright (c) 2020 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("//test/xts/tools/lite/build/suite_lite.gni")
deploy_suite("xdevice") {
suite_name = "acts"
}
详见:https://gitee.com/openharmony/docs/blob/master/readme/测试子系统README.md
see: https://gitee.com/openharmony/docs/blob/master/docs-en/readme/testing-subsystem.md
@rem Copyright (c) 2020-2021 Huawei Device Co., Ltd.
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem http://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@echo off
set BASE_DIR=%~dp0
set PYTHON=python
......@@ -6,12 +19,14 @@ cd /d %BASE_DIR%
(where %PYTHON% | findstr %PYTHON%) >nul 2>&1 || (
@echo "Python3.7 or higher version required!"
pause
goto:eof
)
python -c "import sys; exit(1) if sys.version_info.major < 3 or sys.version_info.minor < 7 else exit(0)"
@if errorlevel 1 (
@echo "Python3.7 or higher version required!"
pause
goto:eof
)
......@@ -32,4 +47,10 @@ for %%a in (%TOOLS%/*.egg) do (
@echo "Error occurs to install %%a!"
)
)
for %%a in (%TOOLS%/*.tar.gz) do (
python -m easy_install --user %TOOLS%/%%a
@if errorlevel 1 (
@echo "Error occurs to install %%a!"
)
)
python -m xdevice %*
#!/usr/bin/env sh
# Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
#
# Copyright (c) 2020-2021 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.
#
error()
{
......@@ -31,4 +44,12 @@ do
$PYTHON -m easy_install --user "$f" || echo "Error occurs to install $f!"
done
for f in "$TOOLS"/*.tar.gz
do
if [ ! -e "$f" ]; then
error "Can not find xdevice package!"
fi
$PYTHON -m easy_install --user "$f" || echo "Error occurs to install $f!"
done
$PYTHON -m xdevice "$@"
......@@ -18,12 +18,14 @@
from setuptools import setup
INSTALL_REQUIRES = []
def main():
setup(name='xdevice',
description='xdevice test framework',
url='',
package_dir={'': 'src'},
package_dir={'': 'src', 'adapter': 'adapter'},
packages=['xdevice',
'xdevice._core',
'xdevice._core.build',
......@@ -33,7 +35,8 @@ def main():
'xdevice._core.environment',
'xdevice._core.executor',
'xdevice._core.report',
'xdevice._core.testkit'
'xdevice._core.testkit',
'adapter.xdevice_adapter',
],
package_data={
'xdevice._core': [
......@@ -49,6 +52,7 @@ def main():
]
},
zip_safe=False,
install_requires=INSTALL_REQUIRES,
)
......
......@@ -2,7 +2,7 @@
# coding=utf-8
#
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Copyright (c) 2020-2021 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
......@@ -30,6 +30,7 @@ from _core.interface import LifeCycle
from _core.interface import IShellReceiver
from _core.interface import ITestKit
from _core.interface import IListener
from _core.interface import IReporter
from _core.exception import ParamError
from _core.exception import DeviceError
from _core.exception import LiteDeviceError
......@@ -40,7 +41,9 @@ from _core.constants import DeviceLabelType
from _core.constants import ManagerType
from _core.constants import DeviceOsType
from _core.constants import ProductForm
from _core.constants import TestType
from _core.constants import CKit
from _core.constants import ConfigConst
from _core.config.config_manager import UserConfigManager
from _core.config.resource_manager import ResourceManager
from _core.executor.listener import CaseResult
......@@ -57,11 +60,17 @@ from _core.utils import get_device_log_file
from _core.utils import get_kit_instances
from _core.utils import get_config_value
from _core.utils import exec_cmd
from _core.utils import check_device_name
from _core.utils import do_module_kit_setup
from _core.utils import do_module_kit_teardown
from _core.environment.manager_env import DeviceSelectionOption
from _core.environment.manager_env import EnvironmentManager
from _core.executor.scheduler import Scheduler
from _core.report.suite_reporter import SuiteReporter
from _core.report.suite_reporter import ResultCode
from _core.report.reporter_helper import ExecInfo
from _core.report.result_reporter import ResultReporter
from _core.report.__main__ import main_report
from _core.command.console import Console
__all__ = [
......@@ -78,6 +87,7 @@ __all__ = [
"IShellReceiver",
"ITestKit",
"IListener",
"IReporter",
"ParamError",
"DeviceError",
"LiteDeviceError",
......@@ -88,7 +98,9 @@ __all__ = [
"ManagerType",
"DeviceOsType",
"ProductForm",
"TestType",
"CKit",
"ConfigConst",
"UserConfigManager",
"ResourceManager",
"CaseResult",
......@@ -109,13 +121,20 @@ __all__ = [
"get_device_log_file",
"get_kit_instances",
"get_config_value",
"exec_cmd"
"exec_cmd",
"check_device_name",
"do_module_kit_setup",
"do_module_kit_teardown",
"ExecInfo",
"ResultReporter",
"main_report"
]
def _load_external_plugins():
plugins = [Plugin.SCHEDULER, Plugin.DRIVER, Plugin.DEVICE, Plugin.LOG,
Plugin.PARSER, Plugin.LISTENER, Plugin.TEST_KIT, Plugin.MANAGER]
Plugin.PARSER, Plugin.LISTENER, Plugin.TEST_KIT, Plugin.MANAGER,
Plugin.REPORTER]
for plugin_group in plugins:
for entry_point in pkg_resources.iter_entry_points(group=plugin_group):
entry_point.load()
......
......@@ -2,7 +2,7 @@
# coding=utf-8
#
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Copyright (c) 2020-2021 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
......
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
......@@ -2,7 +2,7 @@
# coding=utf-8
#
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Copyright (c) 2020-2021 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
......@@ -22,6 +22,9 @@ from dataclasses import dataclass
from _core.exception import ParamError
from _core.logger import platform_logger
from _core.utils import get_local_ip
from xdevice_adapter.constants import UsbConst
__all__ = ["UserConfigManager"]
LOG = platform_logger("ConfigManager")
......@@ -35,11 +38,12 @@ class ConfigFileConst(object):
class UserConfigManager(object):
def __init__(self, config_file="", env=""):
from xdevice import Variables
if config_file:
pass
try:
if env:
self.config_content = ET.fromstring(env)
else:
if config_file:
self.file_path = config_file
else:
user_path = os.path.join(Variables.exec_dir, "config")
top_user_path = os.path.join(Variables.top_dir, "config")
......@@ -53,19 +57,23 @@ class UserConfigManager(object):
path, ConfigFileConst.userconfig_filepath))
break
LOG.debug("user config path: %s" % self.file_path)
if os.path.exists(self.file_path):
tree = ET.parse(self.file_path)
self.config_content = tree.getroot()
else:
raise ParamError("config file not found")
raise ParamError("%s not found" % self.file_path,
error_no="00115")
except SyntaxError as error:
if env:
raise ParamError(
"Parse environment parameter fail! Error: %s" % error.args)
"Parse environment parameter fail! Error: %s" % error.args,
error_no="00115")
else:
raise ParamError(
"Parse %s fail! Error: %s" % (self.file_path, error.args))
"Parse %s fail! Error: %s" % (self.file_path, error.args),
error_no="00115")
def get_user_config_list(self, tag_name):
data_dic = {}
......@@ -94,18 +102,10 @@ class UserConfigManager(object):
return []
return config_list
def get_sn_list(self):
def get_sn_list(self, input_string):
sn_select_list = []
data_dic = {}
for node in self.config_content.findall("environment/device"):
if node.attrib["type"] != "usb-hdc":
continue
for sub in node:
data_dic[sub.tag] = sub.text if sub.text else ""
sn_config = data_dic.get("sn", "")
if sn_config:
sn_select_list = self._handle_str(sn_config)
break
if input_string:
sn_select_list = self._handle_str(input_string)
return sn_select_list
def get_remote_config(self):
......@@ -114,17 +114,18 @@ class UserConfigManager(object):
if "ip" in data_dic.keys() and "port" in data_dic.keys():
remote_ip = data_dic.get("ip", "")
remote_adb_port = data_dic.get("port", "")
remote_port = data_dic.get("port", "")
else:
remote_ip = ""
remote_adb_port = ""
remote_port = ""
if (not remote_ip) or (not remote_adb_port):
if (not remote_ip) or (not remote_port):
remote_ip = ""
remote_adb_port = ""
remote_port = ""
if remote_ip == get_local_ip():
remote_ip = "127.0.0.1"
remote_dic["ip"] = remote_ip
remote_dic["port"] = remote_adb_port
remote_dic["port"] = remote_port
return remote_dic
def get_testcases_dir_config(self):
......@@ -161,7 +162,7 @@ class UserConfigManager(object):
devices = []
for node in self.config_content.findall(target_name):
if node.attrib["type"] != "com":
if node.attrib["type"] != "com" and node.attrib["type"] != "agent":
continue
device = [node.attrib]
......@@ -172,6 +173,8 @@ class UserConfigManager(object):
if sub.text is not None and sub.tag != "serial":
data_dic[sub.tag] = sub.text
if data_dic:
if data_dic.get("ip", "") == get_local_ip():
data_dic["ip"] = "127.0.0.1"
device.append(data_dic)
devices.append(device)
continue
......@@ -189,18 +192,21 @@ class UserConfigManager(object):
return devices
def get_device(self, target_name):
data_dic = {}
for node in self.config_content.findall(target_name):
if node.attrib["type"] != "usb-hdc":
data_dic = {}
if node.attrib["type"] != "usb-hdc" and \
node.attrib["type"] != UsbConst.connector_type:
continue
data_dic["usb_type"] = node.attrib["type"]
for sub in node:
if sub.text is None:
data_dic[sub.tag] = ""
else:
data_dic[sub.tag] = sub.text
break
if data_dic.get("ip", "") == get_local_ip():
data_dic["ip"] = "127.0.0.1"
return data_dic
return None
def get_testcases_dir(self):
from xdevice import Variables
......@@ -226,3 +232,15 @@ class UserConfigManager(object):
return os.path.abspath(
os.path.join(Variables.exec_dir, "resource"))
def get_log_level(self):
data_dic = {}
node = self.config_content.find("loglevel")
if node is not None:
if node.find("console") is None and node.find("file") is None:
# neither loglevel/console nor loglevel/file exists
data_dic.update({"console": str(node.text).strip()})
else:
for child in node:
data_dic.update({child.tag: str(child.text).strip()})
return data_dic
......@@ -2,7 +2,7 @@
# coding=utf-8
#
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Copyright (c) 2020-2021 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
......@@ -110,9 +110,7 @@ class ResourceManager(object):
src = os.path.join(resource_dir, push_value[0:pos].strip())
dst = push_value[pos + len(find_key):len(push_value)].strip()
LOG.info("create_dir: dst = %s" % (dst))
device.execute_shell_command("mkdir -p %s" % dst)
LOG.info("push_file: src = %s, dst = %s" % (src, dst))
device.push_file(src, dst)
elif item["name"] == "pull":
push_value = item["value"]
......@@ -122,16 +120,13 @@ class ResourceManager(object):
src = os.path.join(resource_dir, push_value[0:pos].strip())
dst = push_value[pos + len(find_key):len(push_value)].strip()
LOG.info("pull_file: src = %s, dst = %s" % (src, dst))
device.pull_file(src, dst)
elif item["name"] == "shell":
command = item["value"].strip()
LOG.info("shell = %s", command)
device.execute_shell_command(command)
else:
command = "".join((item["name"], " ", item["value"]))
command = command.strip()
LOG.info("others = %s", command)
device.execute_command(command)
@staticmethod
......
......@@ -2,7 +2,7 @@
# coding=utf-8
#
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Copyright (c) 2020-2021 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
......@@ -22,7 +22,8 @@ __all__ = ["DeviceOsType", "ProductForm", "TestType", "TestExecType",
"DeviceTestType", "HostTestType", "HostDrivenTestType",
"SchedulerType", "ListenerType", "ToolCommandType",
"TEST_DRIVER_SET", "LogType", "ParserType", "CKit", "ComType",
"DeviceLabelType", "DeviceLiteKernel", "GTestConst", "ManagerType"]
"DeviceLabelType", "DeviceLiteKernel", "GTestConst", "ManagerType",
"ModeType", "ConfigConst"]
@dataclass
......@@ -40,9 +41,10 @@ class ProductForm(object):
ProductForm enumeration
"""
phone = "phone"
car = "car"
car = "ivi"
television = "tv"
watch = "watch"
tablet = 'tablet'
@dataclass
......@@ -57,6 +59,7 @@ class TestType(object):
sec = "security"
reli = "reliability"
dst = "distributedtest"
benchmark = "benchmark"
all = "ALL"
......@@ -76,8 +79,9 @@ class DeviceLabelType(object):
"""
wifiiot = "wifiiot"
ipcamera = "ipcamera"
watch = "watch"
watch_gt = "watchGT"
phone = "phone"
watch = "watch"
@dataclass
......@@ -124,10 +128,12 @@ class DeviceTestType(object):
hap_test = "HapTest"
junit_test = "JUnitTest"
jsunit_test = "JSUnitTest"
jsunit_test_lite = "JSUnitTestLite"
ctest_lite = "CTestLite"
cpp_test_lite = "CppTestLite"
lite_cpp_test = "LiteUnitTest"
open_source_test = "OpenSourceTest"
build_only_test = "BuildOnlyTestLite"
@dataclass
......@@ -190,6 +196,8 @@ class ParserType:
cpp_test_lite = "CppTestLite"
cpp_test_list_lite = "CppTestListLite"
open_source_test = "OpenSourceTest"
build_only_test = "BuildOnlyTestLite"
jsuit_test_lite = "JSUnitTestLite"
@dataclass
......@@ -210,7 +218,7 @@ class ToolCommandType(object):
@dataclass
class CKit:
push = "PushKit"
install = "ApkInstallKit"
liteinstall = "LiteAppInstallKit"
command = "CommandKit"
config = "ConfigKit"
wifi = "WIFIKit"
......@@ -222,9 +230,55 @@ class CKit:
liteuikit = 'LiteUiKit'
rootfs = "RootFsKit"
query = "QueryKit"
liteshell = "LiteShellKit"
app_install = "AppInstallKit"
@dataclass
class GTestConst(object):
exec_para_filter = "--gtest_filter"
exec_para_level = "--gtest_testsize"
@dataclass
class ModeType(object):
decc = "decc"
factory = "factory"
developer = "developer"
@dataclass
class ConfigConst(object):
action = "action"
task = "task"
testlist = "testlist"
testfile = "testfile"
testcase = "testcase"
device_sn = "device_sn"
report_path = "report_path"
resource_path = "resource_path"
testcases_path = "testcases_path"
testargs = "testargs"
pass_through = "pass_through"
test_environment = "test_environment"
exectype = "exectype"
testtype = "testtype"
testdriver = "testdriver"
retry = "retry"
session = "session"
dry_run = "dry_run"
reboot_per_module = "reboot_per_module"
check_device = "check_device"
configfile = "config"
repeat = "repeat"
# Runtime Constant
history_report_path = "history_report_path"
product_info = "product_info"
task_state = "task_state"
recover_state = "recover_state"
need_kit_setup = "need_kit_setup"
task_kits = "task_kits"
module_kits = "module_kits"
spt = "spt"
version = "version"
文件模式从 100755 更改为 100644
......@@ -2,7 +2,7 @@
# coding=utf-8
#
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Copyright (c) 2020-2021 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
......@@ -21,9 +21,12 @@ import os
import sys
from _core.constants import HostDrivenTestType
from _core.constants import TestExecType
from _core.constants import ModeType
from _core.constants import DeviceLabelType
from _core.driver.drivers_lite import init_remote_server
from _core.exception import DeviceError
from _core.exception import LiteDeviceError
from _core.exception import ParamError
from _core.exception import ReportException
from _core.exception import ExecuteTerminate
......@@ -32,64 +35,18 @@ from _core.logger import platform_logger
from _core.plugin import Plugin
from _core.testkit.json_parser import JsonParser
from _core.utils import get_config_value
from _core.utils import do_module_kit_setup
from _core.utils import do_module_kit_teardown
from _core.utils import get_filename_extension
from _core.utils import get_file_absolute_path
from _core.utils import get_kit_instances
from _core.utils import check_result_report
from _core.utils import check_mode
from _core.report.suite_reporter import SuiteReporter
LOG = platform_logger("DeviceTest")
def start_task(test_file, configs, device, logger):
from xdevice import Variables
# insert& devicetest path for loading devicetest module
devicetest_module = os.path.join(Variables.modules_dir, "_devicetest")
if os.path.exists(devicetest_module):
sys.path.insert(1, devicetest_module)
if configs["testcases_path"]:
sys.path.insert(1, configs["testcases_path"])
from _devicetest.devicetest.main import DeviceTest
device_test = DeviceTest(test_list=test_file, configs=configs,
devices=[device], log=logger)
device_test.run()
def set_up_env(request, source):
if not source.endswith(".json"):
source = "%s.json" % source
json_config = JsonParser(source)
test_args = get_config_value('xml-output', json_config.get_driver())
kits = get_kit_instances(json_config, request.config.resource_path,
request.config.testcases_path)
kits_copy = copy.deepcopy(kits)
from xdevice import Scheduler
for kit in kits:
if not Scheduler.is_execute:
raise ExecuteTerminate()
kit.__setup__(request.config.device, request=request)
return test_args, kits, kits_copy
def get_file_list(module_path):
file_list = []
if not file_list:
for test_file in os.listdir(module_path):
if test_file.endswith(".py") or test_file.endswith(".pyd"):
file_list.append(os.path.join(
module_path, test_file))
return file_list
else:
filter_file_list = []
for test_file in file_list:
if (test_file.endswith(".pyd") or test_file.endswith(".py")) and \
os.path.exists(os.path.join(module_path, test_file)):
filter_file_list.append(os.path.join(
module_path, test_file))
return filter_file_list
PY_SUFFIX = ".py"
PYD_SUFFIX = ".pyd"
@Plugin(type=Plugin.DRIVER, id=HostDrivenTestType.device_test)
......@@ -111,125 +68,197 @@ class DeviceTestDriver(IDriver):
pass
def __check_config__(self, config=None):
del config
self.py_file = ""
pass
def __init_nfs_server__(self, request=None):
return init_remote_server(self, request)
def __execute__(self, request):
kits, source = self._parse_request(request)
try:
# set self.config
self.config = request.config
self.config.tmp_id = str(request.uuid)
self.config.tmp_folder = os.path.join(self.config.report_path,
"temp")
self.config.devices = request.get_devices()
if request.get("exectype") == TestExecType.device_test and \
not self.config.devices:
LOG.error("no device", error_no="00104")
raise ParamError("Load Error[00104]", error_no="00104")
# get source, json config and kits
if request.get_config_file():
source = request.get_config_file()
LOG.debug("Test config file path: %s" % source)
else:
source = request.get_source_string()
LOG.debug("Test String: %s" % source)
if not source:
LOG.error("no config file found for '%s'" %
request.get_source_file(), error_no="00102")
raise ParamError("Load Error(00102)", error_no="00102")
json_config = JsonParser(source)
kits = get_kit_instances(json_config, request.config.resource_path,
request.config.testcases_path)
# create tmp folder
test_name = request.get_module_name()
tmp_sub_folder = self._create_tmp_folder(request)
self.result = "%s.xml" % os.path.join(tmp_sub_folder, test_name)
# set configs keys
configs = self._set_configs(json_config, kits, request,
tmp_sub_folder)
# get test list
test_list = self._get_test_list(json_config, request, source)
if not test_list:
raise ParamError("no test list to run")
self._run_devicetest(configs, test_list)
except (ReportException, ModuleNotFoundError, ExecuteTerminate,
SyntaxError, ValueError, AttributeError, TypeError,
KeyboardInterrupt, ParamError, DeviceError, LiteDeviceError) \
as exception:
error_no = getattr(exception, "error_no", "00000")
LOG.exception(exception, exc_info=False, error_no=error_no)
self.error_message = exception
finally:
self._handle_finally(request)
def _get_test_list(self, json_config, request, source):
test_list = get_config_value('py_file', json_config.get_driver(),
is_list=True)
if str(request.root.source.source_file).endswith(PYD_SUFFIX) or \
str(request.root.source.source_file).endswith(PY_SUFFIX):
test_list = [request.root.source.source_file]
if not test_list and os.path.exists(source):
test_list = _get_dict_test_list(os.path.dirname(source))
# check test list
testcase = request.get("testcase")
testcase_list = []
if testcase:
testcase_list = str(testcase).split(";")
checked_test_list = []
for index, test in enumerate(test_list):
if not os.path.exists(test):
try:
absolute_file = get_file_absolute_path(test, [
self.config.resource_path, self.config.testcases_path])
except ParamError as error:
LOG.error(error, error_no=error.error_no)
continue
else:
absolute_file = test
file_name = get_filename_extension(absolute_file)[0]
if not testcase_list or file_name in testcase_list:
checked_test_list.append(absolute_file)
else:
LOG.info("test '%s' is ignored", absolute_file)
if checked_test_list:
LOG.info("test list: {}".format(checked_test_list))
else:
LOG.error("no test list found", error_no="00109")
raise ParamError("Load Error(00109)", error_no="00109")
return checked_test_list
def _set_configs(self, json_config, kits, request, tmp_sub_folder):
configs = dict()
configs["testargs"] = self.config.testargs or ""
configs["testargs"] = self.config.testargs or {}
configs["testcases_path"] = self.config.testcases_path or ""
configs["request"] = request
configs["test_name"] = request.get_module_name()
configs["report_path"] = tmp_sub_folder
configs["execute"] = get_config_value(
'execute', json_config.get_driver(), False)
try:
if self.config.device and self.config.device.label == \
DeviceLabelType.ipcamera:
for device in self.config.devices:
do_module_kit_setup(request, kits)
if device.label == DeviceLabelType.ipcamera:
# add extra keys to configs for ipcamera device
self.__init_nfs_server__(request=request)
_, kits, kits_copy = set_up_env(request, source)
configs["linux_host"] = self.linux_host
configs["linux_directory"] = self.linux_directory
configs["kits"] = kits_copy
self.run_module(request, configs, source)
elif self.config.device and self.config.device.label == \
DeviceLabelType.watch:
self.run_module(request, configs, source)
elif self.config.device and self.config.device.label == \
DeviceLabelType.phone:
self.run_module(request, configs, source)
except (ReportException, ModuleNotFoundError, ExecuteTerminate,
SyntaxError, ValueError, AttributeError, TypeError,
KeyboardInterrupt, ParamError) as exception:
LOG.exception(exception)
self.error_message = exception
configs["kits"] = kits
finally:
self._handle_finally(kits, request)
return configs
def _handle_finally(self, kits, request):
def _handle_finally(self, request):
from xdevice import Scheduler
for kit in kits:
kit.__teardown__(request.config.device)
if self.config.device.label == \
DeviceLabelType.ipcamera or self.config.device.label == \
DeviceLabelType.watch:
self.config.device.close()
# do kit teardown
do_module_kit_teardown(request)
# close device connect
for device in self.config.devices:
if device.label == DeviceLabelType.ipcamera or device.label == \
DeviceLabelType.watch_gt:
device.close()
if device.label == DeviceLabelType.phone:
device.close()
# check result report
report_name = request.root.source.test_name if \
not request.root.source.test_name.startswith("{") \
else "report"
if Scheduler.mode != "decc":
module_name = request.get_module_name()
if Scheduler.mode != ModeType.decc:
self.result = check_result_report(
request.config.report_path, self.result, self.error_message,
report_name)
report_name, module_name)
else:
tmp_list = copy.copy(SuiteReporter.get_report_result())
if os.path.dirname(self.result) not in \
[report_path for report_path, _ in tmp_list]:
if self.result not in [report_path for report_path, _ in tmp_list]:
if not self.error_message:
self.error_message = "An unknown exception occurred " \
"during the execution case"
self.error_message = "Case not execute[01205]"
self.result = check_result_report(
request.config.report_path, self.result,
self.error_message, report_name)
self.error_message, report_name, module_name)
def _parse_request(self, request):
from xdevice import Variables
kits = []
self.config = request.config
self.config.device = request.config.environment.devices[0]
if not self.config.device:
raise DeviceError("no device..........................")
current_dir = request.config.resource_path if \
request.config.resource_path else Variables.exec_dir
if request.root.source.source_file.strip():
source = os.path.join(current_dir,
request.root.source.source_file.strip())
LOG.debug("Testfile FilePath: %s" % source)
else:
source = request.root.source.source_string.strip()
self.config.tmp_folder = os.path.join(self.config.report_path,
"temp")
self.config.tmp_id = str(request.uuid)
return kits, source
def run_module(self, request, configs, source):
json_config = JsonParser(source)
def _create_tmp_folder(self, request):
if request.root.source.source_file.strip():
folder_name = "task_%s_%s" % (self.config.tmp_id,
request.root.source.test_name)
else:
folder_name = "task_%s_report" % self.config.tmp_id
tmp_sub_folder = os.path.join(self.config.tmp_folder, folder_name)
os.makedirs(tmp_sub_folder, exist_ok=True)
return tmp_sub_folder
configs["report_path"] = tmp_sub_folder
self.result = "%s.xml" % os.path.join(tmp_sub_folder, "report")
module_path = os.path.dirname(source)
file_list = get_config_value('py_file', json_config.get_driver(),
is_list=True)
if not file_list:
file_list = get_file_list(module_path)
else:
folder_name = "task_%s_report" % self.config.tmp_id
tmp_sub_folder = os.path.join(self.config.tmp_folder,
folder_name)
self.result = "%s.xml" % os.path.join(tmp_sub_folder, "report")
json_config = JsonParser(source)
file_list = get_config_value('py_file', json_config.get_driver(),
is_list=True)
configs["test_name"] = request.root.source.test_name
configs["execute"] = get_config_value('execute',
json_config.get_driver(), False)
def _run_devicetest(self, configs, test_list):
from xdevice import Variables
os.makedirs(tmp_sub_folder, exist_ok=True)
self._run_devicetest(configs, file_list)
# insert paths for loading _devicetest module and testcases
devicetest_module = os.path.join(Variables.modules_dir, "_devicetest")
if os.path.exists(devicetest_module):
sys.path.insert(1, devicetest_module)
if configs["testcases_path"]:
sys.path.insert(1, configs["testcases_path"])
def _run_devicetest(self, configs, test_file):
start_task(test_file, configs, self.config.device, LOG)
# run devicetest
from _devicetest.devicetest.main import DeviceTest
device_test = DeviceTest(test_list=test_list, configs=configs,
devices=self.config.devices, log=LOG)
device_test.run()
def __result__(self):
if check_mode(ModeType.decc):
return self.result
return self.result if os.path.exists(self.result) else ""
def _get_dict_test_list(module_path):
test_list = []
for root, _, files in os.walk(module_path):
for _file in files:
if _file.endswith(".py") or _file.endswith(".pyd"):
test_list.append(os.path.join(root, _file))
return test_list
文件模式从 100755 更改为 100644
......@@ -2,7 +2,7 @@
# coding=utf-8
#
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Copyright (c) 2020-2021 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
......@@ -16,47 +16,74 @@
# limitations under the License.
#
import json
import time
import re
from _core.constants import DeviceTestType
from _core.exception import ExecuteTerminate
from _core.exception import LiteDeviceTimeout
from _core.exception import LiteDeviceConnectError
from _core.exception import LiteDeviceExecuteCommandError
from _core.logger import platform_logger
from _core.utils import convert_port
__all__ = ["generate_report", "LiteHelper"]
CPP_TEST_STANDARD_SIGN = "[==========]"
CPP_TEST_END_SIGN = "Global test environment tear-down"
CPP_SYS_STANDARD_SIGN = " #"
CPP_TEST_END_SIGN = "Gtest xml output finished"
CPP_SYS_STANDARD_SIGN = "OHOS #"
CPP_ERR_MESSAGE = "[ERR]No such file or directory: "
TIMEOUT = 90
CTEST_STANDARD_SIGN = "Start to run test suite"
AT_CMD_ENDS = "OK"
CTEST_END_SIGN = "Framework finished."
CTEST_END_SIGN = "All the test suites finished"
_START_JSUNIT_RUN_MARKER = "[start] start run suites"
_END_JSUNIT_RUN_MARKER = "[end] run suites end"
INSTALL_END_MARKER = "resultMessage is install success !"
PATTERN = re.compile(r'\x1B(\[([0-9]{1,2}(;[0-9]{1,2})*)?m)*')
TIMEOUT = 90
LOG = platform_logger("DmlibLite")
def check_open_source_test(result_output):
if result_output.find(CPP_TEST_STANDARD_SIGN) == -1 and \
("test pass" in result_output.lower() or
"test fail" in result_output.lower() or
"tests pass" in result_output.lower() or
"tests fail" in result_output.lower()):
return True
return False
def check_read_test_end(result=None, input_command=None):
result_output = result.replace(input_command, "")
temp_result = result.replace("\n", "")
if input_command not in temp_result:
return False
index = result.find(input_command) + len(input_command)
result_output = result[index:]
if input_command.startswith("./"):
if result_output.find(CPP_TEST_STANDARD_SIGN) != -1:
if result_output.count(CPP_TEST_STANDARD_SIGN) == 2 or \
result_output.find(CPP_TEST_END_SIGN) != -1:
return True
if result_output.find(CPP_TEST_STANDARD_SIGN) == -1 and \
("test pass" in result_output.lower() or
"test fail" in result_output.lower()):
if check_open_source_test(result_output):
return True
if result_output.find(_START_JSUNIT_RUN_MARKER) >= 1 and \
result_output.find(_END_JSUNIT_RUN_MARKER) >= 1:
return True
if result_output.find(INSTALL_END_MARKER) != -1:
return True
if "%s%s" % (CPP_ERR_MESSAGE, input_command[2:]) in result_output:
LOG.error("execute file not exist, result is %s" % result_output)
raise LiteDeviceExecuteCommandError("execute file not exist")
LOG.error("execute file not exist, result is %s" % result_output,
error_no="00402")
raise LiteDeviceExecuteCommandError("execute file not exist",
error_no="00402")
else:
if " #" in result_output:
if "OHOS #" in result_output or "Linux" in result_output:
if input_command == "reboot" or input_command == "reset":
return False
if input_command.startswith("mount"):
......@@ -100,37 +127,43 @@ class LiteHelper:
status = True
error_message = ""
result = ""
LOG.info("execute command shell %s with timeout %s" %
(command, str(timeout)))
if not telnet:
raise LiteDeviceConnectError("remote device is not connected.")
raise LiteDeviceConnectError("remote device is not connected.",
error_no="00402")
telnet.write(command.encode('ascii') + b"\n")
while time.time() - start_time < timeout:
data = telnet.read_until(bytes(command, encoding="utf8"),
timeout=1)
data = PATTERN.sub('', data.decode('gbk', 'ignore')).replace(
"\r", "")
result = "{}{}".format(result, data)
if command in result:
break
expect_result = [bytes(CPP_TEST_STANDARD_SIGN, encoding="utf8"),
bytes(CPP_SYS_STANDARD_SIGN, encoding="utf8"),
bytes(CPP_TEST_END_SIGN, encoding="utf8")]
while time.time()-start_time < timeout:
while time.time() - start_time < timeout:
if not Scheduler.is_execute:
raise ExecuteTerminate()
raise ExecuteTerminate("Execute terminate", error_no="00300")
_, _, data = telnet.expect(expect_result, timeout=1)
data = PATTERN.sub('', data.decode('gbk', 'ignore'))
result = result + data.replace("\r", "")
data = PATTERN.sub('', data.decode('gbk', 'ignore')).replace(
"\r", "")
result = "{}{}".format(result, data)
if receiver and data:
receiver.__read__(data)
if check_read_test_end(result, command):
break
else:
error_message = "execute command with timeout=%s " % command
LOG.debug("error_message=%s" % error_message)
error_message = "execute %s timed out %s " % (command, timeout)
status = False
if receiver:
if command in result:
index = result.find(command) + len(command)
result_output = result[index:]
else:
result_output = result
generate_report(receiver, result_output)
receiver.__done__()
if not status and command.startswith("uname"):
raise LiteDeviceTimeout("Execute command time out:%s" % command)
return result, status, error_message
......@@ -138,34 +171,43 @@ class LiteHelper:
def read_local_output_test(com=None, command=None, timeout=TIMEOUT,
receiver=None):
input_command = command
linux_end_command = ""
if "--gtest_output=" in command:
linux_end_command = input_command.split(":")[1].split(
"reports")[0].rstrip("/") + " #"
error_message = ""
start_time = time.time()
result = ""
status = True
from xdevice import Scheduler
while time.time()-start_time < timeout:
while time.time() - start_time < timeout:
data = com.readline().decode('gbk', errors='ignore')
data = PATTERN.sub('', data).replace("\r", "")
result = "{}{}".format(result, data)
if command in result or linux_end_command in result:
break
while time.time() - start_time < timeout:
if not Scheduler.is_execute:
raise ExecuteTerminate()
raise ExecuteTerminate("Execute terminate", error_no="00300")
data = com.readline().decode('gbk', errors='ignore')
data = PATTERN.sub('', data)
result = "{}{}".format(result, data.replace("\r", ""))
data = PATTERN.sub('', data).replace("\r", "")
result = "{}{}".format(result, data)
if receiver and data:
receiver.__read__(data)
if check_read_test_end(result, input_command):
break
else:
error_message = "execute command with timeout=%s " % command
LOG.debug("error_message:%s" % error_message)
error_message = "execute %s timed out %s " % (command, timeout)
status = False
if receiver:
if command in result:
index = result.find(command) + len(command)
result_output = result[index:]
else:
result_output = result
generate_report(receiver, result_output)
receiver.__done__()
if not status and command.startswith("uname"):
raise LiteDeviceTimeout("Execute command time out:%s" % command)
LOG.info('Info: execute command success')
return result, status, error_message
@staticmethod
......@@ -178,17 +220,21 @@ class LiteHelper:
from xdevice import Scheduler
while True:
if not Scheduler.is_execute:
raise ExecuteTerminate()
raise ExecuteTerminate("Execute terminate", error_no="00300")
data = com.readline().decode('gbk', errors='ignore')
data = PATTERN.sub('', data)
if isinstance(input_command, list):
data = "{} {}".format(get_current_time(), data)
if data and receiver:
receiver.__read__(data.replace("\r", ""))
result = "{}{}".format(result, data.replace("\r", ""))
if re.search(r"\d+\s+Tests\s+\d+\s+Failures\s+\d+\s+"
r"Ignored", data):
start = time.time()
if (int(time.time()) - int(start)) > timeout:
break
if CTEST_END_SIGN in data:
break
else:
result = "{}{}".format(
result, data.replace("\r", "").replace("\n", "").strip())
......@@ -197,11 +243,8 @@ class LiteHelper:
if (int(time.time()) - int(start)) > timeout:
return result, False, ""
result = PATTERN.sub('', result)
if receiver:
result = "{}{}".format(
result, "{} {}".format(get_current_time(), CTEST_END_SIGN))
generate_report(receiver, result)
receiver.__done__()
LOG.info('Info: execute command success')
return result, True, ""
......@@ -227,10 +270,12 @@ class LiteHelper:
timeout = args.get("timeout", TIMEOUT)
receiver = args.get("receiver", None)
if not com:
raise LiteDeviceConnectError("local device is not connected.")
raise LiteDeviceConnectError("local device is not connected.",
error_no="00402")
LOG.info("local_%s execute command shell %s with timeout %ss" %
(convert_port(com.port), command, str(timeout)))
LOG.info("%s \n execute command shell %s with timeout %s" %
(com, command, str(timeout)))
if isinstance(command, str):
command = command.encode("utf-8")
if command[-2:] != b"\r\n":
......@@ -248,11 +293,92 @@ class LiteHelper:
Execute command on the serial and read all the output from the serial.
"""
if not com:
raise LiteDeviceConnectError("local device is not connected.")
raise LiteDeviceConnectError("local device is not connected.",
error_no="00402")
LOG.info(
"%s \n execute command shell %s" % (com, command))
"local_%s execute command shell %s" % (convert_port(com.port),
command))
command = command.encode("utf-8")
if command[-2:] != b"\r\n":
command = command.rstrip() + b'\r\n'
com.write(command)
@staticmethod
def execute_agent_cmd_with_timeout(self, command,
**kwargs):
import requests
base_url = self.base_url
headers = self.headers
local_source_dir = self.local_source_dir
target_save_path = self.target_save_path
args = kwargs
command_type = args.get("type", None)
sync = args.get("sync", 1)
response = None
try:
if "cmd" == command_type:
url = base_url + "/_processes/"
data = {
'cmd': command,
'sync': sync,
'stdoutRedirect': 'file',
'stderrRedirect': 'file'
}
response = requests.post(url=url, headers=headers,
data=json.dumps(data))
if response.status_code == 200:
LOG.info("connect OK")
else:
LOG.info("connect failed")
response.close()
elif "put" == command_type:
url = base_url + target_save_path + command
data = open(local_source_dir + command, "rb")
response = requests.put(url=url, headers=headers, data=data)
if response.status_code == 200:
LOG.info("{} upload file to {} "
"success".format(local_source_dir,
target_save_path))
else:
LOG.info(
"{} upload file to {} fail".format(local_source_dir,
target_save_path))
response.close()
elif "get" == command_type:
url = base_url + target_save_path + command
response = requests.get(url=url, headers=headers, stream=True)
if response.status_code == 200:
file_name = open(local_source_dir + command + "bak", "wb")
for file_data in response.iter_content(chunk_size=512):
file_name.write(file_data)
file_name.close()
LOG.info("from {} download file to {} success".format(
target_save_path + command,
local_source_dir))
else:
LOG.info("{} download file to {} fail".format(
target_save_path + command,
command,
local_source_dir))
elif "delete" == command_type:
url = base_url + target_save_path + command
LOG.info(url)
response = requests.delete(url)
if response.status_code == 200:
LOG.info("delete {} file success".format(
target_save_path + command))
else:
LOG.info("delete {} file fail".format(
target_save_path + command))
else:
LOG.info("type error")
except Exception as error_message:
LOG.info("error_message:{}".format(error_message))
finally:
if response:
response.close()
return "", True, ""
......@@ -2,7 +2,7 @@
# coding=utf-8
#
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Copyright (c) 2020-2021 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
......@@ -17,17 +17,19 @@
#
import time
import threading
from _core.config.config_manager import UserConfigManager
from _core.constants import DeviceOsType
from _core.constants import ManagerType
from _core.environment.manager_env import DeviceAllocationState
from _core.exception import LiteDeviceConnectError
from _core.exception import ParamError
from _core.exception import LiteDeviceError
from _core.plugin import Plugin
from _core.plugin import get_plugin
from _core.interface import IDeviceManager
from _core.logger import platform_logger
from _core.utils import convert_ip
from _core.utils import convert_port
__all__ = ["ManagerLite"]
......@@ -43,12 +45,15 @@ class ManagerLite(IDeviceManager):
def __init__(self):
self.devices_list = []
self.list_con = threading.Condition()
self.support_labels = ["ipcamera", "wifiiot", "watchGT"]
def init_environment(self, environment=""):
def init_environment(self, environment="", user_config_file=""):
device_lite = get_plugin(plugin_type=Plugin.DEVICE,
plugin_id=DeviceOsType.lite)[0]
devices = UserConfigManager(env=environment).get_com_device(
devices = UserConfigManager(
config_file=user_config_file, env=environment).get_com_device(
"environment/device")
for device in devices:
......@@ -57,18 +62,24 @@ class ManagerLite(IDeviceManager):
device_lite_instance.__init_device__(device)
device_lite_instance.device_allocation_state = \
DeviceAllocationState.available
except (LiteDeviceConnectError, ParamError):
except LiteDeviceError as exception:
LOG.warning(exception)
continue
self.devices_list.append(device_lite_instance)
def env_stop(self):
pass
def apply_device(self, device_option, timeout=10):
"""
Request a device for testing that meets certain criteria.
"""
del timeout
LOG.debug("lite apply_device: apply lock")
self.list_con.acquire()
try:
allocated_device = None
for device in self.devices_list:
if device_option.matches(device):
device.device_allocation_state = \
......@@ -78,12 +89,23 @@ class ManagerLite(IDeviceManager):
return device
time.sleep(10)
return allocated_device
finally:
LOG.debug("lite apply_device: release lock")
self.list_con.release()
@staticmethod
def release_device(device):
device.device_allocation_state = DeviceAllocationState.available
def release_device(self, device):
LOG.debug("lite release_device: apply lock")
self.list_con.acquire()
try:
if device.device_allocation_state == \
DeviceAllocationState.allocated:
device.device_allocation_state = \
DeviceAllocationState.available
LOG.debug("free device sn: %s, type: %s" % (
device.__get_serial__(), device.__class__))
finally:
LOG.debug("lite release_device: release lock")
self.list_con.release()
def list_devices(self):
print("lite devices:")
......@@ -91,21 +113,22 @@ class ManagerLite(IDeviceManager):
format("SerialPort/IP", "Baudrate/Port", "OsType", "Allocation",
"Product", "ConnectType", "ComType"))
for device in self.devices_list:
if device.device_connect_type == "remote":
if device.device_connect_type == "remote" or \
device.device_connect_type == "agent":
print("{0:<20}{1:<16}{2:<16}{3:<16}{4:<16}{5:<16}".format(
device.remote_device.host,
device.remote_device.port,
convert_ip(device.device.host),
convert_port(device.device.port),
device.device_os_type,
device.device_allocation_state,
device.label,
device.device_connect_type))
else:
for com_controller in device.local_device.com_dict:
for com_controller in device.device.com_dict:
print("{0:<20}{1:<16}{2:<16}{3:<16}{4:<16}{5:<16}{6:<16}".
format(device.local_device.com_dict[
com_controller].serial_port,
device.local_device.com_dict[
com_controller].baund_rate,
format(convert_port(device.device.com_dict[
com_controller].serial_port),
device.device.com_dict[
com_controller].baud_rate,
device.device_os_type,
device.device_allocation_state,
device.label,
......
此差异已折叠。
文件模式从 100755 更改为 100644
此差异已折叠。
此差异已折叠。
此差异已折叠。
文件模式从 100755 更改为 100644
此差异已折叠。
此差异已折叠。
文件模式从 100755 更改为 100644
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册