6 Commits

Author SHA1 Message Date
Your Name
40afa507a7 add battery control 2025-06-19 00:56:14 +00:00
Casper Chang
18d97d7272 add timestamp to stress_test.py 2025-06-18 13:49:10 +08:00
Your Name
c7ed176903 add output on console 2025-06-12 04:58:36 +00:00
Your Name
911c033eb8 add get system info method 2025-06-12 00:16:10 +00:00
Your Name
a102e2e564 add stress test python script 2025-06-11 03:18:35 +00:00
Your Name
3605885994 add scripts 2025-05-22 08:39:49 +00:00
4 changed files with 326 additions and 50 deletions

View File

@@ -2,17 +2,20 @@
_board_name=$1
_mount_dir=$2
echo "INFO: Stop Servod"
stop-servod
if [ -z "$_board_name" ]; then
echo "please enter board namd and mount dir"
exit 1
fi
if [ -z "$_mount_dir" ]; then
echo "start servod without share folder mounted"
echo "please enter mount dir, I usually using the dir /home/${USER}/chrome/ToT/src/scripts"
echo "start-servod --channel=release --mount=${_mount_dir}:/tmp/firmware_to_flash -n flashing_servod --board=${_board_name} -p 9999"
echo "INFO: start servod without share folder mounted"
echo "INFO: please enter mount dir, I usually using the dir /home/${USER}/chrome/ToT/src/scripts"
echo "INFO: start-servod --channel=release --mount=${_mount_dir}:/tmp/firmware_to_flash -n flashing_servod --board=${_board_name} -p 9999"
start-servod --channel=release --board=${_board_name} -p 9999
else
echo "start-servod --channel=release --mount=${_mount_dir}:/tmp/firmware_to_flash -n flashing_servod --board=${_board_name} -p 9999"
echo "INFO: start-servod --channel=release --mount=${_mount_dir}:/tmp/firmware_to_flash -n flashing_servod --board=${_board_name} -p 9999"
start-servod --channel=release --mount=${_mount_dir}:/tmp/firmware_to_flash -n flashing_servod --board=${_board_name} -p 9999
fi

217
stress_test.py Executable file
View File

