[fidldev] Useability improvements

- Fail and print error message when an unknown explicit test or
  regen target is provided. Previously unknown arguments would
  get ignored.
- Make it possible to use `fidldev regen` outside of FUCHSIA_DIR
  by using an absolute path for BUILD_DIR instead of a relative one.

Change-Id: Id481693ec421cc75d18a52cdda96b882a5b10d93
Reviewed-on: https://fuchsia-review.googlesource.com/c/fidl-misc/+/409095
Reviewed-by: Mitchell Kember <mkember@google.com>
diff --git a/fidldev/env.py b/fidldev/env.py
index f34ecfc..e5fbe8e 100644
--- a/fidldev/env.py
+++ b/fidldev/env.py
@@ -10,7 +10,7 @@
 assert FUCHSIA_DIR.exists()
 
 with open(FUCHSIA_DIR / ".fx-build-dir") as f:
-    BUILD_DIR = f.read().strip()
+    BUILD_DIR = os.path.join(FUCHSIA_DIR, f.read().strip())
 
 if sys.platform.startswith('linux'):
     PLATFORM = 'linux'
@@ -19,6 +19,3 @@
 else:
     print("Unsupported platform: " + sys.platform)
     sys.exit(1)
-
-with open(FUCHSIA_DIR / (BUILD_DIR + '.zircon') / 'args.gn') as f:
-    MODE = 'asan' if 'asan' in f.read() else 'clang'
diff --git a/fidldev/fidldev.py b/fidldev/fidldev.py
index 3bd6c06..edd9bef 100755
--- a/fidldev/fidldev.py
+++ b/fidldev/fidldev.py
@@ -49,6 +49,9 @@
 
 """
 
+VALID_TEST_TARGETS = [name for (name, _) in test_.TEST_GROUPS] + ['all']
+VALID_REGEN_TARGETS = [name for (name, _) in regen.REGEN_TARGETS] + ['all']
+
 
 def test(args):
     success = True
@@ -56,17 +59,23 @@
         if not args.no_regen:
             util.print_warning(
                 'explicit test targets provided, skipping regen...')
-        success = test_.test_explicit(
-            args.targets, not args.no_build, args.dry_run, args.interactive,
-            args.fx_test_args)
+        unknown_args = set(args.targets) - set(VALID_TEST_TARGETS)
+        if unknown_args:
+            util.print_err(
+                'Error: unknown test targets {}'.format(unknown_args))
+            print('use `fidldev test --help` to print list of valid targets')
+            sys.exit(1)
+        success = test_.test_explicit(args.targets, not args.no_build,
+                                      args.dry_run, args.interactive,
+                                      args.fx_test_args)
     else:
         changed_files = util.get_changed_files()
         if not args.no_regen:
             regen.regen_changed(changed_files, not args.no_build, args.dry_run)
             changed_files = util.get_changed_files()
-        success = test_.test_changed(
-            changed_files, not args.no_build, args.dry_run, args.interactive,
-            args.fx_test_args)
+        success = test_.test_changed(changed_files, not args.no_build,
+                                     args.dry_run, args.interactive,
+                                     args.fx_test_args)
         if args.dry_run:
             print_dryrun_warning()
     if not success:
@@ -75,6 +84,12 @@
 
 def regen_cmd(args):
     if args.targets:
+        unknown_args = set(args.targets) - set(VALID_REGEN_TARGETS)
+        if unknown_args:
+            util.print_err(
+                'Error: unknown regen targets {}'.format(unknown_args))
+            print('use `fidldev regen --help` to print list of valid targets')
+            sys.exit(1)
         regen.regen_explicit(args.targets, not args.no_build, args.dry_run)
     else:
         changed_files = util.get_changed_files()
@@ -84,10 +99,9 @@
 
 
 def print_dryrun_warning():
-    print(
-        'NOTE: dry run is conservative and assumes that regen will '
-        'always change files. If goldens do not change during an actual '
-        'run, fewer tests/regen scripts may be run.')
+    print('NOTE: dry run is conservative and assumes that regen will '
+          'always change files. If goldens do not change during an actual '
+          'run, fewer tests/regen scripts may be run.')
 
 
 parser = argparse.ArgumentParser(
@@ -98,14 +112,13 @@
 
 test_parser = subparsers.add_parser("test", help="Test your FIDL changes")
 test_parser.set_defaults(func=test)
-test_targets = [name for (name, _) in test_.TEST_GROUPS] + ['all']
 test_parser.add_argument(
     'targets',
     metavar='target',
     nargs='*',
     help=
     "Manually specify targets to regen, where a target is one of {}. Omit positional arguments to test based on changed files"
-    .format(test_targets))
+    .format(VALID_TEST_TARGETS))
 test_parser.add_argument(
     "--dry-run",
     "-n",
@@ -140,14 +153,13 @@
 
 regen_parser = subparsers.add_parser("regen", help="Run regen commands")
 regen_parser.set_defaults(func=regen_cmd)
-regen_targets = [name for (name, _) in regen.REGEN_TARGETS] + ['all']
 regen_parser.add_argument(
     'targets',
     metavar='target',
     nargs='*',
     help=
     "Manually specify targets to regen, where a target is one of {}. Omit positional arguments to regen based on changed files"
-    .format(regen_targets))
+    .format(VALID_REGEN_TARGETS))
 regen_parser.add_argument(
     "--dry-run",
     "-n",
diff --git a/fidldev/test_util.py b/fidldev/test_util.py
index c70ca7c..826c234 100644
--- a/fidldev/test_util.py
+++ b/fidldev/test_util.py
@@ -6,11 +6,10 @@
 
 # mock out these environment consts before importing anything else
 MOCK_FUCHSIA_DIR = 'fuchsia_dir'
-MOCK_BUILD_DIR = 'out/default'
+MOCK_BUILD_DIR = 'fuchsia_dir/out/default'
 env.FUCHSIA_DIR = MOCK_FUCHSIA_DIR
 env.BUILD_DIR = MOCK_BUILD_DIR
 env.PLATFORM = 'linux'
-env.MODE = 'clang'
 
 import fidldev
 import util
diff --git a/fidldev/util.py b/fidldev/util.py
index a07e250..1bfeed6 100644
--- a/fidldev/util.py
+++ b/fidldev/util.py
@@ -1,7 +1,7 @@
 import os
 import subprocess
 
-from env import FUCHSIA_DIR, BUILD_DIR, MODE, PLATFORM
+from env import FUCHSIA_DIR, BUILD_DIR, PLATFORM
 
 TOPAZ_DIR = os.path.join(FUCHSIA_DIR, 'topaz')
 GO_DIR = os.path.join(FUCHSIA_DIR, 'third_party/go')
@@ -22,7 +22,7 @@
     'tools/fidl/fidlgen_syzkaller',
 ]
 
-TEST_FIDLC = os.path.join(FUCHSIA_DIR, BUILD_DIR, 'host_x64/fidl-compiler')
+TEST_FIDLC = os.path.join(BUILD_DIR, 'host_x64/fidl-compiler')
 FIDLGEN_TEST_TARGETS = FIDLGEN_BACKEND_DIRS
 FIDLGEN_DART_TEST_TARGET = '//topaz/bin/fidlgen_dart'
 HLCPP_TEST_TARGET = '//sdk/lib/fidl'
@@ -65,8 +65,8 @@
     retcode = subprocess.call(command, shell=isinstance(command, str))
     success = retcode == 0
     if exit_on_failure and not success:
-        print_err(
-            'Error: command failed with status {}! {}'.format(retcode, command))
+        print_err('Error: command failed with status {}! {}'.format(
+            retcode, command))
         exit(1)
     return success