Add argument to specify seed for random number generator.
am: ffaca0b75c

Change-Id: Ide2937efb74bf6ab4345f4e3f89103cef52725a2
diff --git a/iface_fuzzer/ProtoFuzzerMain.cpp b/iface_fuzzer/ProtoFuzzerMain.cpp
index 6b79192..9aac071 100644
--- a/iface_fuzzer/ProtoFuzzerMain.cpp
+++ b/iface_fuzzer/ProtoFuzzerMain.cpp
@@ -37,7 +37,7 @@
 namespace fuzzer {
 
 // 64-bit random number generator.
-static Random random{static_cast<uint64_t>(time(0))};
+static unique_ptr<Random> random;
 // Parameters that were passed in to fuzzer.
 static ProtoFuzzerParams params;
 // Used to mutate inputs to hal driver.
@@ -72,8 +72,12 @@
 
 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
   params = ExtractProtoFuzzerParams(*argc, *argv);
+  cerr << params.DebugString() << endl;
+
+  random = make_unique<Random>(params.seed_);
   mutator = make_unique<ProtoFuzzerMutator>(
-      random, ExtractPredefinedTypes(params.comp_specs_), mutator_config);
+      *random.get(), ExtractPredefinedTypes(params.comp_specs_),
+      mutator_config);
   runner = make_unique<ProtoFuzzerRunner>(params.comp_specs_);
 
   runner->Init(params.target_iface_, params.binder_mode_);
diff --git a/iface_fuzzer/ProtoFuzzerUtils.cpp b/iface_fuzzer/ProtoFuzzerUtils.cpp
index 9eae82e..43710f0 100644
--- a/iface_fuzzer/ProtoFuzzerUtils.cpp
+++ b/iface_fuzzer/ProtoFuzzerUtils.cpp
@@ -48,6 +48,8 @@
          "containing .vts spec files.\n"
          "\tvts_target_iface: name of interface targeted for fuzz, e.g. "
          "\"INfc\".\n"
+         "\tvts_seed: optional integral argument used to initalize the random "
+         "number generator.\n"
          "\n"
          "libfuzzer flags (strictly in form -flag=value):\n"
          "\tUse -help=1 to see libfuzzer flags\n"
@@ -59,6 +61,7 @@
     {"vts_binder_mode", no_argument, 0, 'b'},
     {"vts_spec_dir", required_argument, 0, 'd'},
     {"vts_exec_size", required_argument, 0, 'e'},
+    {"vts_seed", required_argument, 0, 's'},
     {"vts_target_iface", required_argument, 0, 't'}};
 
 // Removes information from CompSpec not needed by fuzzer.
@@ -90,7 +93,6 @@
     while ((ent = readdir(dir))) {
       string vts_spec_name{ent->d_name};
       if (vts_spec_name.find(".vts") != string::npos) {
-        cout << "Loading: " << vts_spec_name << endl;
         string vts_spec_path = dir_path + "/" + vts_spec_name;
         CompSpec comp_spec{};
         ParseInterfaceSpec(vts_spec_path.c_str(), &comp_spec);
@@ -127,7 +129,10 @@
         params.comp_specs_ = ExtractCompSpecs(optarg);
         break;
       case 'e':
-        params.exec_size_ = atoi(optarg);
+        params.exec_size_ = static_cast<size_t>(atoi(optarg));
+        break;
+      case 's':
+        params.seed_ = static_cast<uint64_t>(atoi(optarg));
         break;
       case 't':
         params.target_iface_ = optarg;
@@ -140,6 +145,19 @@
   return params;
 }
 
+string ProtoFuzzerParams::DebugString() {
+  std::stringstream ss;
+  ss << "Execution size: " << exec_size_ << endl;
+  ss << "Target interface: " << target_iface_ << endl;
+  ss << "Binder mode: " << binder_mode_ << endl;
+  ss << "Seed: " << seed_ << endl;
+  ss << "Loaded specs: " << endl;
+  for (const auto &spec : comp_specs_) {
+    ss << spec.component_name() << endl;
+  }
+  return ss.str();
+}
+
 unordered_map<string, TypeSpec> ExtractPredefinedTypes(
     const vector<CompSpec> &specs) {
   unordered_map<string, TypeSpec> predefined_types;
diff --git a/iface_fuzzer/include/ProtoFuzzerUtils.h b/iface_fuzzer/include/ProtoFuzzerUtils.h
index 85af37f..13e5665 100644
--- a/iface_fuzzer/include/ProtoFuzzerUtils.h
+++ b/iface_fuzzer/include/ProtoFuzzerUtils.h
@@ -17,6 +17,7 @@
 #ifndef __VTS_PROTO_FUZZER_UTILS_H__
 #define __VTS_PROTO_FUZZER_UTILS_H__
 
+#include <unistd.h>
 #include <iostream>
 #include <random>
 #include <string>
@@ -64,7 +65,8 @@
 };
 
 // Additional non-libfuzzer parameters passed to the fuzzer.
-struct ProtoFuzzerParams {
+class ProtoFuzzerParams {
+ public:
   // Number of function calls per execution (fixed throughout fuzzer run).
   size_t exec_size_;
   // VTS specs supplied to the fuzzer.
@@ -74,6 +76,10 @@
   // Controls whether HAL is opened in passthrough or binder mode.
   // Passthrough mode is default. Used for testing.
   bool binder_mode_ = false;
+  // Seed used to initialize the random number generator.
+  uint64_t seed_ = static_cast<uint64_t>(time(0));
+  // Returns a string summarizing content of this object.
+  string DebugString();
 };
 
 // Parses command-line flags to create a ProtoFuzzerParams instance.