mirror of
https://gitee.com/bianbu-linux/factorytest
synced 2025-04-18 19:34:59 -04:00
Update for v1.0rc1
This commit is contained in:
parent
91a5524b15
commit
5a98e3422f
40 changed files with 1117 additions and 41 deletions
30
README.md
30
README.md
|
@ -13,9 +13,11 @@
|
|||
```
|
||||
├── cricket # Cricket is a graphical tool that helps you run your test suites.
|
||||
├── gui-main
|
||||
└── tests # factory test case
|
||||
├── auto # auto test case
|
||||
└── manual # manual test case
|
||||
├── res # test case resources
|
||||
├─── tests # factory test case
|
||||
│ ├── auto # auto test case
|
||||
│ └── manual # manual test case
|
||||
└── utils # common files
|
||||
```
|
||||
|
||||
## 测试项
|
||||
|
@ -25,12 +27,28 @@
|
|||
添加测试项规则:
|
||||
|
||||
- 自动测试项和手动测试项分别添加到`tests/auto`和`tests/manual`目录
|
||||
- 每个模块一个文件,以`test_`开头,文件里定义一个类,继承`unittest.TestCase`
|
||||
- 测试项为类的方法,方法名以`test_`开头
|
||||
- 每个模块一个文件,以`test_`开头,可以加上序号规定加载顺序,例如`test_01_`,文件里定义一个测试类,继承`unittest.TestCase`
|
||||
- 测试项为类的方法,测试方法的名称必须以`test_`开头
|
||||
- 类里定义一个字典`LANGUAGES`,用于支持多国语音
|
||||
|
||||
注意事项:
|
||||
|
||||
- 不要在测试方法里调用`os._exit()`、`sys.exit()`或`QApplication quit()`等方法,会导致测试中止,建议创建线程或子进程。
|
||||
|
||||
## 多国语言
|
||||
|
||||
相关文件:
|
||||
|
||||
- cricket/cricket/lang.py
|
||||
- cricket/cricket/languages.json
|
||||
|
||||
语言:
|
||||
|
||||
- zh:中文
|
||||
- en:英文
|
||||
|
||||
默认语言:中文,可以通过`cricket/cricket/lang.py`的_current_lang修改。
|
||||
|
||||
## TODO
|
||||
|
||||
- 支持命令行
|
||||
- 支持命令行
|
||||
|
|
|
@ -6,13 +6,16 @@
|
|||
"stop_button": "停止",
|
||||
"quit_button": "退出",
|
||||
"reboot_button": "重启",
|
||||
"poweroff_button": "关闭",
|
||||
"poweroff_button": "关机",
|
||||
"camera": "摄像头",
|
||||
"audio": "音频",
|
||||
"test_table_head": ["模块", "测试项", "结果"],
|
||||
"test_step": "测试步骤",
|
||||
"start_button": "开始",
|
||||
"play_button": "播放",
|
||||
"record_button": "录音",
|
||||
"playback_button": "回放",
|
||||
"speed_button": "速度",
|
||||
"pass_button": "通过",
|
||||
"fail_button": "失败"
|
||||
},
|
||||
|
@ -24,12 +27,15 @@
|
|||
"quit_button": "Quit",
|
||||
"reboot_button": "Reboot",
|
||||
"poweroff_button": "Shutdown",
|
||||
"camera": "Camera",
|
||||
"audio": "Microphone",
|
||||
"test_table_head": ["Module", "Test Item", "Result"],
|
||||
"test_step": "Test Step",
|
||||
"start_button": "Start",
|
||||
"play_button": "Play",
|
||||
"record_button": "Record",
|
||||
"playback_button": "Playback",
|
||||
"speed_button": "Speed",
|
||||
"pass_button": "Pass",
|
||||
"fail_button": "Fail"
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
This is the "View" of the MVC world.
|
||||
"""
|
||||
|
||||
from PyQt5.QtCore import Qt, QTimer
|
||||
from PyQt5.QtCore import Qt, QTimer, QUrl
|
||||
from PyQt5.QtGui import QColor
|
||||
from PyQt5.QtWidgets import (
|
||||
QMainWindow,
|
||||
|
@ -14,10 +14,16 @@ from PyQt5.QtWidgets import (
|
|||
QGroupBox,
|
||||
QTableWidget,
|
||||
QStatusBar,
|
||||
QTableWidgetItem
|
||||
QTableWidgetItem,
|
||||
QHeaderView
|
||||
)
|
||||
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
|
||||
from PyQt5.QtMultimediaWidgets import QVideoWidget
|
||||
|
||||
import os
|
||||
import time
|
||||
import threading
|
||||
import subprocess
|
||||
from importlib import import_module
|
||||
|
||||
from cricket.model import TestMethod, TestCase, TestModule
|
||||
|
@ -28,7 +34,7 @@ from cricket.lang import SimpleLang
|
|||
# Display constants for test status
|
||||
STATUS = {
|
||||
TestMethod.STATUS_PASS: {
|
||||
'description': u'Pass',
|
||||
'description': u'通过',
|
||||
'symbol': u'\u25cf',
|
||||
'tag': 'pass',
|
||||
'color': '#28C025',
|
||||
|
@ -40,7 +46,7 @@ STATUS = {
|
|||
'color': '#259EBF'
|
||||
},
|
||||
TestMethod.STATUS_FAIL: {
|
||||
'description': u'Failure',
|
||||
'description': u'失败',
|
||||
'symbol': u'F',
|
||||
'tag': 'fail',
|
||||
'color': '#E32C2E'
|
||||
|
@ -87,6 +93,8 @@ class MainWindow(QMainWindow, SimpleLang):
|
|||
self.setWindowTitle(self.get_text('title'))
|
||||
# self.showFullScreen()
|
||||
|
||||
self.font_size = 16
|
||||
|
||||
# Set up the main content for the window.
|
||||
self._setup_main_content()
|
||||
|
||||
|
@ -107,9 +115,12 @@ class MainWindow(QMainWindow, SimpleLang):
|
|||
It is a persistent GUI component
|
||||
'''
|
||||
|
||||
self.setStyleSheet(f'font-size: {self.font_size}px;')
|
||||
|
||||
self.content = QFrame(self)
|
||||
self.content_layout = QVBoxLayout(self.content)
|
||||
|
||||
# toolbar
|
||||
toolbar = QFrame(self.content)
|
||||
layout = QGridLayout(toolbar)
|
||||
|
||||
|
@ -139,19 +150,67 @@ class MainWindow(QMainWindow, SimpleLang):
|
|||
|
||||
self.content_layout.addWidget(toolbar)
|
||||
|
||||
# tests
|
||||
# -------------------
|
||||
# | | |
|
||||
# | auto | camera |
|
||||
# | | |
|
||||
# -------------------
|
||||
# | manual | audio |
|
||||
# | | |
|
||||
# -------------------
|
||||
self.tests = QFrame(self.content)
|
||||
self.tests_layout = QGridLayout(self.tests)
|
||||
|
||||
self._setup_test_table('auto', 0, 0, 4, 1)
|
||||
self._setup_test_table('manual', 4, 0, 3, 1)
|
||||
|
||||
camera_box = QGroupBox(self.get_text('camera'), self.tests)
|
||||
camera_box_layout = QVBoxLayout(camera_box)
|
||||
video_widget = QVideoWidget(camera_box)
|
||||
self.media_player = QMediaPlayer()
|
||||
self.media_player.setVideoOutput(video_widget)
|
||||
camera_box_layout.addWidget(video_widget)
|
||||
|
||||
audio_box = QGroupBox(self.get_text('audio'), self.tests)
|
||||
audio_box_layout = QVBoxLayout(audio_box)
|
||||
|
||||
self.tests_layout.addWidget(camera_box, 0, 1, 4, 1)
|
||||
self.tests_layout.addWidget(audio_box, 4, 1, 3, 1)
|
||||
|
||||
self.tests_layout.setRowStretch(0, 4)
|
||||
self.tests_layout.setRowStretch(1, 4)
|
||||
self.tests_layout.setRowStretch(2, 4)
|
||||
self.tests_layout.setRowStretch(3, 4)
|
||||
|
||||
self.tests_layout.setRowStretch(4, 3)
|
||||
self.tests_layout.setRowStretch(5, 3)
|
||||
self.tests_layout.setRowStretch(6, 3)
|
||||
|
||||
self.tests_layout.setColumnStretch(0, 1)
|
||||
self.tests_layout.setColumnStretch(1, 1)
|
||||
|
||||
self.content_layout.addWidget(self.tests)
|
||||
|
||||
# set main content to window
|
||||
self.setCentralWidget(self.content)
|
||||
|
||||
def _setup_test_table(self, name):
|
||||
def _setup_test_table(self, name, row, column, row_span, column_span):
|
||||
module = import_module(name)
|
||||
|
||||
box = QGroupBox(module.MODULE_NAME[self.current_lang], self.content)
|
||||
box = QGroupBox(module.MODULE_NAME[self.current_lang], self.tests)
|
||||
box.setStyleSheet("QGroupBox::title { font-weight: bold; }")
|
||||
layout = QVBoxLayout(box)
|
||||
|
||||
columns = self.get_text('test_table_head')
|
||||
|
||||
table = QTableWidget(box)
|
||||
table.setStyleSheet('QTableWidget { background-color: black; color: white; }')
|
||||
table.setColumnCount(len(columns))
|
||||
table.setHorizontalHeaderLabels(columns)
|
||||
for i in range(len(columns)):
|
||||
table.horizontalHeader().setSectionResizeMode(i, QHeaderView.Stretch)
|
||||
table.verticalHeader().setStyleSheet('QHeaderView::section { width: 32px; }')
|
||||
table.setSelectionBehavior(QTableWidget.SelectRows)
|
||||
table.itemSelectionChanged.connect(self.on_testMethodSelected)
|
||||
layout.addWidget(table)
|
||||
|
@ -162,7 +221,7 @@ class MainWindow(QMainWindow, SimpleLang):
|
|||
layout.addWidget(status)
|
||||
self.run_status[name] = status
|
||||
|
||||
self.content_layout.addWidget(box)
|
||||
self.tests_layout.addWidget(box, row, column, row_span, column_span)
|
||||
|
||||
######################################################
|
||||
# Handlers for setting a new project
|
||||
|
@ -201,9 +260,15 @@ class MainWindow(QMainWindow, SimpleLang):
|
|||
item = QTableWidgetItem(self._get_text(subModuleName, subModule, testMethod_name))
|
||||
table.setItem(row, 1, item)
|
||||
item = QTableWidgetItem('')
|
||||
item.setTextAlignment(Qt.AlignCenter)
|
||||
item.setData(Qt.UserRole, testMethod.path)
|
||||
table.setItem(row, 2, item)
|
||||
|
||||
logical_dpi = table.logicalDpiY()
|
||||
font_pixel = self.font_size * logical_dpi / 72
|
||||
row_height = int(font_pixel * 2)
|
||||
table.setRowHeight(row, row_height)
|
||||
|
||||
@project.setter
|
||||
def project(self, project):
|
||||
self._project = project
|
||||
|
@ -215,7 +280,6 @@ class MainWindow(QMainWindow, SimpleLang):
|
|||
# Populate the initial tree nodes. This is recursive, because
|
||||
# the tree could be of arbitrary depth.
|
||||
for testModule_name, testModule in sorted(project.items()):
|
||||
self._setup_test_table(testModule_name)
|
||||
self._add_test_module(testModule_name, testModule)
|
||||
self.executor[testModule_name] = None
|
||||
|
||||
|
@ -228,18 +292,72 @@ class MainWindow(QMainWindow, SimpleLang):
|
|||
######################################################
|
||||
|
||||
def mainloop(self):
|
||||
pipeline = 'gst-pipeline: spacemitsrc location=/opt/factorytest/res/camtest_sensor0_mode0.json close-dmabuf=1 ! videoconvert ! video/x-raw,format=BGRx ! autovideosink sync=0'
|
||||
self.media_player.setMedia(QMediaContent(QUrl(pipeline)))
|
||||
self.media_player.play()
|
||||
|
||||
self.audio_thread = threading.Thread(target=lambda: self.audio_loop())
|
||||
self.audio_thread.start()
|
||||
|
||||
self.cmd_run_all()
|
||||
|
||||
self.root.exec_()
|
||||
|
||||
def _play_wav(self, device, volume, path):
|
||||
cmd = f'amixer -c 1 cset numid=1,iface=MIXER,name="DAC Playback Volume" {volume}'
|
||||
proc = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
print(f'Set playback volume to {volume} return {proc.returncode}')
|
||||
|
||||
cmd = f'aplay -D{device} -r 48000 -f S16_LE {path}'
|
||||
proc = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
print(f'Play {path} on {device} return {proc.returncode}')
|
||||
|
||||
def _record_wav(self, device, volume, duration, path):
|
||||
cmd = f'amixer -c 1 cset numid=1,iface=MIXER,name="ADC Capture Volume" {volume},{volume}'
|
||||
proc = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
print(f'Set capture volume to {volume} return {proc.returncode}')
|
||||
|
||||
cmd = f'arecord -D{device} -r 48000 -f S16_LE -d {duration} {path}'
|
||||
proc = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
print(f'Record {path} on {device} in {duration}s return {proc.returncode}')
|
||||
|
||||
def audio_loop(self):
|
||||
# sleep for a while
|
||||
time.sleep(15)
|
||||
|
||||
device = 'hw:1'
|
||||
playback_volume = 184
|
||||
record_volume = 184
|
||||
duration = 5
|
||||
|
||||
res_path = '/opt/factorytest/res'
|
||||
start_record_file = f'{res_path}/start-record.wav'
|
||||
stop_record_file = f'{res_path}/stop-record.wav'
|
||||
start_play_file = f'{res_path}/start-play.wav'
|
||||
stop_play_file = f'{res_path}/stop-play.wav'
|
||||
record_file = '/tmp/factorytest-record.wav'
|
||||
|
||||
while True:
|
||||
self._play_wav(device, playback_volume, start_record_file)
|
||||
self._record_wav(device, record_volume, duration, record_file)
|
||||
self._play_wav(device, playback_volume, stop_record_file)
|
||||
self._play_wav(device, playback_volume, start_play_file)
|
||||
self._play_wav(device, playback_volume, record_file)
|
||||
self._play_wav(device, playback_volume, stop_play_file)
|
||||
time.sleep(duration)
|
||||
|
||||
######################################################
|
||||
# User commands
|
||||
######################################################
|
||||
|
||||
def cmd_poweroff(self):
|
||||
self.media_player.stop()
|
||||
self.stop()
|
||||
# self.root.quit()
|
||||
os.system('poweroff')
|
||||
|
||||
def cmd_reboot(self):
|
||||
self.media_player.stop()
|
||||
self.stop()
|
||||
# self.root.quit()
|
||||
os.system('reboot')
|
||||
|
@ -298,8 +416,9 @@ class MainWindow(QMainWindow, SimpleLang):
|
|||
if item.data(Qt.UserRole) == node.path:
|
||||
for column in range(columnCount):
|
||||
_item = table.item(row, column)
|
||||
_item.setForeground(QColor(STATUS[node.status]['color']))
|
||||
item.setText(STATUS[node.status]['description'])
|
||||
_item.setBackground(QColor(STATUS[node.status]['color']))
|
||||
if module == 'auto':
|
||||
item.setText(STATUS[node.status]['description'])
|
||||
break
|
||||
|
||||
def on_testProgress(self, executor):
|
||||
|
@ -386,12 +505,12 @@ class MainWindow(QMainWindow, SimpleLang):
|
|||
# 'skip': self.executor.result_count.get(TestMethod.STATUS_SKIP, 0),
|
||||
# })
|
||||
|
||||
# Reset the buttons
|
||||
self.reset_button_states_on_end()
|
||||
|
||||
# Drop the reference to the executor
|
||||
self.executor[module] = None
|
||||
|
||||
# Reset the buttons
|
||||
self.reset_button_states_on_end()
|
||||
|
||||
def on_executorSuiteError(self, event, module, error):
|
||||
"An error occurred running the test suite."
|
||||
# Display the error in a dialog
|
||||
|
|
145
deprecated/test_01_lcd.py
Normal file
145
deprecated/test_01_lcd.py
Normal file
|
@ -0,0 +1,145 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import subprocess
|
||||
import threading
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QGuiApplication
|
||||
from PyQt5.QtWidgets import (
|
||||
QApplication,
|
||||
QMainWindow,
|
||||
QFrame,
|
||||
QVBoxLayout,
|
||||
QGroupBox,
|
||||
QLabel,
|
||||
QStatusBar,
|
||||
QPushButton,
|
||||
QGridLayout
|
||||
)
|
||||
|
||||
from cricket.lang import SimpleLang
|
||||
|
||||
result = False
|
||||
|
||||
class LCDTestWindow(SimpleLang):
|
||||
def __init__(self, languages) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.languages = languages
|
||||
|
||||
self.app = QApplication([])
|
||||
|
||||
self.window = QMainWindow()
|
||||
self.window.setWindowTitle(self._get_text('title'))
|
||||
# self.window.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||
|
||||
# Main content
|
||||
content = QFrame(self.window)
|
||||
content_layout = QVBoxLayout(content)
|
||||
|
||||
# Test step
|
||||
box = QGroupBox(self.get_text('test_step'), content)
|
||||
box_layout = QVBoxLayout(box)
|
||||
|
||||
label = QLabel(self._get_text('test_step'), box)
|
||||
box_layout.addWidget(label)
|
||||
|
||||
content_layout.addWidget(box)
|
||||
|
||||
# Status
|
||||
# self.status = QStatusBar(content)
|
||||
# self.status.showMessage('Not running')
|
||||
# content_layout.addWidget(self.status)
|
||||
|
||||
# Toolbar
|
||||
toolbar = QFrame(content)
|
||||
toolbar_layout = QGridLayout(toolbar)
|
||||
|
||||
self.pass_button = QPushButton(self.get_text('pass_button'), toolbar)
|
||||
# self.pass_button.setDisabled(True)
|
||||
self.pass_button.clicked.connect(self.cmd_pass)
|
||||
self.pass_button.setFocus()
|
||||
toolbar_layout.addWidget(self.pass_button, 0, 0)
|
||||
|
||||
self.fail_button = QPushButton(self.get_text('fail_button'), toolbar)
|
||||
# self.fail_button.setDisabled(True)
|
||||
self.fail_button.clicked.connect(self.cmd_fail)
|
||||
toolbar_layout.addWidget(self.fail_button, 0, 1)
|
||||
|
||||
content_layout.addWidget(toolbar)
|
||||
|
||||
self.window.setCentralWidget(content)
|
||||
|
||||
# Move to center
|
||||
# screen = QGuiApplication.primaryScreen()
|
||||
# if screen:
|
||||
# screen_geometry = screen.geometry()
|
||||
# window_geometry = self.window.geometry()
|
||||
# x = (screen_geometry.width() - window_geometry.width()) // 2
|
||||
# y = (screen_geometry.height() - window_geometry.height()) // 2
|
||||
# self.window.move(x, y)
|
||||
|
||||
# self.window.show()
|
||||
self.window.showFullScreen()
|
||||
|
||||
self.app.exec_()
|
||||
|
||||
def _get_text(self, key):
|
||||
if self.languages:
|
||||
lang = self.languages.get(self.current_lang)
|
||||
if lang is not None:
|
||||
text = lang.get(key)
|
||||
if text is not None:
|
||||
return text
|
||||
|
||||
return 'Undefined'
|
||||
|
||||
def cmd_pass(self):
|
||||
global result
|
||||
|
||||
# self.status.showMessage('Stopping...')
|
||||
result = True
|
||||
self.app.quit()
|
||||
|
||||
def cmd_fail(self):
|
||||
global result
|
||||
|
||||
# self.status.showMessage('Stopping...')
|
||||
result = False
|
||||
self.app.quit()
|
||||
|
||||
class LCDTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'LCDTest': 'MIPI屏',
|
||||
'test_lcd': '彩色条纹',
|
||||
'title': 'MIPI屏',
|
||||
'test_step': '''1. 观察MIPI屏彩色条纹是否符合预期
|
||||
'''
|
||||
},
|
||||
'en': {
|
||||
'LCDTest': 'MIPI Screen',
|
||||
'test_lcd': 'Color Bar',
|
||||
'title': 'MIPI Screen',
|
||||
'test_step': '''1. 观察MIPI屏彩色条纹是否符合预期
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
def test_lcd(self):
|
||||
global result
|
||||
|
||||
t = threading.Thread(target=LCDTestWindow, args=(self.LANGUAGES,))
|
||||
t.start()
|
||||
|
||||
cmd = 'modetest -M spacemit -s 136@127:1200x1920 -a -P 31@127:1200x1920+0+0@AR24'
|
||||
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
t.join()
|
||||
|
||||
if proc.poll() is None:
|
||||
print('Try to kill process...')
|
||||
proc.kill()
|
||||
|
||||
self.assertTrue(result)
|
152
deprecated/test_03_fan.py
Normal file
152
deprecated/test_03_fan.py
Normal file
|
@ -0,0 +1,152 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import threading
|
||||
import os
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QGuiApplication
|
||||
from PyQt5.QtWidgets import (
|
||||
QApplication,
|
||||
QMainWindow,
|
||||
QFrame,
|
||||
QVBoxLayout,
|
||||
QGroupBox,
|
||||
QLabel,
|
||||
QStatusBar,
|
||||
QPushButton,
|
||||
QGridLayout
|
||||
)
|
||||
|
||||
from cricket.lang import SimpleLang
|
||||
|
||||
result = False
|
||||
|
||||
class FanTestWindow(SimpleLang):
|
||||
def __init__(self, speed_routine, languages) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.speed_routine = speed_routine
|
||||
self.languages = languages
|
||||
|
||||
self.app = QApplication([])
|
||||
|
||||
self.window = QMainWindow()
|
||||
self.window.setWindowTitle(self._get_text('title'))
|
||||
# self.window.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||
|
||||
# Main content
|
||||
content = QFrame(self.window)
|
||||
content_layout = QVBoxLayout(content)
|
||||
|
||||
# Test step
|
||||
box = QGroupBox(self.get_text('test_step'), content)
|
||||
box_layout = QVBoxLayout(box)
|
||||
|
||||
label = QLabel(self._get_text('test_step'), box)
|
||||
box_layout.addWidget(label)
|
||||
|
||||
content_layout.addWidget(box)
|
||||
|
||||
# Status
|
||||
# self.status = QStatusBar(content)
|
||||
# self.status.showMessage('Not running')
|
||||
# content_layout.addWidget(self.status)
|
||||
|
||||
# Toolbar
|
||||
toolbar = QFrame(content)
|
||||
toolbar_layout = QGridLayout(toolbar)
|
||||
|
||||
self.speed_button = QPushButton(self.get_text('speed_button'), toolbar)
|
||||
self.speed_button.clicked.connect(self.cmd_speed)
|
||||
self.speed_button.setFocus()
|
||||
toolbar_layout.addWidget(self.speed_button, 0, 0)
|
||||
|
||||
self.pass_button = QPushButton(self.get_text('pass_button'), toolbar)
|
||||
self.pass_button.setDisabled(True)
|
||||
self.pass_button.clicked.connect(self.cmd_pass)
|
||||
toolbar_layout.addWidget(self.pass_button, 0, 1)
|
||||
|
||||
self.fail_button = QPushButton(self.get_text('fail_button'), toolbar)
|
||||
self.fail_button.setDisabled(True)
|
||||
self.fail_button.clicked.connect(self.cmd_fail)
|
||||
toolbar_layout.addWidget(self.fail_button, 0, 2)
|
||||
|
||||
content_layout.addWidget(toolbar)
|
||||
|
||||
self.window.setCentralWidget(content)
|
||||
|
||||
# Move to center
|
||||
# screen = QGuiApplication.primaryScreen()
|
||||
# if screen:
|
||||
# screen_geometry = screen.geometry()
|
||||
# window_geometry = self.window.geometry()
|
||||
# x = (screen_geometry.width() - window_geometry.width()) // 2
|
||||
# y = (screen_geometry.height() - window_geometry.height()) // 2
|
||||
# self.window.move(x, y)
|
||||
|
||||
# self.window.show()
|
||||
self.window.showFullScreen()
|
||||
|
||||
self.app.exec_()
|
||||
|
||||
def _get_text(self, key):
|
||||
if self.languages:
|
||||
lang = self.languages.get(self.current_lang)
|
||||
if lang is not None:
|
||||
text = lang.get(key)
|
||||
if text is not None:
|
||||
return text
|
||||
|
||||
return 'Undefined'
|
||||
|
||||
def cmd_speed(self):
|
||||
self.speed_routine()
|
||||
self.pass_button.setDisabled(False)
|
||||
self.fail_button.setDisabled(False)
|
||||
|
||||
def cmd_pass(self):
|
||||
global result
|
||||
|
||||
# self.status.showMessage('Stopping...')
|
||||
result = True
|
||||
self.app.quit()
|
||||
|
||||
def cmd_fail(self):
|
||||
global result
|
||||
|
||||
# self.status.showMessage('Stopping...')
|
||||
result = False
|
||||
self.app.quit()
|
||||
|
||||
class FanTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'FanTest': '风扇',
|
||||
'test_speed': '变速',
|
||||
'title': '风扇',
|
||||
'test_step': '''1. 检查风扇是否正常转动
|
||||
2. 点击变速,检查风扇转速是否随之变化
|
||||
'''
|
||||
},
|
||||
'en': {
|
||||
'FanTest': 'Fan',
|
||||
'test_speed': 'Speed',
|
||||
'title': 'Fan',
|
||||
'test_step': '''1. 检查风扇是否正常转动
|
||||
2. 点击变速,检查风扇转速是否随之变化
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
def _speed_routine(self):
|
||||
pass
|
||||
|
||||
def test_speed(self):
|
||||
global result
|
||||
|
||||
t = threading.Thread(target=FanTestWindow, args=(self._speed_routine,
|
||||
self.LANGUAGES,))
|
||||
t.start()
|
||||
t.join()
|
||||
|
||||
self.assertTrue(result)
|
182
deprecated/test_03_gpio.py
Normal file
182
deprecated/test_03_gpio.py
Normal file
|
@ -0,0 +1,182 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import threading
|
||||
import os
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QGuiApplication
|
||||
from PyQt5.QtWidgets import (
|
||||
QApplication,
|
||||
QMainWindow,
|
||||
QFrame,
|
||||
QVBoxLayout,
|
||||
QGroupBox,
|
||||
QLabel,
|
||||
QStatusBar,
|
||||
QPushButton,
|
||||
QGridLayout
|
||||
)
|
||||
|
||||
from cricket.lang import SimpleLang
|
||||
|
||||
result = False
|
||||
|
||||
class GPIOTestWindow(SimpleLang):
|
||||
def __init__(self, languages) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.languages = languages
|
||||
|
||||
self.app = QApplication([])
|
||||
|
||||
self.window = QMainWindow()
|
||||
self.window.setWindowTitle(self._get_text('title'))
|
||||
# self.window.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||
|
||||
# Main content
|
||||
content = QFrame(self.window)
|
||||
content_layout = QVBoxLayout(content)
|
||||
|
||||
# Test step
|
||||
box = QGroupBox(self.get_text('test_step'), content)
|
||||
box_layout = QVBoxLayout(box)
|
||||
|
||||
label = QLabel(self._get_text('test_step'), box)
|
||||
box_layout.addWidget(label)
|
||||
|
||||
content_layout.addWidget(box)
|
||||
|
||||
# Status
|
||||
# self.status = QStatusBar(content)
|
||||
# self.status.showMessage('Not running')
|
||||
# content_layout.addWidget(self.status)
|
||||
|
||||
# Toolbar
|
||||
toolbar = QFrame(content)
|
||||
toolbar_layout = QGridLayout(toolbar)
|
||||
|
||||
self.pass_button = QPushButton(self.get_text('pass_button'), toolbar)
|
||||
# self.pass_button.setDisabled(True)
|
||||
self.pass_button.clicked.connect(self.cmd_pass)
|
||||
self.pass_button.setFocus()
|
||||
toolbar_layout.addWidget(self.pass_button, 0, 0)
|
||||
|
||||
self.fail_button = QPushButton(self.get_text('fail_button'), toolbar)
|
||||
# self.fail_button.setDisabled(True)
|
||||
self.fail_button.clicked.connect(self.cmd_fail)
|
||||
toolbar_layout.addWidget(self.fail_button, 0, 1)
|
||||
|
||||
content_layout.addWidget(toolbar)
|
||||
|
||||
self.window.setCentralWidget(content)
|
||||
|
||||
# Move to center
|
||||
# screen = QGuiApplication.primaryScreen()
|
||||
# if screen:
|
||||
# screen_geometry = screen.geometry()
|
||||
# window_geometry = self.window.geometry()
|
||||
# x = (screen_geometry.width() - window_geometry.width()) // 2
|
||||
# y = (screen_geometry.height() - window_geometry.height()) // 2
|
||||
# self.window.move(x, y)
|
||||
|
||||
# self.window.show()
|
||||
self.window.showFullScreen()
|
||||
|
||||
self.app.exec_()
|
||||
|
||||
def _get_text(self, key):
|
||||
if self.languages:
|
||||
lang = self.languages.get(self.current_lang)
|
||||
if lang is not None:
|
||||
text = lang.get(key)
|
||||
if text is not None:
|
||||
return text
|
||||
|
||||
return 'Undefined'
|
||||
|
||||
def cmd_pass(self):
|
||||
global result
|
||||
|
||||
# self.status.showMessage('Stopping...')
|
||||
result = True
|
||||
self.app.quit()
|
||||
|
||||
def cmd_fail(self):
|
||||
global result
|
||||
|
||||
# self.status.showMessage('Stopping...')
|
||||
result = False
|
||||
self.app.quit()
|
||||
|
||||
class GPIOTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'GPIOTest': 'GPIO',
|
||||
'test_gpio': '开关灯',
|
||||
'title': 'GPIO',
|
||||
'test_step': '''1. 观察26 pin连接器灯是否全亮
|
||||
'''
|
||||
},
|
||||
'en': {
|
||||
'GPIOTest': 'GPIO',
|
||||
'test_gpio': '开关灯',
|
||||
'title': 'GPIO',
|
||||
'test_step': '''1. 观察26 pin连接器灯是否全亮
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
def _export(self, gpios):
|
||||
export_file = '/sys/class/gpio/export'
|
||||
self.assertTrue(os.path.exists(export_file))
|
||||
for gpio in gpios:
|
||||
try:
|
||||
with open(export_file, 'w') as f:
|
||||
f.write(gpio)
|
||||
except:
|
||||
self.fail(f'Export gpio{gpio} fail')
|
||||
|
||||
def _out(self, gpios, value):
|
||||
for gpio in gpios:
|
||||
try:
|
||||
with open(f'/sys/class/gpio/gpio{gpio}/direction', 'w') as f:
|
||||
f.write('out')
|
||||
with open(f'/sys/class/gpio/gpio{gpio}/value', 'w') as f:
|
||||
f.write(value)
|
||||
except:
|
||||
self.fail(f'Set gpio{gpio} fail')
|
||||
|
||||
def _unexport(self, gpios):
|
||||
unexport_file = '/sys/class/gpio/unexport'
|
||||
self.assertTrue(os.path.exists(unexport_file))
|
||||
for gpio in gpios:
|
||||
try:
|
||||
with open(unexport_file, 'w') as f:
|
||||
f.write(gpio)
|
||||
except:
|
||||
self.fail(f'Unexport gpio{gpio} fail')
|
||||
|
||||
def test_gpio(self):
|
||||
global result
|
||||
|
||||
t = threading.Thread(target=GPIOTestWindow, args=(self.LANGUAGES,))
|
||||
t.start()
|
||||
|
||||
# turn on
|
||||
gpios = [
|
||||
'47', '48', '49', '50', '51', '52',
|
||||
'70', '71', '72', '73', '74',
|
||||
'75', '76', '77', '78',
|
||||
'90', '91', '92',
|
||||
]
|
||||
|
||||
self._export(gpios)
|
||||
self._out(gpios, '1')
|
||||
|
||||
t.join()
|
||||
|
||||
# turn off
|
||||
self._out(gpios, '0')
|
||||
self._unexport(gpios)
|
||||
|
||||
self.assertTrue(result)
|
|
@ -31,7 +31,8 @@ class SpeakerTest(TestCase):
|
|||
|
||||
bell_file = '/opt/factorytest/res/nocturne.wav'
|
||||
cmd = f'aplay -Dhw:1,0 -r 48000 -f S16_LE {bell_file} > /dev/null'
|
||||
self.play_proc = subprocess.Popen(cmd, shell=True)
|
||||
self.play_proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
def _stop_routine(self):
|
||||
if self.play_proc.poll() is None:
|
|
@ -34,7 +34,8 @@ class MicTest(TestCase):
|
|||
timeout = 10
|
||||
record_file = '/tmp/record.wav'
|
||||
cmd = f'arecord -Dhw:1,0 -r 48000 -f S16_LE -d {timeout} {record_file}'
|
||||
self.record_proc = subprocess.Popen(cmd, shell=True)
|
||||
self.record_proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
def _stop_record(self):
|
||||
if self.record_proc.poll() is None:
|
||||
|
@ -48,7 +49,8 @@ class MicTest(TestCase):
|
|||
print(f'playback amixer: {result.returncode}')
|
||||
|
||||
cmd = 'aplay -Dhw:1,0 -r 48000 -f S16_LE /tmp/record.wav'
|
||||
self.playback_proc = subprocess.Popen(cmd, shell=True)
|
||||
self.playback_proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
def _stop_playback(self):
|
||||
if self.playback_proc.poll() is None:
|
|
@ -33,7 +33,8 @@ class HeadphonesTest(TestCase):
|
|||
|
||||
bell_file = '/opt/factorytest/res/nocturne.wav'
|
||||
cmd = f'aplay -Dhw:1,0 -r 48000 -f S16_LE {bell_file}'
|
||||
self.play_proc = subprocess.Popen(cmd, shell=True)
|
||||
self.play_proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
def _stop_routine(self):
|
||||
if self.play_proc.poll() is None:
|
|
@ -36,7 +36,8 @@ class MicrophoneTest(TestCase):
|
|||
timeout = 10
|
||||
record_file = '/tmp/record.wav'
|
||||
cmd = f'arecord -Dhw:1,0 -r 48000 -f S16_LE -d {timeout} {record_file}'
|
||||
self.record_proc = subprocess.Popen(cmd, shell=True)
|
||||
self.record_proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
def _stop_record(self):
|
||||
if self.record_proc.poll() is None:
|
||||
|
@ -50,7 +51,8 @@ class MicrophoneTest(TestCase):
|
|||
print(f'playback amixer: {result.returncode}')
|
||||
|
||||
cmd = 'aplay -Dhw:1,0 -r 48000 -f S16_LE /tmp/record.wav'
|
||||
self.playback_proc = subprocess.Popen(cmd, shell=True)
|
||||
self.playback_proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
def _stop_playback(self):
|
||||
if self.playback_proc.poll() is None:
|
19
deprecated/test_09_camera.py
Normal file
19
deprecated/test_09_camera.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import os
|
||||
|
||||
class CameraTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'CameraTest': '摄像头',
|
||||
'test_still': '拍照',
|
||||
},
|
||||
'en': {
|
||||
'CameraTest': 'Camera',
|
||||
'test_still': 'Still',
|
||||
}
|
||||
}
|
||||
|
||||
def test_still(self):
|
||||
self.assertTrue(os.path.exists('/tmp/cpp0_output_1920x1080_s1920.nv12'))
|
||||
self.assertTrue(os.path.exists('/tmp/raw_output0_3840x2160.raw'))
|
21
memtester.sh
Executable file
21
memtester.sh
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
|
||||
test_size=100M
|
||||
test_loop=1000
|
||||
|
||||
echo "Starting memtester..."
|
||||
memtester $test_size $test_loop &
|
||||
|
||||
# Get the process ID of the memtester instance
|
||||
memtester_pid=$!
|
||||
|
||||
# Wait for the process to finish
|
||||
wait $memtester_pid
|
||||
|
||||
# Check the exit status of memtester process
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "memtester test completed successfully."
|
||||
else
|
||||
echo "memtester test encountered an error or exited prematurely."
|
||||
echo none > /sys/class/leds/sys-led/trigger
|
||||
fi
|
69
res/camtest_sensor0_mode0.json
Normal file
69
res/camtest_sensor0_mode0.json
Normal file
|
@ -0,0 +1,69 @@
|
|||
{
|
||||
"tuning_server_enable":1,
|
||||
"show_fps":1,
|
||||
"auto_run": 1,
|
||||
"test_frame": 30,
|
||||
"dump_one_frame": 29,
|
||||
|
||||
"cpp_node": [
|
||||
{
|
||||
"name": "cpp0",
|
||||
"enable": 1,
|
||||
"format":"NV12",
|
||||
"src_from_file": 1,
|
||||
|
||||
"src_path":"/tmp/cpp_case_in_data/1920x1080/",
|
||||
"size_width":1280,
|
||||
"size_height":720,
|
||||
},
|
||||
{
|
||||
"name": "cpp1",
|
||||
"enable": 0,
|
||||
"format":"NV12",
|
||||
"src_from_file": 0,
|
||||
|
||||
"src_path":"/vendor/etc/camera/",
|
||||
"size_width":1920,
|
||||
"size_height":1080,
|
||||
},
|
||||
],
|
||||
|
||||
"isp_node":[
|
||||
{
|
||||
"name": "isp0",
|
||||
"enable": 1,
|
||||
"work_mode":"online",
|
||||
"format":"NV12",
|
||||
"out_width":1280,
|
||||
"out_height":720,
|
||||
|
||||
"sensor_name":"ov16a10_spm",
|
||||
"sensor_id" : 0,
|
||||
"sensor_work_mode":0,
|
||||
"fps":30,
|
||||
|
||||
"src_file":"/tmp/1920x1080_raw12_long_packed.vrf",
|
||||
"bit_depth": 12,
|
||||
"in_width":1920,
|
||||
"in_height":1080,
|
||||
},
|
||||
{
|
||||
"name": "isp1",
|
||||
"enable": 0,
|
||||
"work_mode":"offline_capture",
|
||||
"format":"NV12",
|
||||
"out_width":1600,
|
||||
"out_height":1200,
|
||||
|
||||
"src_file":"/tmp/1920x1080_raw12_long_packed.vrf",
|
||||
"bit_depth": 12,
|
||||
"in_width":1920,
|
||||
"in_height":1080,
|
||||
|
||||
"sensor_name":"gc2375h_spm",
|
||||
"sensor_id" : 1,
|
||||
"sensor_work_mode":0,
|
||||
"fps":30,
|
||||
},
|
||||
]
|
||||
}
|
BIN
res/canon.wav
Normal file
BIN
res/canon.wav
Normal file
Binary file not shown.
BIN
res/nocturne.wav
BIN
res/nocturne.wav
Binary file not shown.
BIN
res/start-play.wav
Normal file
BIN
res/start-play.wav
Normal file
Binary file not shown.
BIN
res/start-record.wav
Normal file
BIN
res/start-record.wav
Normal file
Binary file not shown.
BIN
res/stop-play.wav
Normal file
BIN
res/stop-play.wav
Normal file
Binary file not shown.
BIN
res/stop-record.wav
Normal file
BIN
res/stop-record.wav
Normal file
Binary file not shown.
8
stability
Executable file
8
stability
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
ROOT=$(dirname "$(readlink -f "$0")")
|
||||
|
||||
pushd $ROOT > /dev/null
|
||||
./stress-ng.sh &
|
||||
./memtester.sh &
|
||||
popd > /dev/null
|
18
stress-ng.sh
Executable file
18
stress-ng.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "Starting stress test..."
|
||||
stress-ng --cpu 6 --cpu-method all --cpu-load 50 --metrics-brief &
|
||||
|
||||
# Get the process ID of the stress-ng instance
|
||||
stress_ng_pid=$!
|
||||
|
||||
# Wait for the process to finish
|
||||
wait $stress_ng_pid
|
||||
|
||||
# Check the exit status of stress-ng process
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Stress test completed successfully."
|
||||
else
|
||||
echo "Stress test encountered an error or exited prematurely."
|
||||
echo none > /sys/class/leds/sys-led/trigger
|
||||
fi
|
19
tests/auto/test_01_ctp.py
Normal file
19
tests/auto/test_01_ctp.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import os
|
||||
|
||||
class CTPTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'CTPTest': '触摸屏',
|
||||
'test_read_model': '读取型号'
|
||||
},
|
||||
'en': {
|
||||
'CTPTest': 'CTP',
|
||||
'test_read_model': 'Read model'
|
||||
}
|
||||
}
|
||||
|
||||
def test_read_model(self):
|
||||
model_file = '/sys/devices/platform/soc/d4018800.i2c/i2c-6/6-005d/productinfo'
|
||||
self.assertTrue(os.path.exists(model_file))
|
21
tests/auto/test_03_mini_pcie_sata.py
Normal file
21
tests/auto/test_03_mini_pcie_sata.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
#import usb.core
|
||||
|
||||
class MiniPCIeTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'MiniPCIeTest': 'Mini PCIe to SATA',
|
||||
'test_read_model': '读取型号'
|
||||
},
|
||||
'en': {
|
||||
'MiniPCIeTest': 'Mini PCIe to SATA',
|
||||
'test_read_model': 'Read model'
|
||||
}
|
||||
}
|
||||
|
||||
def test_read_model(self):
|
||||
model_file = '/sys/bus/pci/devices/0002:01:00.0/ata1/host0/target0:0:0/0:0:0:0/model'
|
||||
self.assertTrue(os.path.exists(model_file))
|
|
@ -19,6 +19,7 @@ class UDiskTest(TestCase):
|
|||
u3_hub_dir = '/sys/devices/platform/soc/soc:usb3@0/c0a00000.dwc3/xhci-hcd.0.auto/usb3/3-1/'
|
||||
self.assertTrue(os.path.exists(f'{u2_hub_dir}/product'))
|
||||
self.assertTrue(os.path.exists(f'{u3_hub_dir}/product'))
|
||||
# self.assertTrue(os.path.exists(f'{u3_hub_dir}/3-1.2/product'))
|
||||
# self.assertTrue(os.path.exists(f'{u3_hub_dir}/3-1.3/product'))
|
||||
self.assertTrue(os.path.exists(f'{u3_hub_dir}/3-1.4/product'))
|
||||
self.assertTrue(os.path.exists(f'{u2_hub_dir}/2-1.1/product'))
|
||||
self.assertTrue(os.path.exists(f'{u2_hub_dir}/2-1.3/product'))
|
||||
self.assertTrue(os.path.exists(f'{u3_hub_dir}/3-1.2/product'))
|
||||
self.assertTrue(os.path.exists(f'{u3_hub_dir}/3-1.4/product'))
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import os
|
||||
|
||||
class EEPROMTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'EEPROMTest': 'EEPROM',
|
||||
'test_read': '读取数据'
|
||||
},
|
||||
'en': {
|
||||
'EEPROMTest': 'EEPROM',
|
||||
'test_read': 'Read data'
|
||||
}
|
||||
}
|
||||
|
||||
def test_read(self):
|
||||
eeprom_file = '/sys/devices/platform/soc/d4012000.i2c/i2c-2/2-0050/eeprom'
|
||||
self.assertTrue(os.path.exists(eeprom_file))
|
||||
try:
|
||||
with open(eeprom_file, 'rb') as f:
|
||||
f.read(8)
|
||||
except:
|
||||
self.fail('Read fail')
|
|
@ -1,12 +1,13 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import os
|
||||
import time
|
||||
import socket
|
||||
import struct
|
||||
import fcntl
|
||||
import subprocess
|
||||
|
||||
from dns.resolver import Resolver
|
||||
|
||||
class Eth0Test(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
|
@ -35,8 +36,9 @@ class Eth0Test(TestCase):
|
|||
|
||||
def test_ping(self):
|
||||
ifname = 'eth0'
|
||||
ping = f'ping -I {ifname} -c 3 baidu.com'
|
||||
timeout = 10
|
||||
site = 'baidu.com'
|
||||
ping = f'ping -I {ifname} -c 3 {site}'
|
||||
timeout = 15
|
||||
|
||||
i = 0
|
||||
while i < timeout:
|
||||
|
@ -54,7 +56,11 @@ class Eth0Test(TestCase):
|
|||
try:
|
||||
ip = self.get_ip(ifname)
|
||||
print(f'{ifname}: {ip}')
|
||||
break
|
||||
if ip.startswith('169.254.'):
|
||||
time.sleep(1)
|
||||
i += 1
|
||||
else:
|
||||
break
|
||||
except:
|
||||
time.sleep(1)
|
||||
i += 1
|
||||
|
@ -62,6 +68,21 @@ class Eth0Test(TestCase):
|
|||
if i == timeout:
|
||||
self.fail('Get ip timeout')
|
||||
|
||||
i = 0
|
||||
while i < timeout:
|
||||
try:
|
||||
resolver = Resolver()
|
||||
answer = resolver.query(site)
|
||||
if answer:
|
||||
print(f'nameserver: {answer.nameserver}')
|
||||
break
|
||||
except:
|
||||
time.sleep(1)
|
||||
i += 1
|
||||
|
||||
if i == timeout:
|
||||
self.fail('DNS query timeout')
|
||||
|
||||
try:
|
||||
result = subprocess.run(ping, capture_output=True, shell=True, timeout=timeout)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import os
|
||||
import time
|
||||
import socket
|
||||
import struct
|
||||
import fcntl
|
||||
import subprocess
|
||||
|
||||
from dns.resolver import Resolver
|
||||
|
||||
class Eth1Test(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
|
@ -35,8 +36,9 @@ class Eth1Test(TestCase):
|
|||
|
||||
def test_ping(self):
|
||||
ifname = 'eth1'
|
||||
ping = f'ping -I {ifname} -c 3 baidu.com'
|
||||
timeout = 10
|
||||
site = 'baidu.com'
|
||||
ping = f'ping -I {ifname} -c 3 {site}'
|
||||
timeout = 15
|
||||
|
||||
i = 0
|
||||
while i < timeout:
|
||||
|
@ -54,7 +56,11 @@ class Eth1Test(TestCase):
|
|||
try:
|
||||
ip = self.get_ip(ifname)
|
||||
print(f'{ifname}: {ip}')
|
||||
break
|
||||
if ip.startswith('169.254.'):
|
||||
time.sleep(1)
|
||||
i += 1
|
||||
else:
|
||||
break
|
||||
except:
|
||||
time.sleep(1)
|
||||
i += 1
|
||||
|
@ -62,6 +68,21 @@ class Eth1Test(TestCase):
|
|||
if i == timeout:
|
||||
self.fail('Get ip timeout')
|
||||
|
||||
i = 0
|
||||
while i < timeout:
|
||||
try:
|
||||
resolver = Resolver()
|
||||
answer = resolver.query(site)
|
||||
if answer:
|
||||
print(f'nameserver: {answer.nameserver}')
|
||||
break
|
||||
except:
|
||||
time.sleep(1)
|
||||
i += 1
|
||||
|
||||
if i == timeout:
|
||||
self.fail('DNS query timeout')
|
||||
|
||||
try:
|
||||
result = subprocess.run(ping, capture_output=True, shell=True, timeout=timeout)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
|
|
|
@ -15,9 +15,13 @@ class BTTest(TestCase):
|
|||
}
|
||||
|
||||
def test_scan(self):
|
||||
scan = 'hcitool -i hci0 scan'
|
||||
# timeout: length * 1.28s
|
||||
# devices: numrsp
|
||||
scan = 'hcitool -i hci0 scan --length=5 --numrsp=1'
|
||||
try:
|
||||
result = subprocess.run(scan, capture_output=True, shell=True, timeout=10)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
proc = subprocess.run(scan, capture_output=True, text=True, shell=True, timeout=10)
|
||||
print(proc.stdout)
|
||||
self.assertEqual(proc.returncode, 0)
|
||||
self.assertGreater(len(proc.stdout.splitlines()), 1)
|
||||
except subprocess.TimeoutExpired:
|
||||
self.fail('Scan timeout')
|
||||
|
|
53
tests/auto/test_09_wifi.py
Normal file
53
tests/auto/test_09_wifi.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
class WiFiTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'WiFiTest': 'WiFi',
|
||||
'test_scan': '扫描'
|
||||
},
|
||||
'en': {
|
||||
'WiFiTest': 'WiFi',
|
||||
'test_scan': 'Scan'
|
||||
}
|
||||
}
|
||||
|
||||
def _wpa_cli(self, command):
|
||||
timeout = 10
|
||||
cmd = f'wpa_cli -p/var/run/wpa_supplicant -iwlan0 {command}'
|
||||
proc = subprocess.run(cmd, capture_output=True, text=True, shell=True, timeout=timeout)
|
||||
print(f'Create wpa_cli subprocess run {command} return {proc.returncode}')
|
||||
return proc.returncode, proc.stdout
|
||||
|
||||
def test_scan(self):
|
||||
try:
|
||||
timeout = 10
|
||||
cmd = 'pidof wpa_supplicant'
|
||||
proc = subprocess.run(cmd, capture_output=True, text=True, shell=True, timeout=timeout)
|
||||
if proc.returncode:
|
||||
cmd = 'wpa_supplicant -B -Dnl80211 -iwlan0 -c/etc/wpa_supplicant.conf'
|
||||
proc = subprocess.run(cmd, capture_output=True, text=True, shell=True, timeout=timeout)
|
||||
print(f'Create wpa_supplicant subprocess return {proc.returncode}')
|
||||
self.assertEqual(proc.returncode, 0)
|
||||
|
||||
rc, out = self._wpa_cli('scan')
|
||||
print(out)
|
||||
self.assertEqual(rc, 0)
|
||||
|
||||
i = 0
|
||||
while i < timeout:
|
||||
rc, out = self._wpa_cli('scan_results')
|
||||
print(out)
|
||||
self.assertEqual(rc, 0)
|
||||
if len(out.splitlines()) > 1:
|
||||
break
|
||||
time.sleep(1)
|
||||
i += 1
|
||||
|
||||
if i == timeout:
|
||||
self.fail('scan results without ap')
|
||||
except subprocess.TimeoutExpired:
|
||||
self.fail('Scan failed')
|
32
tests/auto/test_10_4g_module.py
Normal file
32
tests/auto/test_10_4g_module.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
#import usb.core
|
||||
|
||||
class USB4GModuleTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'USB4GModuleTest': '4G模块',
|
||||
'test_read_product': '读取型号'
|
||||
},
|
||||
'en': {
|
||||
'USB4GModuleTest': '4G Moduel',
|
||||
'test_read_product': 'Read product name'
|
||||
}
|
||||
}
|
||||
|
||||
def test_read_product(self):
|
||||
product_file = '/sys/devices/platform/soc/c0980100.ehci1/usb1/1-1/product'
|
||||
self.assertTrue(os.path.exists(product_file))
|
||||
|
||||
try:
|
||||
timeout = 10
|
||||
cmd = 'mmcli -m 0'
|
||||
proc = subprocess.run(cmd, shell=True, capture_output=True,
|
||||
text=True, timeout=timeout)
|
||||
print(f'Create mmcli subprocess return {proc.returncode}')
|
||||
self.assertEqual(proc.returncode, 0)
|
||||
self.assertNotIn(proc.stdout, 'sim-missing')
|
||||
except:
|
||||
self.fail('Create mmcli subprocess failed')
|
|
@ -1 +1 @@
|
|||
MODULE_NAME = {'zh': '手动测试项', 'en': 'Manual Test Item'}
|
||||
MODULE_NAME = {'zh': '人工判断项', 'en': 'Manual Test Item'}
|
23
tests/manual/test_01_lcd.py
Normal file
23
tests/manual/test_01_lcd.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import subprocess
|
||||
|
||||
class LCDTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'LCDTest': 'MIPI屏',
|
||||
'test_lcd': '彩色条纹'
|
||||
},
|
||||
'en': {
|
||||
'LCDTest': 'MIPI Screen',
|
||||
'test_lcd': 'Color Bar'
|
||||
}
|
||||
}
|
||||
|
||||
def test_lcd(self):
|
||||
try:
|
||||
cmd = 'modetest -M spacemit -s 136@127:1200x1920 -a -P 31@127:1200x1920+0+0@AR24'
|
||||
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
except:
|
||||
self.fail('Create modetest subprocess fail')
|
24
tests/manual/test_02_hdmi_audio.py
Normal file
24
tests/manual/test_02_hdmi_audio.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import subprocess
|
||||
|
||||
class HDMIAudioTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'HDMIAudioTest': 'HDMI Audio',
|
||||
'test_hdmi_auido': '播放一段音乐'
|
||||
},
|
||||
'en': {
|
||||
'HDMIAudioTest': 'HDMI Audio',
|
||||
'test_hdmi_auido': 'Play a piece of music'
|
||||
}
|
||||
}
|
||||
|
||||
def test_hdmi_auido(self):
|
||||
try:
|
||||
music_file = '/opt/factorytest/res/canon.wav'
|
||||
cmd = f'aplay -Dhw:0,0 -r 48000 -f S16_LE {music_file}'
|
||||
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
except:
|
||||
self.fail('Create subprocess fail')
|
25
tests/manual/test_03_fan.py
Normal file
25
tests/manual/test_03_fan.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import subprocess
|
||||
|
||||
class FanTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'FanTest': '风扇',
|
||||
'test_speed': '开关'
|
||||
},
|
||||
'en': {
|
||||
'FanTest': 'Fan',
|
||||
'test_speed': 'On/Off',
|
||||
'title': 'Fan'
|
||||
}
|
||||
}
|
||||
|
||||
def test_speed(self):
|
||||
try:
|
||||
gpio = 79
|
||||
cmd = f'/opt/factorytest/utils/fan.sh {gpio}'
|
||||
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
except:
|
||||
self.fail('Create fan.sh subprocess failed')
|
25
tests/manual/test_03_gpio.py
Normal file
25
tests/manual/test_03_gpio.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
from unittest import TestCase
|
||||
|
||||
import subprocess
|
||||
|
||||
class GPIOTest(TestCase):
|
||||
LANGUAGES = {
|
||||
'zh': {
|
||||
'GPIOTest': 'GPIO',
|
||||
'test_gpio': '开灯'
|
||||
},
|
||||
'en': {
|
||||
'GPIOTest': 'GPIO',
|
||||
'test_gpio': 'Turn on light'
|
||||
}
|
||||
}
|
||||
|
||||
def test_gpio(self):
|
||||
try:
|
||||
gpios = '47 48 49 50 51 52 70 71 72 73 74 75 76 77 78 90 91 92'
|
||||
cmd = f'/opt/factorytest/utils/gpio.sh {gpios}'
|
||||
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
except:
|
||||
self.fail('Create gpio subprocess fail')
|
||||
|
12
utils/fan.sh
Executable file
12
utils/fan.sh
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
echo $1 > /sys/class/gpio/export
|
||||
echo out > /sys/class/gpio/gpio$1/direction
|
||||
|
||||
while true
|
||||
do
|
||||
echo 1 > /sys/class/gpio/gpio$1/value
|
||||
sleep 5
|
||||
echo 0 > /sys/class/gpio/gpio$1/value
|
||||
sleep 5
|
||||
done
|
8
utils/gpio.sh
Executable file
8
utils/gpio.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
for gpio in "$@"
|
||||
do
|
||||
echo $gpio > /sys/class/gpio/export
|
||||
echo out > /sys/class/gpio/gpio$gpio/direction
|
||||
echo 1 > /sys/class/gpio/gpio$gpio/value
|
||||
done
|
Loading…
Add table
Reference in a new issue