Fix error when script_executable is not in PATH

This change fixes an unclear error message that can arise on Windows
when the exe pointed to by script_executable in the .gn dotfile
doesn't exist in the user's PATH.

If this occurs, the following error is printed:
"""
ERROR at //starboard/build/config/BUILDCONFIG.gn:15:15: Could not execute interpreter.

<exec_script that was attempted>

I was trying to execute "".
"""

This occurs because the function that searches for the
script_executable in the PATH on a Windows machine returns an empty
base::FilePath if the exe isn't found. As such, check if this happens
and return an Err that reports the problem.

Change-Id: I963b01619f68cef2a951fafc4c66f274176e66e0
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/13260
Reviewed-by: Brett Wilson <brettw@chromium.org>
Commit-Queue: Brett Wilson <brettw@chromium.org>
diff --git a/src/gn/setup.cc b/src/gn/setup.cc
index 9dba72e..8f1bd7a 100644
--- a/src/gn/setup.cc
+++ b/src/gn/setup.cc
@@ -781,8 +781,14 @@
     if (!value->VerifyTypeIs(Value::STRING, err)) {
       return false;
     }
-    build_settings_.set_python_path(
-        ProcessFileExtensions(UTF8ToFilePath(value->string_value())));
+    base::FilePath python_path =
+        ProcessFileExtensions(UTF8ToFilePath(value->string_value()));
+    if (python_path.empty()) {
+      *err = Err(Location(), "Could not find \"" + value->string_value() +
+                                 "\" from dotfile in PATH.");
+      return false;
+    }
+    build_settings_.set_python_path(python_path);
   } else {
 #if defined(OS_WIN)
     base::FilePath python_path =
diff --git a/src/gn/setup_unittest.cc b/src/gn/setup_unittest.cc
index 370f722..d905355 100644
--- a/src/gn/setup_unittest.cc
+++ b/src/gn/setup_unittest.cc
@@ -46,6 +46,36 @@
   EXPECT_EQ(gen_deps[0], base::MakeAbsoluteFilePath(dot_gn_name));
 }
 
+#if defined(OS_WIN)
+TEST_F(SetupTest, MissingScriptExeGeneratesSetupErrorOnWindows) {
+  base::CommandLine cmdline(base::CommandLine::NO_PROGRAM);
+
+  // Create a temp directory containing a .gn file and a BUILDCONFIG.gn file,
+  // pass it as --root.
+  base::ScopedTempDir in_temp_dir;
+  ASSERT_TRUE(in_temp_dir.CreateUniqueTempDir());
+  base::FilePath in_path = in_temp_dir.GetPath();
+  base::FilePath dot_gn_name = in_path.Append(FILE_PATH_LITERAL(".gn"));
+  WriteFile(dot_gn_name,
+            "buildconfig = \"//BUILDCONFIG.gn\"\n"
+            "script_executable = \"this_does_not_exist\"\n");
+
+  WriteFile(in_path.Append(FILE_PATH_LITERAL("BUILDCONFIG.gn")), "");
+  cmdline.AppendSwitchASCII(switches::kRoot, FilePathToUTF8(in_path));
+
+  // Create another temp dir for writing the generated files to.
+  base::ScopedTempDir build_temp_dir;
+  ASSERT_TRUE(build_temp_dir.CreateUniqueTempDir());
+
+  // Run setup and check that the .gn file is in the scheduler's gen deps.
+  Setup setup;
+  Err err;
+  EXPECT_FALSE(setup.DoSetupWithErr(FilePathToUTF8(build_temp_dir.GetPath()),
+                                    true, cmdline, &err));
+  EXPECT_TRUE(err.has_error());
+}
+#endif  // defined(OS_WIN)
+
 static void RunExtensionCheckTest(std::string extension,
                                   bool success,
                                   const std::string& expected_error_message) {