@@ -0,0 +1,217 @@
#!/usr/bin/env python3
import subprocess
import argparse
import time
import sys
from datetime import datetime
def log(message):
"""Helper function to log messages with timestamp."""
print(f"{datetime.now().strftime('%H:%M:%S')} - {message}")
def run_ssh_command(ip, command, password="test0000", timeout=300, retries=3):
"""Execute an SSH command using sshpass with retries and timeout."""
ssh_cmd = f'sshpass -p {password} ssh -o StrictHostKeyChecking=no root@{ip} "{command}"'
for attempt in range(1, retries + 1):
try:
result = subprocess.run(
ssh_cmd,
shell=True,
capture_output=True,
text=True,
check=True,
timeout=timeout
)
return result.stdout.strip(), result.stderr.strip()
except subprocess.TimeoutExpired:
log(f"SSH command timed out after {timeout} seconds (attempt {attempt}/{retries}): {command}")
if attempt == retries:
return None, "Timeout expired"
except subprocess.CalledProcessError as e:
log(f"SSH command error (attempt {attempt}/{retries}): {e}, stderr: {e.stderr}")
if attempt == retries:
return None, e.stderr
time.sleep(5) # Wait before retrying
return None, "Failed after retries"
def manage_battery_level(ip, check_interval=10):
"""Monitor battery level and control charging based on thresholds using ectool chargestate."""
log(f"\nManaging battery level for {ip}...")
while True:
# Get battery percentage from ectool chargestate show
stdout, stderr = run_ssh_command(ip, "ectool chargestate show | grep 'batt_state_of_charge' | awk '{print $3}'")
if stdout and stdout.strip().isdigit():
battery_level = int(stdout.strip())
log(f"Current battery level: {battery_level}%")
# Check if battery > 90%
if battery_level > 90:
log("Battery > 90%, initiating discharge mode...")
stdout, stderr = run_ssh_command(ip, "ectool chargecontrol discharge")
if stderr:
log(f"Failed to set discharge mode: {stderr}")
else:
log("Discharge mode set successfully")
# Check if battery <= 30%
elif battery_level <= 30:
log("Battery <= 30%, switching to normal mode...")
stdout, stderr = run_ssh_command(ip, "ectool chargecontrol normal")
if stderr:
log(f"Failed to set normal mode: {stderr}")
else:
log("Normal mode set successfully")
return # Exit after returning to normal mode
else:
log(f"Battery level {battery_level}% is within acceptable range")
else:
log(f"Failed to retrieve battery level: {stderr}")
return # Exit on failure to get battery status
# Wait before next check
time.sleep(check_interval)
def get_system_info(ip):
"""Retrieve system information using crossystem and cat /etc/lsb-release."""
log(f"\nCollecting system information for {ip}...")
# Run crossystem
log("\n--- crossystem output ---")
stdout, stderr = run_ssh_command(ip, "crossystem")
if stdout:
log(stdout)
else:
log(f"Failed to retrieve crossystem info: {stderr}")
# Run cat /etc/lsb-release
log("\n--- /etc/lsb-release output ---")
stdout, stderr = run_ssh_command(ip, "cat /etc/lsb-release")
if stdout:
log(stdout)
else:
log(f"Failed to retrieve /etc/lsb-release: {stderr}")
log("\n")
def get_last_eventlog_line(ip):
"""Retrieve the last line of /var/log/eventlog.txt."""
command = "tail -n 1 /var/log/eventlog.txt"
stdout, stderr = run_ssh_command(ip, command)
return stdout if stdout else None
def run_firmware_update(ip, timeout=300):
"""Run the firmware update command and check for success."""
command = "/usr/local/chromeos-firmwareupdate_joxer_r132 -m factory"
log(f"Firmware update command: {command}")
stdout, stderr = run_ssh_command(ip, command, timeout=timeout)
# log stdout and stderr
# log(f"\n--- stdout ---\n{stdout if stdout else 'No stdout'}")
# log(f"\n--- stderr ---\n{stderr if stderr else 'No stderr'}")
if stdout is None:
log(f"Firmware update failed: No output received (timeout or error).")
return False
if "Firmware updater exits successfully" not in stdout:
log(f"Firmware update failed: Success message not found. Output: {stdout}, Error: {stderr}")
return False
return True
def reboot_device(ip):
"""Send reboot command to the device and verify it's back online using ping."""
command = "reboot"
run_ssh_command(ip, command)
log(f"Reboot command sent to {ip}. Waiting for device to restart...")
max_attempts = 3
wait_time = 60 # Total wait time in seconds
ping_interval = 5 # Seconds between ping attempts
time.sleep(wait_time)
for attempt in range(1, max_attempts + 1):
log(f"Ping attempt {attempt}/{max_attempts}...")
start_time = time.time()
while time.time() - start_time < wait_time:
try:
# Attempt to ping the device
subprocess.run(
f"ping -c 1 {ip}",
shell=True,
capture_output=True,
text=True,
check=True,
)
log(f"Device {ip} is back online.")
return True
except subprocess.CalledProcessError:
time.sleep(ping_interval) # Wait before next ping
log(f"Ping attempt {attempt} failed.")
log(f"Device {ip} did not respond to ping after {max_attempts} attempts.")
return False
def main():
# Parse command-line arguments
parser = argparse.ArgumentParser(description="Stress test script for firmware update")
parser.add_argument("--remote", required=True, help="IP address of the DUT")
parser.add_argument("--loops", type=int, default=30, help="Number of test loops")
args = parser.parse_args()
ip = args.remote
loops = args.loops
failures = 0
get_system_info(ip)
for i in range(1, loops + 1):
log(f"\nStarting loop {i}/{loops}...")
manage_battery_level(ip)
# Step 1: Get initial last line of eventlog
initial_log = get_last_eventlog_line(ip)
if not initial_log:
log("Failed to retrieve initial event log. Aborting loop.")
failures += 1
return
log(f"Initial event log line: {initial_log}")
# Step 2: Run firmware update
log("Running firmware update...")
if not run_firmware_update(ip):
log("Firmware update failed. Aborting loop.")
failures += 1
return False
# Step 4: Check if event log changed
log("Checking event log before reboot...")
time.sleep(10)
final_log = get_last_eventlog_line(ip)
if not final_log:
log("Failed to retrieve final event log. Aborting loop.")
failures += 1
return False
log(f"Final event log line: {final_log}")
if final_log == initial_log:
log("Event log did not change after firmware update!")
failures += 1
else:
log(f"Event log updated. New line: {final_log}")
return False
# Step 3: Reboot device
if True != reboot_device(ip):
return False
# Summary
log(f"\nTest completed. Total loops: {loops}, Failures: {failures}")
if failures > 0:
sys.exit(1)
if __name__ == "__main__":
main()

92
test.log Normal file
View File

