Expose API to parse known absl flags.

This change makes it easier for consumers such as Chromium to use fuzztest. It
changes argument handling in two ways:

1) It exposes a new 'InitAbslFlagsForFuzztest' API. Chromium's test suites
   otherwise needed to call into absl flags directly to initialize absl's
   command line; this was problematic in projects where absl flags are not
   normally used. Integration of fuzztest is easier if we need to call
   only fuzztest APIs instead of absl flags directly.

   A key point of this new API is that it does not call
   absl::ParseCommandLine, but instead absl::ParseAbseilFlagsOnly.
   This ignores unknown command-line options, which is important in
   environments where other code may use non-absl parsing of command lines.

2) fuzztest_gtest_main is amended to use the above function instead
   of absl::ParseCommandLine. This is because, when used with libfuzzer
   or other non-centipede fuzzing engines, those fuzzing engines themselves
   absorb command linm arguments, and thus the previous use of
   absl::ParseCommandLine always failed unless a complex
   '-undefok=' argument was constructed listing all the possible options
   that could be passed to libfuzzer.

As an indication of the complexity here, in a typical Chromium test,
command-line arguments may flow to four places:
* FuzzTest's absl flags
* libfuzzer, passed there via InitFuzzTest (or some other fuzzing engine)
* Chromium's own test frameworks (flags like --single-process-tests)
* Chromium's underlying code, e.g. for enabling runtime features
  or disabling the sandbox.

Because of the many areas of code handling command line arguments, it's not
practical to declare them all in advance either using absl flags, nor using
`-undefok` and that's why it's important that FuzzTest uses
absl::ParseAbseilFlagsOnly to avoid erroring in the face of unknown extra
command line arguments.

This CL does not fix a third problem in this area, which is that
the fuzztest engine stores the given argc and argv and assumes it never
subsequently changes - this assumption is wrong in projects such as
Chromium where other layers of software may absorb and modify the
command line later, and results in use-after-return bugs. However
this can be easily worked around by storing an extra copy of the original
argc and argv for use by fuzztest, disregarding subsequent changes.

PiperOrigin-RevId: 625785463
diff --git a/fuzztest/BUILD b/fuzztest/BUILD
index fd4eae7..38990c3 100644
--- a/fuzztest/BUILD
+++ b/fuzztest/BUILD
@@ -109,6 +109,7 @@
         ":registry",
         ":runtime",
         "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/flags:parse",
         "@com_google_absl//absl/flags:reflection",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/strings:str_format",
diff --git a/fuzztest/fuzztest_gtest_main.cc b/fuzztest/fuzztest_gtest_main.cc
index 1c53586..f4aea2d 100644
--- a/fuzztest/fuzztest_gtest_main.cc
+++ b/fuzztest/fuzztest_gtest_main.cc
@@ -21,7 +21,10 @@
 
 int main(int argc, char** argv) {
   testing::InitGoogleTest(&argc, argv);
-  absl::ParseCommandLine(argc, argv);
+  // We call fuzztest::ParseAbslFlagsrather than absl::ParseCommandLine
+  // since the latter would complain about any unknown flags that need
+  // to be passed to legacy fuzzing engines (e.g. libfuzzer).
+  fuzztest::ParseAbslFlags(argc, argv);
   fuzztest::InitFuzzTest(&argc, &argv);
   return RUN_ALL_TESTS();
 }
diff --git a/fuzztest/init_fuzztest.cc b/fuzztest/init_fuzztest.cc
index dda5f94..9d3db8e 100644
--- a/fuzztest/init_fuzztest.cc
+++ b/fuzztest/init_fuzztest.cc
@@ -11,6 +11,7 @@
 
 #include "gtest/gtest.h"
 #include "absl/flags/flag.h"
+#include "absl/flags/parse.h"
 #include "absl/flags/reflection.h"
 #include "absl/strings/match.h"
 #include "absl/strings/str_cat.h"
@@ -229,4 +230,10 @@
   internal::Runtime::instance().SetRunMode(run_mode);
 }
 
+void ParseAbslFlags(int argc, char** argv) {
+  std::vector<char*> positional_args;
+  std::vector<absl::UnrecognizedFlag> unrecognized_flags;
+  absl::ParseAbseilFlagsOnly(argc, argv, positional_args, unrecognized_flags);
+}
+
 }  // namespace fuzztest
diff --git a/fuzztest/init_fuzztest.h b/fuzztest/init_fuzztest.h
index df5da51..e33ca39 100644
--- a/fuzztest/init_fuzztest.h
+++ b/fuzztest/init_fuzztest.h
@@ -8,6 +8,18 @@
 
 namespace fuzztest {
 
+// Initializes Abseil flags such that FuzzTest can rely upon them.
+// It initializes all Abseil flags (not just FuzzTest ones).
+// It does not do anything with non-Abseil flags and will not result
+// in an error or failure if there are other flags on the command line
+// (as there might be especially if you are using a non-centipede
+// fuzzing engine).
+// This should be called only if you have no other code initializing
+// Abseil flags from the command line elsewhere (such as
+// absl::ParseCommandLine()).
+// It does not change the command line (argv); only reads it.
+void ParseAbslFlags(int argc, char** argv);
+
 // Initializes FuzzTest. Handles the FuzzTest related flags and registers
 // FUZZ_TEST-s in the binary as GoogleTest TEST-s.
 //
@@ -17,6 +29,8 @@
 // https://llvm.org/docs/LibFuzzer.html#using-libfuzzer-as-a-library
 //
 // REQUIRES: `main()` has started before calling this function.
+// REQUIRES: Abseil flags have been inited, either using
+//           ParseAbslFlags or some other means
 void InitFuzzTest(int* argc, char*** argv);
 
 // Returns a list of all registered fuzz test names in the form of