Enable doc tests on Fuchsia

Fargo will now cross compile and run code samples
in documentation.

Change-Id: I535b2f77d125040418509489e5deea002328f871
diff --git a/fargo-test/src/main.rs b/fargo-test/src/bin/hello.rs
similarity index 68%
rename from fargo-test/src/main.rs
rename to fargo-test/src/bin/hello.rs
index 8a4d087..d4c998c 100644
--- a/fargo-test/src/main.rs
+++ b/fargo-test/src/bin/hello.rs
@@ -2,14 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+use fargo_test::print_hello_world;
+
 fn main() {
-    println!("Hello, world!");
-    println!("Hello, world!");
-    println!("Hello, world!");
-    println!("Hello, world!");
-    println!("Hello, world!");
-    println!("Hello, world!");
-    println!("Hello, world!");
+    for _ in 0..6 {
+        print_hello_world();
+    }
 }
 
 #[cfg(test)]
diff --git a/fargo-test/src/lib.rs b/fargo-test/src/lib.rs
new file mode 100644
index 0000000..cfce2fd
--- /dev/null
+++ b/fargo-test/src/lib.rs
@@ -0,0 +1,11 @@
+/// Function that does what it says
+/// ```
+/// use fargo_test::print_hello_world;
+///
+/// for _ in 0..6 {
+///    print_hello_world();
+/// }
+/// ```
+pub fn print_hello_world() {
+    println!("Hello, world!");
+}
diff --git a/src/command_line.rs b/src/command_line.rs
index 67cce85..c821a00 100644
--- a/src/command_line.rs
+++ b/src/command_line.rs
@@ -11,7 +11,7 @@
     sdk::TargetOptions,
     write_config, FuchsiaConfig, RunCargoOptions, RunMode, DEFAULT_MOD_NAME,
 };
-use failure::{Error, ResultExt};
+use failure::{bail, Error, ResultExt};
 use std::path::PathBuf;
 use structopt::StructOpt;
 
@@ -222,7 +222,7 @@
 #[derive(Debug, StructOpt)]
 struct RunOnTarget {
     /// Path to the binary to run.
-    binary_to_run: String,
+    binary_to_run: Option<String>,
 
     /// Use run to run the binary.
     #[structopt(long)]
@@ -314,6 +314,14 @@
     #[structopt(long)]
     example: Option<String>,
 
+    /// Test only this library's documentation.
+    #[structopt(long)]
+    doc: bool,
+
+    /// Compile, but don't run tests.
+    #[structopt(long)]
+    no_run: bool,
+
     /// Arguments to pass to the test runner.
     #[structopt(long)]
     test_args: Option<String>,
@@ -356,6 +364,8 @@
     #[structopt(long, global = true)]
     manifest_path: Option<PathBuf>,
 
+    run_target_first: Option<String>,
+
     #[structopt(subcommand)]
     command: FargoCommand,
 }
@@ -573,8 +583,18 @@
                 run_on_target.run_with_sessionctl,
             );
 
+            let binary_to_run = if let Some(binary_to_run) = run_on_target.binary_to_run {
+                binary_to_run
+            } else {
+                if let Some(binary_to_run) = opt.run_target_first {
+                    binary_to_run
+                } else {
+                    bail!("The fargo test runner was not passed a binary to run")
+                }
+            };
+
             return run_program_on_target(
-                &run_on_target.binary_to_run,
+                &binary_to_run,
                 verbose,
                 run_on_target.nocapture,
                 &fuchsia_config,
@@ -670,7 +690,8 @@
                     .release(test_opts.release)
                     .manifest_path(opt.manifest_path)
                     .nocapture(test_opts.nocapture),
-                false,
+                test_opts.no_run,
+                test_opts.doc,
                 &target_options,
                 &params,
                 to_opt_str(&test_args),
diff --git a/src/lib.rs b/src/lib.rs
index 75cf70b..533663c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -130,7 +130,7 @@
                 // TODO(raggi): provide a fuller ignore flag/pattern match solution here.
                 if !path.starts_with(&tgt) && !path.starts_with(&git) {
                     println!("autotest: running tests because {:?}", path);
-                    run_tests(run_cargo_options, false, target_options, &[], None).ok();
+                    run_tests(run_cargo_options, false, false, target_options, &[], None).ok();
                 }
             }
             _ => {}
@@ -141,16 +141,21 @@
 fn run_tests(
     run_cargo_options: &RunCargoOptions,
     no_run: bool,
+    doc: bool,
     target_options: &TargetOptions<'_, '_>,
     params: &[&str],
     target_params: Option<&str>,
 ) -> Result<(), Error> {
-    let mut args = vec![];
+    let mut args = vec!["-Zdoctest-xcompile"];
 
     if no_run {
         args.push("--no-run");
     }
 
+    if doc {
+        args.push("--doc");
+    }
+
     for param in params {
         args.push(param);
     }
@@ -491,13 +496,7 @@
 ///         release: true,
 ///         nocapture: false,
 ///         run_mode: RunMode::Run,
-///         story_name: None,
-///         mod_name: None,
-///         disable_cross: false,
-///         manifest_path: None,
-///         cmx_path: None,
-///         app_dir: None,
-///         app_name: None,
+///         ..RunCargoOptions::default()
 ///     },
 ///     "help",
 ///     &[],
@@ -557,19 +556,22 @@
 
     let runner_env_name = format!("CARGO_TARGET_{}_RUNNER", target_triple_uc);
     let rustflags_env_name = format!("CARGO_TARGET_{}_RUSTFLAGS", target_triple_uc);
+    let rustflags = get_rustflags(options, target_options, &sysroot_as_path)?;
 
     if options.verbose {
         println!("runner_env_name: {:?}", runner_env_name);
         println!("rustflags_env_name: {:?}", rustflags_env_name);
         println!("rustc_path: {:?}", rustc_path()?.to_string_lossy());
         println!("cargo_path: {:?}", cargo_path()?.to_string_lossy());
+        println!("rustdoc_path: {:?}", rustdoc_path()?);
+        println!("rustflags: {:?}", &rustflags);
     }
 
     cmd.env(runner_env_name, fargo_command)
-        .env(rustflags_env_name, get_rustflags(options, target_options, &sysroot_as_path)?)
+        .env(rustflags_env_name, &rustflags)
         .env("RUSTC", rustc_path()?.to_string_lossy().as_ref())
         .env("RUSTDOC", rustdoc_path()?.to_string_lossy().as_ref())
-        .env("RUSTDOCFLAGS", "--cap-lints allow -Z unstable-options")
+        .env("RUSTDOCFLAGS", &rustflags)
         .env("FUCHSIA_SHARED_ROOT", shared_libraries_path(target_options)?)
         .env("ZIRCON_BUILD_ROOT", zircon_build_path(&target_options.config)?)
         .arg(subcommand)