@@ -0,0 +1,92 @@
Collecting system information for 192.168.50.173...
--- crossystem output ---
arch = x86 # [RO/str] Platform architecture
backup_nvram_request = 1 # [RW/int] Backup the nvram somewhere at the next boot. Cleared on success.
battery_cutoff_request = 0 # [RW/int] Cut off battery and shutdown on next boot
block_devmode = 0 # [RW/int] Block all use of developer mode
board_id = 2 # [RO/int] Board hardware revision number
clear_tpm_owner_done = 1 # [RW/int] Clear TPM owner done
clear_tpm_owner_request = 0 # [RW/int] Clear TPM owner on next boot
cros_debug = 1 # [RO/int] OS should allow debug features
dbg_reset = 0 # [RW/int] Debug reset mode request
debug_build = 1 # [RO/int] OS image built for debug features
dev_boot_altfw = 0 # [RW/int] Enable developer mode alternate bootloader
dev_boot_signed_only = 0 # [RW/int] Enable developer mode boot only from official kernels
dev_boot_usb = 0 # [RW/int] Enable developer mode boot from external disk (USB/SD)
dev_default_boot = disk # [RW/str] Default boot from disk, altfw or usb
dev_enable_udc = 0 # [RW/int] Enable USB Device Controller
devsw_boot = 1 # [RO/int] Developer switch position at boot
devsw_cur = 1 # [RO/int] Developer switch current position
diagnostic_request = 0 # [RW/int] Request diagnostic rom run on next boot
disable_dev_request = 0 # [RW/int] Disable virtual dev-mode on next boot
ecfw_act = RW # [RO/str] Active EC firmware
post_ec_sync_delay = 0 # [RW/int] Short delay after EC software sync (persistent, writable, eve only)
fw_prev_result = unknown # [RO/str] Firmware result of previous boot
fw_prev_tried = A # [RO/str] Firmware tried on previous boot (A or B)
fw_result = unknown # [RW/str] Firmware result this boot
fw_tried = A # [RO/str] Firmware tried this boot (A or B)
fw_try_count = 0 # [RW/int] Number of times to try fw_try_next
fw_try_next = A # [RW/str] Firmware to try next (A or B)
fw_vboot2 = 1 # [RO/int] 1 if firmware was selected by vboot2 or 0 otherwise
fwb_tries = 0 # [RW/int] Try firmware B count
fwid = Google_Joxer.15217.608.0 # [RO/str] Active firmware ID
fwupdate_tries = 0 # [RW/int] Times to try OS firmware update (inside kern_nv)
hwid = JOXER TEST 8200 # [RO/str] Hardware ID
inside_vm = 0 # [RO/int] Running in a VM?
kern_nv = 0x0000 # [RO/int] Non-volatile field for kernel use
kernel_max_rollforward = 0xfffffffe # [RW/int] Max kernel version to store into TPM
kernkey_vfy = hash # [RO/str] Type of verification done on kernel keyblock
loc_idx = 0 # [RW/int] Localization index for firmware screens
mainfw_act = A # [RO/str] Active main firmware
mainfw_type = developer # [RO/str] Active main firmware type
minios_priority = A # [RW/str] miniOS image to try first (A or B)
nvram_cleared = 0 # [RW/int] Have NV settings been lost? Write 0 to clear
display_request = 0 # [RW/int] Should we initialize the display at boot?
phase_enforcement = (error) # [RO/int] Board should have full security settings applied
recovery_reason = 0 # [RO/int] Recovery mode reason for current boot
recovery_request = 0 # [RW/int] Recovery mode request
recovery_subcode = 0 # [RW/int] Recovery reason subcode
recoverysw_boot = 0 # [RO/int] Recovery switch position at boot
recoverysw_cur = (error) # [RO/int] Recovery switch current position
recoverysw_ec_boot = 0 # [RO/int] Recovery switch position at EC boot
ro_fwid = Google_Joxer.15217.439.0 # [RO/str] Read-only firmware ID
tpm_attack = 0 # [RW/int] TPM was interrupted since this flag was cleared
tpm_fwver = 0x00010001 # [RO/int] Firmware version stored in TPM
tpm_kernver = 0x00010001 # [RO/int] Kernel version stored in TPM
tpm_rebooted = 0 # [RO/int] TPM requesting repeated reboot
tried_fwb = 0 # [RO/int] Tried firmware B before A this boot
try_ro_sync = 0 # [RO/int] try read only software sync
vdat_flags = 0x00008810 # [RO/int] Flags from VbSharedData
wipeout_request = 0 # [RW/int] Firmware requested factory reset (wipeout)
wpsw_cur = 0 # [RO/int] Firmware write protect hardware switch current position
--- /etc/lsb-release output ---
CHROMEOS_RELEASE_APPID={A5F9E181-D0BE-4D6D-B67D-125069233535}
CHROMEOS_BOARD_APPID={A5F9E181-D0BE-4D6D-B67D-125069233535}
CHROMEOS_CANARY_APPID={90F229CE-83E2-4FAF-8479-E368A34938B1}
DEVICETYPE=REFERENCE
CHROMEOS_RELEASE_NAME=Chrome OS
CHROMEOS_AUSERVER=https://tools.google.com/service/update2
CHROMEOS_DEVSERVER=
CHROMEOS_RELEASE_BUILDER_PATH=factory-nissa-15199.B-nissa/R109-15199.624.0
CHROMEOS_RELEASE_KEYSET=devkeys
CHROMEOS_RELEASE_TRACK=testimage-channel
CHROMEOS_RELEASE_BUILD_TYPE=Official Build
CHROMEOS_RELEASE_DESCRIPTION=15199.624.0 (Official Build) dev-channel nissa test
CHROMEOS_RELEASE_BOARD=nissa
CHROMEOS_RELEASE_BRANCH_NUMBER=624
CHROMEOS_RELEASE_BUILD_NUMBER=15199
CHROMEOS_RELEASE_CHROME_MILESTONE=109
CHROMEOS_RELEASE_PATCH_NUMBER=0
CHROMEOS_RELEASE_VERSION=15199.624.0
GOOGLE_RELEASE=15199.624.0
CHROMEOS_RELEASE_UNIBUILD=1
Starting loop 1/100...
Initial event log line: 326 | 2025-06-11 00:31:45 | Firmware vboot info | boot_mode=Developer | fw_tried=A | fw_try_count=0 | fw_prev_tried=A | fw_prev_result=Unknown
Running firmware update...
Firmware update command: /usr/local/chromeos-firmwareupdate_joxer_r132 -m factory

