CLI: unify device handling.

Provides AddDeviceArgument() function for CLI commands to add a device
to the commandline. The main benefits are:
 1. The help message will be the same for all tools.
 2. Automatic selection between a positional or optional argument.

`cros` devices arguments should normally be positional to keep backwards
compatibility, but `brillo` device arguments need to be optional so that
a default device can be provided if it is unspecified.

BUG=brillo:82, brillo:620, brillo:623
TEST=cbuildbot/run_tests

Change-Id: Id491097310671e73a6a4742b53d47dfdf392b7e1
Reviewed-on: https://chromium-review.googlesource.com/263988
Reviewed-by: Yiming Chen <yimingc@chromium.org>
Commit-Queue: David Pursell <dpursell@chromium.org>
Trybot-Ready: David Pursell <dpursell@chromium.org>
Tested-by: David Pursell <dpursell@chromium.org>
diff --git a/cli/command_unittest.py b/cli/command_unittest.py
index 77f082f..cee07ad 100644
--- a/cli/command_unittest.py
+++ b/cli/command_unittest.py
@@ -29,7 +29,7 @@
     print('Just testing')
 
 
-class TestCommandTest(cros_test_lib.TestCase):
+class TestCommandTest(cros_test_lib.MockTestCase):
   """This test class tests that Commands method."""
 
   def testParserSetsCommandClass(self):
@@ -58,6 +58,26 @@
     else:
       self.fail('Invalid command was accepted by the CommandDecorator')
 
+  def testCrosAddDeviceArgument(self):
+    """Tests CliCommand.AddDeviceArgument() for `cros`."""
+    self.PatchObject(command, '_GetToolset', return_value='cros')
+    parser = argparse.ArgumentParser()
+    command.CliCommand.AddDeviceArgument(parser)
+    # cros should have a positional device argument.
+    parser.parse_args(['device'])
+    with self.assertRaises(SystemExit):
+      parser.parse_args(['--device', 'device'])
+
+  def testBrilloAddDeviceArgument(self):
+    """Tests CliCommand.AddDeviceArgument() for `brillo`."""
+    self.PatchObject(command, '_GetToolset', return_value='brillo')
+    parser = argparse.ArgumentParser()
+    command.CliCommand.AddDeviceArgument(parser)
+    # brillo should have an optional device argument.
+    with self.assertRaises(SystemExit):
+      parser.parse_args(['device'])
+    parser.parse_args(['--device', 'device'])
+
 
 class MockCommand(partial_mock.PartialMock):
   """Mock class for a generic CLI command."""