blob: 3e315354775ac99b12ccfa4a5145aef3d98eb316 [file] [log] [blame]
# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""A test to stress CPU, memory and disk.
Description
-----------
A test using `stressapptest <https://github.com/stressapptest/stressapptest>`_
to stress CPU, memory, and disk.
By default the system data partition (or the stateful partition for Chrome OS
devices) is used. However a long stress testing of disk may shorten eMMC or SSD
life, so you may want to set `disk_thread` argument to False if `seconds` is
pretty long.
Setting memory ratio may be tricky. If your system does not have enough free
memory (for example if you have lots of tests running in parallel) then the test
will fail, so usually you'll want to set `free_memory_only` argument to True.
However, if you start multiple tests at same time, other tests may allocate more
memory after the calculation of "free memory" is done, causing the test to fail.
To solve that, increase the argument `wait_secs` so the calculation of "free
memory" will be done when the memory usage is stabilized.
Test Procedure
--------------
This is an automated test without user interaction.
Start the test and it will run for the time specified in argument `seconds`, and
pass if no errors found; otherwise fail with error messages and logs, especially
if unexpected reboot or crash were found during execution.
Dependency
----------
- Need external program `stressapptest
<https://github.com/stressapptest/stressapptest>`_.
Examples
--------
To stress CPU, memory (90% of free memory), and the disk using stateful
partition for 60 seconds, add this in test list::
{
"pytest_name": "stressapptest"
}
To stress for one day without accessing disk::
{
"pytest_name": "stressapptest",
"args": {
"seconds": 86400,
"disk_thread": false
}
}
To stress using only two threads, and only run on cpu core 2 and 3::
{
"pytest_name": "stressapptest",
"args": {
"num_threads": 2,
"taskset_args": ["-c", "2,3"]
}
}
"""
import logging
import time
import unittest
import factory_common # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.test.utils import stress_manager
from cros.factory.utils.arg_utils import Arg
class StressAppTest(unittest.TestCase):
"""Run stressapptest to test the memory and disk is fine."""
ARGS = [
Arg('seconds', int,
'Time to execute the stressapptest.', default=60),
Arg('memory_ratio', float,
'Radio of memory to be used by stressapptest.',
default=0.9),
Arg('free_memory_only', bool,
'Only use free memory for test. When set to True, only '
'memory_radio * free_memory are used for stressapptest.',
default=True),
Arg('wait_secs', int,
'Time to wait in seconds before executing stressapptest.',
default=0),
Arg('disk_thread', bool,
'Stress disk using -f argument of stressapptest.',
default=True),
Arg('disk_thread_dir', str,
'Directory of disk thread file will be placed '
'(default to system stateful partition.)',
default=None),
Arg('max_errors', int,
'Number of errors to exit early.',
default=stress_manager.DEFAULT_MAX_ERRORS),
Arg('num_threads', int,
'Number of threads to be used. Default to number of cores.',
default=None),
Arg('taskset_args', list,
'Argument to taskset to change CPU affinity for stressapptest.',
default=None)
]
def setUp(self):
self.dut = device_utils.CreateDUTInterface()
def runTest(self):
# Wait other parallel tests memory usage to settle to a stable value, so
# stressapptest will not claim too much memory.
if self.args.wait_secs:
time.sleep(self.args.wait_secs)
try:
with stress_manager.StressManager(self.dut).Run(
duration_secs=self.args.seconds,
memory_ratio=self.args.memory_ratio,
free_memory_only=self.args.free_memory_only,
disk_thread=self.args.disk_thread,
disk_thread_dir=self.args.disk_thread_dir,
max_errors=self.args.max_errors,
num_threads=self.args.num_threads,
taskset_args=self.args.taskset_args):
pass
except stress_manager.StressManagerError as e:
logging.error('StressAppTest failed: %s', e)
raise