View File

@@ -1,47 +1,11 @@
tast.firmware.SoftwareSync.dev
tast.firmware.DeepSleep
tast.firmware.BootMode.rec_to_dev
tast.firmware.BootMode.rec_to_dev_gbb
tast.firmware.CorruptBothFWSigABAndEC.dev
tast.firmware.CorruptBothFWSigABAndEC.normal
tast.firmware.CorruptBothFWSigABAndEC.dev
tast.firmware.ECADC
tast.firmware.ECBattery
tast.firmware.ECCbi
tast.firmware.ECChargingState.discharge
tast.firmware.ECChargingState.full_charge
tast.firmware.ECKeyboard.usb_keyboard
tast.firmware.ECKeyboard.convertible
tast.firmware.ECLaptopMode
tast.firmware.ECLidShutdown
tast.firmware.ECLidSwitch.check_key_press
tast.firmware.ECLidSwitch.open_lid_to_boot
tast.firmware.ECLidSwitch.close_lid_to_shutd
tast.firmware.ECLidSwitch.open_lid_to_unsusp
tast.firmware.ECPowerButton
tast.firmware.ECPowerG3.shutdown
tast.firmware.ECPowerG3.power_button
tast.firmware.ECPowerG3.power_state
tast.firmware.ECPowerG3.power_state_usb_plug
tast.firmware.ECPowerG3.power_state_snk
tast.firmware.ECPowerG3.power_state_rec_off
tast.firmware.ECPowerG3.power_button_from_ro
tast.firmware.ECReboot
tast.firmware.ECSharedMemory
tast.firmware.ECSize
tast.firmware.ECTabletMode
tast.firmware.ECUSBPorts.usb_pins_on_lid_clo
tast.firmware.ECUSBPorts.usb_pins_on_shutdow
tast.firmware.ECVerifyVK
tast.firmware.ECWakeSource.power_btn
tast.firmware.ECWakeSource.keypress
tast.firmware.ECWakeSource.lid
tast.firmware.ECWakeSource.usb_keyboard
tast.firmware.ECWatchdog
tast.firmware.Eventlog.suspend_resume
tast.firmware.Fmap.ec
tast.firmware.FWCorruptRecoveryCache.normal
tast.firmware.ScreenWakeTabletMode
tast.firmware.SoftwareSync.normal
tast.firmware.USBResumeFromSuspend
tast.firmware.WriteProtect.ec
tast.power.SuspendPerf.fw_qual
tast.firmware.ECPowerG3.power_state
tast.firmware.ServoGBBFlags
tast.firmware.WriteProtect.ec
tast.firmware.WriteProtect.ec_dev
tast.firmware.FwScreenPressPower.invalid_screen
tast.firmware.FwmpDevDisableBoot
tast.firmware.VerityCorruptRootfs.dev
tast.firmware.WriteProtect.ap_dev
tast.firmware.WriteProtectCrossystem.dev