TYPE_STRING support for iface_fuzzer.

Test: SANITIZE_TARGET="address coverage" mma -j64
Change-Id: Id460b484d74fd173fe4bd20b7d99c687440d654d
diff --git a/iface_fuzzer/ProtoFuzzerMutateFns.cpp b/iface_fuzzer/ProtoFuzzerMutateFns.cpp
index 8f86698..9960dae 100644
--- a/iface_fuzzer/ProtoFuzzerMutateFns.cpp
+++ b/iface_fuzzer/ProtoFuzzerMutateFns.cpp
@@ -104,6 +104,58 @@
   return result;
 }
 
+VarInstance ProtoFuzzerMutator::StringRandomGen(const VarSpec &var_spec) {
+  VarInstance result{VarInstanceStubFromSpec(var_spec)};
+
+  size_t str_size = mutator_config_.default_string_size_;
+  string str(str_size, 0);
+  auto rand_char = std::bind(&ProtoFuzzerMutator::RandomAsciiChar, this);
+  std::generate_n(str.begin(), str_size, rand_char);
+
+  StringDataValueMessage string_data;
+  string_data.set_message(str.c_str());
+  string_data.set_length(str_size);
+
+  *result.mutable_string_value() = string_data;
+  return result;
+}
+
+VarInstance ProtoFuzzerMutator::StringMutate(const VarInstance &var_instance) {
+  VarInstance result{var_instance};
+  string str = result.string_value().message();
+  size_t str_size = result.string_value().length();
+
+  // Three things can happen when mutating a string:
+  // 1. A random char is inserted into a random position.
+  // 2. A randomly selected char is removed from the string.
+  // 3. A randomly selected char in the string is replaced by a random char.
+  size_t dice_roll = str.empty() ? 0 : rand_(3);
+  size_t idx = rand_(str_size);
+  switch (dice_roll) {
+    case 0:
+      // Insert a random char.
+      str.insert(str.begin() + idx, RandomAsciiChar());
+      ++str_size;
+      break;
+    case 1:
+      // Remove a randomly selected char.
+      str.erase(str.begin() + idx);
+      --str_size;
+      break;
+    case 2:
+      // Replace a randomly selected char.
+      str[idx] = RandomAsciiChar();
+      break;
+    default:
+      // Do nothing.
+      break;
+  }
+
+  result.mutable_string_value()->set_message(str);
+  result.mutable_string_value()->set_length(str_size);
+  return result;
+}
+
 VarInstance ProtoFuzzerMutator::StructRandomGen(const VarSpec &var_spec) {
   VarInstance result{VarInstanceStubFromSpec(var_spec)};
   const TypeSpec &blueprint = FindPredefinedType(result.predefined_type());
@@ -271,6 +323,16 @@
   return value;
 }
 
+char ProtoFuzzerMutator::RandomAsciiChar() {
+  const char char_set[] =
+      "0123456789"
+      "`~!@#$%^&*()-_=+[{]};:',<.>/? "
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+      "abcdefghijklmnopqrstuvwxyz";
+  size_t num_chars = sizeof(char_set) - 1;
+  return char_set[rand_(num_chars)];
+}
+
 }  // namespace fuzzer
 }  // namespace vts
 }  // namespace android
diff --git a/iface_fuzzer/ProtoFuzzerMutator.cpp b/iface_fuzzer/ProtoFuzzerMutator.cpp
index df096f7..3a20976 100644
--- a/iface_fuzzer/ProtoFuzzerMutator.cpp
+++ b/iface_fuzzer/ProtoFuzzerMutator.cpp
@@ -71,6 +71,11 @@
   mutate_fns_[TYPE_SCALAR] =
       std::bind(&ProtoFuzzerMutator::ScalarMutate, this, _1);
 
+  random_gen_fns_[TYPE_STRING] =
+      std::bind(&ProtoFuzzerMutator::StringRandomGen, this, _1);
+  mutate_fns_[TYPE_STRING] =
+      std::bind(&ProtoFuzzerMutator::StringMutate, this, _1);
+
   random_gen_fns_[TYPE_STRUCT] =
       std::bind(&ProtoFuzzerMutator::StructRandomGen, this, _1);
   mutate_fns_[TYPE_STRUCT] =
diff --git a/iface_fuzzer/include/ProtoFuzzerMutator.h b/iface_fuzzer/include/ProtoFuzzerMutator.h
index 90a0562..0609684 100644
--- a/iface_fuzzer/include/ProtoFuzzerMutator.h
+++ b/iface_fuzzer/include/ProtoFuzzerMutator.h
@@ -47,6 +47,8 @@
   Odds func_mutated_ = {100, 1};
   // Default size used to randomly generate a vector.
   size_t default_vector_size_ = 64;
+  // Default size used to randomly generate a string.
+  size_t default_string_size_ = 16;
 };
 
 // Provides methods for mutation or random generation.
@@ -75,6 +77,8 @@
   VarInstance EnumMutate(const VarInstance &);
   VarInstance ScalarRandomGen(const VarSpec &);
   VarInstance ScalarMutate(const VarInstance &);
+  VarInstance StringRandomGen(const VarSpec &);
+  VarInstance StringMutate(const VarInstance &);
   VarInstance StructRandomGen(const VarSpec &);
   VarInstance StructMutate(const VarInstance &);
   VarInstance UnionRandomGen(const VarSpec &);
@@ -95,6 +99,8 @@
   bool Mutate(bool);
   float Mutate(float);
   double Mutate(double);
+  // Generates a random ASCII character.
+  char RandomAsciiChar();
 
   // Looks up predefined type by name.
   const TypeSpec &FindPredefinedType(std::string);