1*9c5db199SXin Li# Autotest Best Practices 2*9c5db199SXin LiWhen the ChromeOS team started using autotest, we tried our best to figure out 3*9c5db199SXin Lihow to fit our code and our tests into the upstream style with little guidance 4*9c5db199SXin Liand poor documentation. This went poorly. With the benefit of hindsight, 5*9c5db199SXin Liwe’re going to lay out some best-practices that we’d like to enforce going 6*9c5db199SXin Liforward. In many cases, there is legacy code that contradicts this style; we 7*9c5db199SXin Lishould go through and refactor that code to fit these guidelines as time 8*9c5db199SXin Liallows. 9*9c5db199SXin Li 10*9c5db199SXin Li## Upstream Documentation 11*9c5db199SXin Li 12*9c5db199SXin LiThere is a sizeable volume of general Autotest documentation available on 13*9c5db199SXin Ligithub: 14*9c5db199SXin Lihttps://github.com/autotest/autotest/wiki 15*9c5db199SXin Li 16*9c5db199SXin Li## Coding style 17*9c5db199SXin Li 18*9c5db199SXin LiBasically PEP-8. See [docs/coding-style.md](coding-style.md) 19*9c5db199SXin Li 20*9c5db199SXin Li## Where should my code live? 21*9c5db199SXin Li 22*9c5db199SXin Li| Type of Code | Relative Path | 23*9c5db199SXin Li|---------------------------|-------------------------| 24*9c5db199SXin Li| client-side tests | client/site_tests/ | 25*9c5db199SXin Li| server-side tests | server/site_tests | 26*9c5db199SXin Li| common library code | client/common_lib/cros/ | 27*9c5db199SXin Li| server-only library code | server/cros | 28*9c5db199SXin Li 29*9c5db199SXin Li 30*9c5db199SXin Li## Writing tests 31*9c5db199SXin Li 32*9c5db199SXin LiAn autotest is really defined by its control file. A control file contains 33*9c5db199SXin Liimportant metadata about the test (name, author, description, duration, what 34*9c5db199SXin Lisuite it’s in, etc) and then pulls in and executes the actual test code. This 35*9c5db199SXin Litest code can be shared among multiple distinct test cases by parameterizing it 36*9c5db199SXin Liand passing those parameters in from separate control files. 37*9c5db199SXin Li 38*9c5db199SXin LiAutotests *must*: 39*9c5db199SXin Li 40*9c5db199SXin Li * Be self-contained: assume nothing about the condition of the device 41*9c5db199SXin Li * Be hermetic: requiring the Internet to be reachable in order for your test 42*9c5db199SXin Li to succeed is unacceptable. 43*9c5db199SXin Li * Be automatic: avoid user interaction and run-time specification of input 44*9c5db199SXin Li values. 45*9c5db199SXin Li * Be integration tests: if you can test the feature in a unit test (or a 46*9c5db199SXin Li chrome browser test), do so. 47*9c5db199SXin Li * Prefer object composition to inheritance: avoid subclassing test.test to 48*9c5db199SXin Li implement common functionality for multiple tests. Instead, create a class 49*9c5db199SXin Li that your tests can instantiate to perform common operations. This enables 50*9c5db199SXin Li us to write tests that use both PyAuto and Servo without dealing with 51*9c5db199SXin Li multiple inheritance, for example. 52*9c5db199SXin Li * Be deterministic: a test should not validate the timing of some operation. 53*9c5db199SXin Li Instead, write a test that records the timing in performance keyvals so that 54*9c5db199SXin Li we can track the numbers over time. 55*9c5db199SXin Li 56*9c5db199SXin LiAutotests *must not*: 57*9c5db199SXin Li 58*9c5db199SXin Li * Put significant logic in the control file: control files are really just 59*9c5db199SXin Li python, so one can put arbitrary logic in there. Don’t. Run your test 60*9c5db199SXin Li code, perhaps with some parameters. 61*9c5db199SXin Li 62*9c5db199SXin LiAutotests *may*: 63*9c5db199SXin Li 64*9c5db199SXin Li * Share parameterized fixtures: a test is defined by a control file. Control 65*9c5db199SXin Li files import and run test code, and can pass simple parameters to the code 66*9c5db199SXin Li they run through a well-specified interface. 67*9c5db199SXin Li 68*9c5db199SXin LiAutotest has a notion of both client-side tests and server-side tests. Code in 69*9c5db199SXin Lia client-side test runs only on the device under test (DUT), and as such isn’t 70*9c5db199SXin Licapable of maintaining state across reboots or handling a failed suspend/resume 71*9c5db199SXin Liand the like. If possible, an autotest should be written as a client-side 72*9c5db199SXin Litest. A ‘server’ test runs on the autotest server, but gets assigned a DUT 73*9c5db199SXin Lijust like a client-side test. It can use various autotest primitives (and 74*9c5db199SXin Lilibrary code written by the CrOS team) to manipulate that device. Most, if not 75*9c5db199SXin Liall, tests that use Servo or remote power management should be server-side 76*9c5db199SXin Litests, as an example. 77*9c5db199SXin Li 78*9c5db199SXin LiAdding a test involves putting a control file and a properly-written test 79*9c5db199SXin Liwrapper in the right place in the source tree. There are conventions that must 80*9c5db199SXin Libe followed, and a variety of primitives available for use. When writing any 81*9c5db199SXin Licode, whether client-side test, server-side test, or library, have a strong 82*9c5db199SXin Libias towards using autotest utility code. This keeps the codebase consistent. 83*9c5db199SXin Li 84*9c5db199SXin Li 85*9c5db199SXin Li## Writing a test 86*9c5db199SXin Li 87*9c5db199SXin LiThis section explains considerations and requirements for any autotest, whether 88*9c5db199SXin Liclient or server. 89*9c5db199SXin Li 90*9c5db199SXin Li### Control files 91*9c5db199SXin Li 92*9c5db199SXin LiUpstream documentation 93*9c5db199SXin LiOur local conventions for autotest control files deviate from the above a bit, 94*9c5db199SXin Libut the indication about which fields are mandatory still holds. 95*9c5db199SXin Li 96*9c5db199SXin Li| Variable | Required | Value | 97*9c5db199SXin Li|--------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 98*9c5db199SXin Li| AUTHOR | Yes | A comma-delimited string of at least one responsible engineer and a backup engineer -- or at worst a backup mailing list. i.e. AUTHOR = ‘msb, snanda’ | 99*9c5db199SXin Li| DEPENDENCIES | No | list of tags known to the HW test lab. | 100*9c5db199SXin Li| DOC | Yes | Long description of the test, pass/fail criteria | 101*9c5db199SXin Li| NAME | Yes | Display name of the test. Generally this is the directory where your test lives e.g. hardware_TPMCheck. If you are using multiple run_test calls in the same control file or multiple control files with one test wrapper in the same suite, problems arise with the displaying of your test name. crosbug.com/35795. When in doubt ask. | 102*9c5db199SXin Li| SYNC\_COUNT | No | Integer >= 1. Number of simultaneous devices needed for a test run. | 103*9c5db199SXin Li| TIME | Yes | Test duration: 'FAST' (<1m), 'MEDIUM' (<10m), 'LONG' (<20m), 'LENGTHY' (>30m) | 104*9c5db199SXin Li| TEST\_TYPE | Yes | Client or Server | 105*9c5db199SXin Li| ATTRIBUTES | No | Comma separated list of attribute tags to apply to this control file, used in composing suites. For instance, 'suite:foo, suite:bar'. | 106*9c5db199SXin Li 107*9c5db199SXin Li### Running tests in suites 108*9c5db199SXin Li 109*9c5db199SXin LiMake sure that the suite name is listed in `site_utils/attribute_allowlist.txt`, 110*9c5db199SXin Lithen add the appropriate attribute to the ATTRIBUTES field in tests that make 111*9c5db199SXin Liup the test suite. For instance: 112*9c5db199SXin Li 113*9c5db199SXin Li``` 114*9c5db199SXin Li... 115*9c5db199SXin LiATTRIBUTES = 'suite:suite-a, suite:suite-b' 116*9c5db199SXin Li... 117*9c5db199SXin Li``` 118*9c5db199SXin Li 119*9c5db199SXin Liwould indicate that the control file above should be run as part of both 120*9c5db199SXin Li`suite-a` and `suite-b`. 121*9c5db199SXin Li 122*9c5db199SXin Li### Pure python 123*9c5db199SXin Li 124*9c5db199SXin LiLie, cheat and steal to keep your tests in pure python. It will be easier to 125*9c5db199SXin Lidebug failures, it will be easier to generate meaningful error output, it will 126*9c5db199SXin Libe simpler to get your tests installed and run, and it will be simpler for the 127*9c5db199SXin Lilab team to build tools that allow you to quickly iterate. 128*9c5db199SXin Li 129*9c5db199SXin LiShelling out to existing command-line tools is done fairly often, and isn’t a 130*9c5db199SXin Literrible thing. The test author can wind up having to do a lot of output 131*9c5db199SXin Liparsing, which is often brittle, but this can be a decent tradeoff in lieu of 132*9c5db199SXin Lihaving to reimplement large pieces of functionality in python. 133*9c5db199SXin Li 134*9c5db199SXin LiNote that you will need to be sure that any commands you use are installed on 135*9c5db199SXin Lithe host. For a client-side test, “the host” means “the DUT”. For a 136*9c5db199SXin Liserver-side test, “the host” typically means “the system running autoserv”; 137*9c5db199SXin Lihowever, if you use SiteHost.run(), the command will run on the DUT. On the 138*9c5db199SXin Liserver, your tests will have access to all tools common to both a typical CrOS 139*9c5db199SXin Lichroot environment and standard Goobuntu. 140*9c5db199SXin Li 141*9c5db199SXin LiIf you want to use a tool on the DUT, it may be appropriate to include it as a 142*9c5db199SXin Lidependency of the chromeos-base/chromeos-test package. This ensures that the 143*9c5db199SXin Litool is pre-installed on every test image for every device, and will always be 144*9c5db199SXin Liavailable for use. Otherwise, the tool must be installed as an autotest “dep”. 145*9c5db199SXin Li 146*9c5db199SXin Li_Never install your own shell scripts and call them._ Anything you can do in 147*9c5db199SXin Lishell, you can do in python. 148*9c5db199SXin Li 149*9c5db199SXin Li### Reporting failures 150*9c5db199SXin Li 151*9c5db199SXin LiAutotest supports several kinds of failure statuses: 152*9c5db199SXin Li 153*9c5db199SXin Li| Status | Exception | Reason | 154*9c5db199SXin Li|----------|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 155*9c5db199SXin Li| WARN | error.TestWarn | error.TestWarn should be used when side effects to the test running are encountered but are not directly related to the test running. For example, if you are testing Wifi and powerd crashes. *Currently* there are not any clear usecases for this and error.TestWarn should be generally avoided until further notice. | 156*9c5db199SXin Li| TEST\_NA | error.TestNAError | This test does not apply in the current environment. | 157*9c5db199SXin Li| ERROR | error.TestError | The test was unable to validate the desired behavior. | 158*9c5db199SXin Li| FAIL | error.TestFail | The test determined the desired behavior failed to occur. | 159*9c5db199SXin Li 160*9c5db199SXin Li 161*9c5db199SXin Li### Considerations when writing client-side tests 162*9c5db199SXin Li 163*9c5db199SXin LiAll client-side tests authored at Google must live in the client/site\_tests sub-directory of the autotest source tree. 164*9c5db199SXin Li 165*9c5db199SXin Li###Compiling and executing binaries 166*9c5db199SXin Li 167*9c5db199SXin LiIt is possible to compile source that’s included with your test and use the 168*9c5db199SXin Liproducts at test runtime. The build infrastructure will compile this code for 169*9c5db199SXin Lithe appropriate target architecture and package it up along with the rest of 170*9c5db199SXin Liyour test’s resources, but this increases your development iteration time as 171*9c5db199SXin Liyou need to actually re-build and re-package your test to deploy it to the 172*9c5db199SXin Lidevice. While we hope to improve tooling support for this use case in the 173*9c5db199SXin Lifuture, avoiding this issue is the ideal. 174*9c5db199SXin Li 175*9c5db199SXin LiIf you can’t avoid this, here’s how to get your code compiled and installed as 176*9c5db199SXin Lia part of your test: 177*9c5db199SXin Li1. Create a src/ directory next to your control file. 178*9c5db199SXin Li2. Put your source, including its Makefile, in src/ 179*9c5db199SXin Li3. define a method in your test class called “setup(self)” that takes no arguments. 180*9c5db199SXin Li4. setup(self) should perform all tasks necessary to build your tool. There are some helpful utility functions in client/common_lib/utils.py. Trivial example: 181*9c5db199SXin Li 182*9c5db199SXin Li``` 183*9c5db199SXin Li def setup(self): 184*9c5db199SXin Li os.chdir(self.srcdir) 185*9c5db199SXin Li utils.make('OUT_DIR=.') 186*9c5db199SXin Li``` 187*9c5db199SXin Li 188*9c5db199SXin Li### Reusing code (“fixtures”) 189*9c5db199SXin Li 190*9c5db199SXin LiAny autotest is, essentially, a single usage of a re-usable test fixture. This 191*9c5db199SXin Liis because run\_once() in your test wrapper can take any arguments you want. As 192*9c5db199SXin Lisuch, multiple control files can re-use the same wrapper -- and should, where 193*9c5db199SXin Liit makes sense. 194*9c5db199SXin Li 195*9c5db199SXin Li### Considerations when writing server-side tests 196*9c5db199SXin Li 197*9c5db199SXin LiAll server-side tests authored at Google must live in the server/site\_tests 198*9c5db199SXin Lisub-directory of the autotest source tree. 199*9c5db199SXin Li 200*9c5db199SXin LiIt should be even easier to keep the server-side of a test in pure python, as 201*9c5db199SXin Liyou should simply be driving the DUT and verifying state. 202*9c5db199SXin Li 203*9c5db199SXin Li### When/why to write a server-side test 204*9c5db199SXin Li 205*9c5db199SXin LiServer-side tests are appropriate when some operation in the test can't be 206*9c5db199SXin Liexecuted on the DUT. The prototypical example is rebooting the DUT. Other 207*9c5db199SXin Liexamples include tests that manipulate the network around the DUT (e.g. WiFi 208*9c5db199SXin Litests), tests that power off the DUT, and tests that rely on a Servo attached 209*9c5db199SXin Lito the DUT. 210*9c5db199SXin Li 211*9c5db199SXin LiOne simple criterion for whether to write a server-side test is this: Is the 212*9c5db199SXin LiDUT an object that the test must manipulate? If the answer is “yes”, then a 213*9c5db199SXin Liserver-side test makes sense. 214*9c5db199SXin Li 215*9c5db199SXin Li### Control files for server-side tests 216*9c5db199SXin Li 217*9c5db199SXin LiServer-side tests commonly operate on the DUT as an object. Autotest 218*9c5db199SXin Lirepresents the DUT with an instance of class Host; the instance is constructed 219*9c5db199SXin Liand passed to the test from the control file. Creating the host object in the 220*9c5db199SXin Licontrol file can be done using certain definitions present in the global 221*9c5db199SXin Lienvironment of every control file: 222*9c5db199SXin Li 223*9c5db199SXin Li * Function hosts.create\_host() will create a host object from a string with 224*9c5db199SXin Li the name of the host (an IP address as a string is also acceptable). 225*9c5db199SXin Li * Variable machines is a list of the host names available to the test. 226*9c5db199SXin Li 227*9c5db199SXin LiBelow is a sample fragment for a control file that runs a simple server side test in parallel on all the hosts specified for the test. The fragment is a complete control file, except for the missing boilerplate comments and documentation definitions required in all control files. 228*9c5db199SXin Li 229*9c5db199SXin Li``` 230*9c5db199SXin Lidef run(machine): 231*9c5db199SXin Li host = hosts.create_host(machine) 232*9c5db199SXin Li job.run_test("platform_ServerTest", host=host) 233*9c5db199SXin Li 234*9c5db199SXin Liparallel_simple(run, machines) 235*9c5db199SXin Li``` 236*9c5db199SXin Li 237*9c5db199SXin LiNote: The sample above relies on a common convention that the run\_once() 238*9c5db199SXin Limethod of a server-side test defines an argument named host with a default 239*9c5db199SXin Livalue, e.g. 240*9c5db199SXin Li 241*9c5db199SXin Li``` 242*9c5db199SXin Lidef run_once(self, host=None): 243*9c5db199SXin Li # … test code goes here. 244*9c5db199SXin Li``` 245*9c5db199SXin Li 246*9c5db199SXin Li### Operations on Host objects 247*9c5db199SXin Li 248*9c5db199SXin LiA Host object supports various methods to operate on a DUT. Below is a short list of important methods supported by instances of Host: 249*9c5db199SXin Li 250*9c5db199SXin Li * run(command) - run a shell command on the host 251*9c5db199SXin Li * reboot() - reboot the host, and wait for it to be back on the network 252*9c5db199SXin Li * wait_up() - wait for the host to be active on the network 253*9c5db199SXin Li * wait_down() - wait until the host is no longer on the network, or until it is known to have rebooted. 254*9c5db199SXin Li 255*9c5db199SXin LiMore details, including a longer list of available methods, and more about how 256*9c5db199SXin Lithey work can be found in the Autotest documentation for autoserv and Autotest 257*9c5db199SXin Lidocumentation for Host. 258*9c5db199SXin Li 259*9c5db199SXin Li### Servo-based tests 260*9c5db199SXin Li 261*9c5db199SXin LiFor server-side tests that use a servo-attached DUT, the host object has a 262*9c5db199SXin Liservo attribute. If Autotest determines that the DUT has a Servo attached, the 263*9c5db199SXin Liservo attribute will be a valid instance of a Servo client object; otherwise 264*9c5db199SXin Lithe attribute will be None. 265*9c5db199SXin Li 266*9c5db199SXin LiFor a DUT in the lab, Autotest will automatically determine whether there is a 267*9c5db199SXin Liservo available; however, if a test requires Servo, its control file must have 268*9c5db199SXin Liadditional code to guarantee a properly initialized servo object on the host. 269*9c5db199SXin Li 270*9c5db199SXin LiBelow is a code snippet outlining the requirements; portions of the control file have been omitted for brevity: 271*9c5db199SXin Li 272*9c5db199SXin Li``` 273*9c5db199SXin Li# ... Standard boilerplate variable assignments... 274*9c5db199SXin LiDEPENDENCIES = "servo_state:WORKING" 275*9c5db199SXin Li# ... more standard boilerplate... 276*9c5db199SXin Li# servo_state:WORKING - servo is present and can provide required functionality 277*9c5db199SXin Li# servo_state:BROKEN - servo is present but cannot provide required functionality 278*9c5db199SXin Li 279*9c5db199SXin Liargs_dict = utils.args_to_dict(args) 280*9c5db199SXin Liservo_args = hosts.SiteHost.get_servo_arguments(args_dict) 281*9c5db199SXin Li 282*9c5db199SXin Lidef run(machine): 283*9c5db199SXin Li host = hosts.create_host(machine, servo_args=servo_args) 284*9c5db199SXin Li job.run_test("platform_SampleServoTest", host=host) 285*9c5db199SXin Li 286*9c5db199SXin Liparallel_simple(run, machines) 287*9c5db199SXin Li``` 288*9c5db199SXin Li 289*9c5db199SXin LiThe `DEPENDENCIES` setting guarantees that if the test is scheduled in the lab, 290*9c5db199SXin Liit will be assigned to a DUT that has a servo. 291*9c5db199SXin Li 292*9c5db199SXin LiThe setting of `servo_args` guarantees two distinct things: First, it forces 293*9c5db199SXin Lichecks that will make sure that the Servo is functioning properly; this 294*9c5db199SXin Liguarantees that the host's `servo` attribute will not be None. Second, the code 295*9c5db199SXin Liallows you to pass necessary servo specific command-line arguments to 296*9c5db199SXin Li`test_that`. 297*9c5db199SXin Li 298*9c5db199SXin LiIf the test control file follows the formula above, the test can be reliably called in a variety of ways: 299*9c5db199SXin Li * When used for hosts in the lab, the host’s servo object will use the servo attached to the host, and the test can assume that the servo object is not None. 300*9c5db199SXin Li * If you start servod manually on your desktop using the default port, you can use test_that without any special options. 301*9c5db199SXin Li * If you need to specify a non-default host or port number (e.g. because servod is remote, or because you have more than one servo board), you can specify them with commands like these: 302*9c5db199SXin Li 303*9c5db199SXin Li``` 304*9c5db199SXin Litest_that --args=”servo_host=...” … 305*9c5db199SXin Litest_that --args=”servo_port=...” … 306*9c5db199SXin Litest_that --args=”servo_host=... servo_port=...” ... 307*9c5db199SXin Li``` 308*9c5db199SXin Li 309*9c5db199SXin Li### Calling client-side tests from a server-side test 310*9c5db199SXin Li 311*9c5db199SXin LiCommonly, server-side tests need to do more on the DUT than simply run short 312*9c5db199SXin Lishell commands. In those cases, a client-side test should be written and 313*9c5db199SXin Liinvoked from the server-side test. In particular, a client side test allows 314*9c5db199SXin Lithe client side code to be written in Python that uses standard Autotest 315*9c5db199SXin Liinfrastructure, such as various utility modules or the logging infrastructure. 316*9c5db199SXin Li 317*9c5db199SXin LiBelow is a short snippet showing the standard form for calling a client-side 318*9c5db199SXin Litest from server-side code: 319*9c5db199SXin Li 320*9c5db199SXin Li``` 321*9c5db199SXin Lifrom autotest_lib.server import autotest 322*9c5db199SXin Li 323*9c5db199SXin Li # ... inside some function, e.g. in run_once() 324*9c5db199SXin Li client_at = autotest.Autotest(host) 325*9c5db199SXin Li client_at.run_test("platform_ClientTest") 326*9c5db199SXin Li``` 327*9c5db199SXin Li 328*9c5db199SXin Li### Writing library code 329*9c5db199SXin Li 330*9c5db199SXin LiThere is a large quantity of Chromium OS specific code in the autotest 331*9c5db199SXin Licodebase. Much of this exists to provide re-usable modules that enable tests 332*9c5db199SXin Lito talk to system services. The guidelines from above apply here as well. 333*9c5db199SXin LiThis code should be as pure python as possible, though it is reasonable to 334*9c5db199SXin Lishell out to command line tools from time to time. In some cases we’ve done 335*9c5db199SXin Lithis where we could (now) use the service’s DBus APIs directly. If you’re 336*9c5db199SXin Liadding code to allow tests to communicate with your service, it is strongly 337*9c5db199SXin Lirecommended that you use DBus where possible, instead of munging config files 338*9c5db199SXin Lidirectly or using command-line tools. 339*9c5db199SXin Li 340*9c5db199SXin LiCurrently, our library code lives in a concerning variety of places in the 341*9c5db199SXin Liautotest tree. This is due to a poor initial understanding of how to do 342*9c5db199SXin Lithings, and new code should follow the following conventions instead: 343*9c5db199SXin Li 344*9c5db199SXin Li * Used only in server-side tests: server/cros 345*9c5db199SXin Li * Used in both server- and client-side tests, or only client: 346*9c5db199SXin Li client/common\_lib/cros 347*9c5db199SXin Li 348*9c5db199SXin Li### Adding test deps 349*9c5db199SXin Li 350*9c5db199SXin LiThis does not refer to the optional `DEPENDENCIES` field in test control files. 351*9c5db199SXin LiRather, this section discusses how and when to use code/data/tools that are not 352*9c5db199SXin Lipre-installed on test images, and should (or can) not be included right in with 353*9c5db199SXin Lithe test source. 354*9c5db199SXin Li 355*9c5db199SXin LiUnfortunately, there is no hard-and-fast rule here. Generally, if this is some 356*9c5db199SXin Lismall tool or blob of data you need for a single test, you should include it as 357*9c5db199SXin Lidiscussed above in Writing client-side tests. If you’re writing the tool, and 358*9c5db199SXin Liit has use for developers as well as in one or more tests that you’re writing, 359*9c5db199SXin Lithen make it a first-class CrOS project. Write an ebuild, write unit tests, 360*9c5db199SXin Liand then add it to the test image by default. This can be done by RDEPENDing 361*9c5db199SXin Lion your new test package from the chromeos-test ebuild. 362*9c5db199SXin Li 363*9c5db199SXin LiIf your code/data falls in the middle (useful to several tests, not to devs), 364*9c5db199SXin Liand/or is large (hundreds of megabytes as opposed to tens) then using an 365*9c5db199SXin Liautotest ‘dep’ may be the right choice. Conceptually, an autotest test dep is 366*9c5db199SXin Lisimply another kind of archive that the autotest infrastructure knows how to 367*9c5db199SXin Lifetch and unpack. There are two components to including a dependency from an 368*9c5db199SXin Liautotest test -- setup during build time and installing it on your DUT when 369*9c5db199SXin Lirunning a test. The setup phase must be run from your tests setup() method 370*9c5db199SXin Lilike so: 371*9c5db199SXin Li 372*9c5db199SXin Li``` 373*9c5db199SXin Lidef setup(self): 374*9c5db199SXin Li self.job.setup_dep([‘mydep’]) 375*9c5db199SXin Li logging.debug(‘mydep is at %s’ % (os.path.join(self.autodir, 376*9c5db199SXin Li ‘deps/mydep’)) 377*9c5db199SXin Li``` 378*9c5db199SXin Li 379*9c5db199SXin LiThe above gets run when you “build” the test. 380*9c5db199SXin Li 381*9c5db199SXin LiThe other half of this equation is actually installing the dependency so you 382*9c5db199SXin Lican use it while running a test. To do this, add the following to either your 383*9c5db199SXin Lirun\_once or initialize methods: 384*9c5db199SXin Li 385*9c5db199SXin Li``` 386*9c5db199SXin Li dep = dep_name 387*9c5db199SXin Li dep_dir = os.path.join(self.autodir, 'deps', dep=dep) 388*9c5db199SXin Li self.job.install_pkg(dep, 'dep', dep_dir) 389*9c5db199SXin Li``` 390*9c5db199SXin Li 391*9c5db199SXin Li 392*9c5db199SXin LiYou can now reference the content of your dep using dep_dir. 393*9c5db199SXin Li 394*9c5db199SXin LiNow that you know how to include a dep, the next question is how to write one. 395*9c5db199SXin LiBefore you read further, you should check out client/deps/\* for many examples 396*9c5db199SXin Liof deps in our autotest tree. 397*9c5db199SXin Li 398*9c5db199SXin Li### Create a dep from a third-party package 399*9c5db199SXin Li 400*9c5db199SXin LiThere are many examples of how to do this in the client/deps directory already. 401*9c5db199SXin LiThe key component is to check in a tarball of the version of the dependency 402*9c5db199SXin Liyou’d like to include under client/deps/your\_dep. 403*9c5db199SXin Li 404*9c5db199SXin LiAll deps require a control file and an actual python module by the same name. 405*9c5db199SXin LiThey will also need a copy of common.py to import utils.update\_version. Both 406*9c5db199SXin Lithe control and common are straightforward, the python module does all the 407*9c5db199SXin Limagic. 408*9c5db199SXin Li 409*9c5db199SXin LiThe deps python module follows a standard convention: a setup function and a 410*9c5db199SXin Licall to utils.update\_version. update\_version is used instead of directly 411*9c5db199SXin Licalling setup as it maintains additional versioning logic ensuring setup is 412*9c5db199SXin Lionly done 1x per dep. The following is its method signature: 413*9c5db199SXin Li 414*9c5db199SXin Li``` 415*9c5db199SXin Lidef update_version(srcdir, preserve_srcdir, new_version, install, 416*9c5db199SXin Li *args, **dargs) 417*9c5db199SXin Li``` 418*9c5db199SXin Li 419*9c5db199SXin Li 420*9c5db199SXin LiNotably, install should be a pointer to your setup function and `*args` should 421*9c5db199SXin Libe filled in with params to said setup function. 422*9c5db199SXin Li 423*9c5db199SXin LiIf you are using a tarball, your setup function should look something like: 424*9c5db199SXin Li 425*9c5db199SXin Li``` 426*9c5db199SXin Lidef setup(tarball, my_dir) 427*9c5db199SXin Li utils.extract_tarball_to_dir(tarball, my_dir) 428*9c5db199SXin Li os.chdir(my_dir) 429*9c5db199SXin Li utils.make() # this assumes your tarball has a Makefile. 430*9c5db199SXin Li``` 431*9c5db199SXin Li 432*9c5db199SXin LiAnd you would invoke this with: 433*9c5db199SXin Li 434*9c5db199SXin Li``` 435*9c5db199SXin Liutils.update_version(os.getcwd(), True, version, setup, tarball_path, 436*9c5db199SXin Li os.getcwd()) 437*9c5db199SXin Li``` 438*9c5db199SXin Li 439*9c5db199SXin Li 440*9c5db199SXin LiNote: The developer needs to call this because def setup is a function they are 441*9c5db199SXin Lidefining that can take any number of arguments or install the dep in any way 442*9c5db199SXin Lithey see fit. The above example uses tarballs but some are distributed as 443*9c5db199SXin Listraight source under the src dir so their setup function only takes a top 444*9c5db199SXin Lilevel path. We could avoid this by forcing a convention but that would be 445*9c5db199SXin Liartificially constraining the deps mechanism. 446*9c5db199SXin Li 447*9c5db199SXin LiOnce you’ve created the dep, you will also have to add the dep to the 448*9c5db199SXin Liautotest-deps package in chromiumos-overlay/chromeos-base/autotest-deps, 449*9c5db199SXin Li‘cros\_workon start’ it, and re-emerge it. 450*9c5db199SXin Li 451*9c5db199SXin Li### Create a dep from other chrome-os packages 452*9c5db199SXin Li 453*9c5db199SXin LiOne can also create autotest deps from code that lives in other CrOS packages, 454*9c5db199SXin Lior from build products generated by other packages. This is similar as above 455*9c5db199SXin Libut you can reference code using the `CHROMEOS_ROOT` env var that points to the 456*9c5db199SXin Liroot of the CrOS source checkout, or the SYSROOT env var (which points to 457*9c5db199SXin Li/build/<board>) to refer to build products. Again, read the above. Here’s an 458*9c5db199SXin Liexample of the former with the files I want in 459*9c5db199SXin Lichromeos\_tree/chromite/my\_dep/\* where this will be the python code in 460*9c5db199SXin Liautotest/files/client/deps/my\_dep/my\_dep.py module. 461*9c5db199SXin Li 462*9c5db199SXin Li``` 463*9c5db199SXin Liimport common, os, shutil 464*9c5db199SXin Lifrom autotest_lib.client.bin import utils 465*9c5db199SXin Li 466*9c5db199SXin Liversion = 1 467*9c5db199SXin Li 468*9c5db199SXin Lidef setup(setup_dir): 469*9c5db199SXin Li my_dep_dir = os.path.join(os.environ['CHROMEOS_ROOT'], 'chromite', 470*9c5db199SXin Li 'buildbot') 471*9c5db199SXin Li shutil.copytree(my_dep_dir, setup_dir) 472*9c5db199SXin Li 473*9c5db199SXin Li 474*9c5db199SXin Liwork_dir = os.path.join(os.getcwd(), 'src') 475*9c5db199SXin Liutils.update_version(os.getcwd(), True, version, setup, work_dir) 476*9c5db199SXin Li``` 477