// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/protobuf_mutator.h"

#include <algorithm>
#include <iostream>
#include <map>
#include <random>
#include <string>

#include "src/field_instance.h"
#include "src/weighted_reservoir_sampler.h"

namespace protobuf_mutator {

using protobuf::Descriptor;
using protobuf::EnumDescriptor;
using protobuf::EnumValueDescriptor;
using protobuf::FieldDescriptor;
using protobuf::FileDescriptor;
using protobuf::Message;
using protobuf::OneofDescriptor;
using protobuf::Reflection;
using protobuf::util::MessageDifferencer;
using std::placeholders::_1;

namespace {

const size_t kMaxInitializeDepth = 32;
const size_t kDeletionThreshold = 128;
const uint64_t kMutateWeight = 1000000;

enum class Mutation {
  None,
  Add,     // Adds new field with default value.
  Mutate,  // Mutates field contents.
  Delete,  // Deletes field.
  Copy,    // Copy values copied from another field.

  // TODO(vitalybuka):
  // Clone,  // Adds new field with value copied from another field.
};

// Return random integer from [0, count)
size_t GetRandomIndex(ProtobufMutator::RandomEngine* random, size_t count) {
  assert(count > 0);
  if (count == 1) return 0;
  return std::uniform_int_distribution<size_t>(0, count - 1)(*random);
}

// Flips random bit in the buffer.
void FlipBit(size_t size, uint8_t* bytes,
             ProtobufMutator::RandomEngine* random) {
  size_t bit = GetRandomIndex(random, size * 8);
  bytes[bit / 8] ^= (1u << (bit % 8));
}

// Flips random bit in the value.
template <class T>
T FlipBit(T value, ProtobufMutator::RandomEngine* random) {
  FlipBit(sizeof(value), reinterpret_cast<uint8_t*>(&value), random);
  return value;
}

// Return true with probability about 1-of-n.
bool GetRandomBool(ProtobufMutator::RandomEngine* random, size_t n = 2) {
  return GetRandomIndex(random, n) == 0;
}

struct CreateDefaultField : public FieldFunction<CreateDefaultField> {
  template <class T>
  void ForType(const FieldInstance& field) const {
    T value;
    field.GetDefault(&value);
    field.Create(value);
  }
};

struct DeleteField : public FieldFunction<DeleteField> {
  template <class T>
  void ForType(const FieldInstance& field) const {
    field.Delete();
  }
};

struct CopyField : public FieldFunction<CopyField> {
  template <class T>
  void ForType(const ConstFieldInstance& source,
               const FieldInstance& field) const {
    T value;
    source.Load(&value);
    field.Store(value);
  }
};

struct AppendField : public FieldFunction<AppendField> {
  template <class T>
  void ForType(const ConstFieldInstance& source,
               const FieldInstance& field) const {
    T value;
    source.Load(&value);
    field.Create(value);
  }
};

class IsEqualValueField : public FieldFunction<IsEqualValueField, bool> {
 public:
  template <class T>
  bool ForType(const ConstFieldInstance& a, const ConstFieldInstance& b) const {
    T aa;
    a.Load(&aa);
    T bb;
    b.Load(&bb);
    return IsEqual(aa, bb);
  }

 private:
  bool IsEqual(const ConstFieldInstance::Enum& a,
               const ConstFieldInstance::Enum& b) const {
    assert(a.count == b.count);
    return a.index == b.index;
  }

  bool IsEqual(const std::unique_ptr<protobuf::Message>& a,
               const std::unique_ptr<protobuf::Message>& b) const {
    return MessageDifferencer::Equals(*a, *b);
  }

  template <class T>
  bool IsEqual(const T& a, const T& b) const {
    return a == b;
  }
};

// Selects random field and mutation from the given proto message.
class MutationSampler {
 public:
  MutationSampler(bool keep_initialized, size_t size_increase_hint,
                  ProtobufMutator::RandomEngine* random, Message* message)
      : keep_initialized_(keep_initialized), random_(random), sampler_(random) {
    if (size_increase_hint < kDeletionThreshold) {
      // Avoid adding new field and prefer deleting fields if we getting close
      // to the limit.
      float adjustment = 0.5 * size_increase_hint / kDeletionThreshold;
      add_weight_ *= adjustment;
      delete_weight_ *= 1 - adjustment;
    }
    Sample(message);
    assert(mutation() != Mutation::None);
  }

  // Returns selected field.
  const FieldInstance& field() const { return sampler_.selected().field; }

  // Returns selected mutation.
  Mutation mutation() const { return sampler_.selected().mutation; }

 private:
  void Sample(Message* message) {
    const Descriptor* descriptor = message->GetDescriptor();
    const Reflection* reflection = message->GetReflection();

    int field_count = descriptor->field_count();
    for (int i = 0; i < field_count; ++i) {
      const FieldDescriptor* field = descriptor->field(i);
      if (const OneofDescriptor* oneof = field->containing_oneof()) {
        // Handle entire oneof group on the first field.
        if (field->index_in_oneof() == 0) {
          assert(oneof->field_count());
          const FieldDescriptor* current_field =
              reflection->GetOneofFieldDescriptor(*message, oneof);
          for (;;) {
            const FieldDescriptor* add_field =
                oneof->field(GetRandomIndex(random_, oneof->field_count()));
            if (add_field != current_field) {
              sampler_.Try(add_weight_, {{message, add_field}, Mutation::Add});
              break;
            }
            if (oneof->field_count() < 2) break;
          }
          if (current_field) {
            if (current_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
              sampler_.Try(kMutateWeight,
                           {{message, current_field}, Mutation::Mutate});
            sampler_.Try(delete_weight_,
                         {{message, current_field}, Mutation::Delete});
            sampler_.Try(GetCopyWeight(field),
                         {{message, current_field}, Mutation::Copy});
          }
        }
      } else {
        if (field->is_repeated()) {
          int field_size = reflection->FieldSize(*message, field);
          sampler_.Try(add_weight_, {{message, field,
                                      GetRandomIndex(random_, field_size + 1)},
                                     Mutation::Add});

          if (field_size) {
            size_t random_index = GetRandomIndex(random_, field_size);
            if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
              sampler_.Try(kMutateWeight,
                           {{message, field, random_index}, Mutation::Mutate});
            sampler_.Try(delete_weight_,
                         {{message, field, random_index}, Mutation::Delete});
            sampler_.Try(GetCopyWeight(field),
                         {{message, field, random_index}, Mutation::Copy});
          }
        } else {
          if (reflection->HasField(*message, field)) {
            if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)
              sampler_.Try(kMutateWeight, {{message, field}, Mutation::Mutate});
            if ((!field->is_required() || !keep_initialized_))
              sampler_.Try(delete_weight_,
                           {{message, field}, Mutation::Delete});
            sampler_.Try(GetCopyWeight(field),
                         {{message, field}, Mutation::Copy});
          } else {
            sampler_.Try(add_weight_, {{message, field}, Mutation::Add});
          }
        }
      }

      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
        if (field->is_repeated()) {
          const int field_size = reflection->FieldSize(*message, field);
          for (int j = 0; j < field_size; ++j)
            Sample(reflection->MutableRepeatedMessage(message, field, j));
        } else if (reflection->HasField(*message, field)) {
          Sample(reflection->MutableMessage(message, field));
        }
      }
    }
  }

  uint64_t GetCopyWeight(const FieldDescriptor* field) const {
    // Coping sub-messages can increase size significantly.
    return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
               ? add_weight_
               : kMutateWeight;
  }

  bool keep_initialized_ = false;

  // Adding and deleting are intrusive and expensive mutations, we'd like to do
  // them less often than field mutations.
  uint64_t add_weight_ = kMutateWeight / 10;
  uint64_t delete_weight_ = kMutateWeight / 10;

  ProtobufMutator::RandomEngine* random_;

  struct Result {
    Result() = default;
    Result(const FieldInstance& f, Mutation m) : field(f), mutation(m) {}

    FieldInstance field;
    Mutation mutation = Mutation::None;
  };
  WeightedReservoirSampler<Result, ProtobufMutator::RandomEngine> sampler_;
};

// Selects random field of compatible type to use for clone mutations.
class DataSourceSampler {
 public:
  DataSourceSampler(const ConstFieldInstance& match,
                    ProtobufMutator::RandomEngine* random, Message* message)
      : match_(match), random_(random), sampler_(random) {
    Sample(message);
  }

  // Returns selected field.
  const ConstFieldInstance& field() const {
    assert(!IsEmpty());
    return sampler_.selected();
  }

  bool IsEmpty() const { return sampler_.IsEmpty(); }

 private:
  void Sample(Message* message) {
    const Descriptor* descriptor = message->GetDescriptor();
    const Reflection* reflection = message->GetReflection();

    int field_count = descriptor->field_count();
    for (int i = 0; i < field_count; ++i) {
      const FieldDescriptor* field = descriptor->field(i);
      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
        if (field->is_repeated()) {
          const int field_size = reflection->FieldSize(*message, field);
          for (int j = 0; j < field_size; ++j) {
            Sample(reflection->MutableRepeatedMessage(message, field, j));
          }
        } else if (reflection->HasField(*message, field)) {
          Sample(reflection->MutableMessage(message, field));
        }
      }

      if (field->cpp_type() != match_.cpp_type()) continue;
      if (match_.cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
        if (field->enum_type() != match_.enum_type()) continue;
      } else if (match_.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
        if (field->message_type() != match_.message_type()) continue;
      }

      if (field->is_repeated()) {
        if (int field_size = reflection->FieldSize(*message, field)) {
          ConstFieldInstance source(message, field,
                                    GetRandomIndex(random_, field_size));
          if (!IsEqualValueField()(match_, source))
            sampler_.Try(field_size, source);
        }
      } else {
        if (reflection->HasField(*message, field)) {
          ConstFieldInstance source(message, field);
          if (!IsEqualValueField()(match_, source)) sampler_.Try(1, source);
        }
      }
    }
  }

  ConstFieldInstance match_;
  ProtobufMutator::RandomEngine* random_;

  WeightedReservoirSampler<ConstFieldInstance, ProtobufMutator::RandomEngine>
      sampler_;
};

}  // namespace

class FieldMutator {
 public:
  FieldMutator(size_t size_increase_hint, ProtobufMutator* mutator)
      : size_increase_hint_(size_increase_hint), mutator_(mutator) {}

  void Mutate(int32_t* value) const {
    RepeatMutate(value, std::bind(&ProtobufMutator::MutateInt32, mutator_, _1));
  }

  void Mutate(int64_t* value) const {
    RepeatMutate(value, std::bind(&ProtobufMutator::MutateInt64, mutator_, _1));
  }

  void Mutate(uint32_t* value) const {
    RepeatMutate(value,
                 std::bind(&ProtobufMutator::MutateUInt32, mutator_, _1));
  }

  void Mutate(uint64_t* value) const {
    RepeatMutate(value,
                 std::bind(&ProtobufMutator::MutateUInt64, mutator_, _1));
  }

  void Mutate(float* value) const {
    RepeatMutate(value, std::bind(&ProtobufMutator::MutateFloat, mutator_, _1));
  }

  void Mutate(double* value) const {
    RepeatMutate(value,
                 std::bind(&ProtobufMutator::MutateDouble, mutator_, _1));
  }

  void Mutate(bool* value) const {
    RepeatMutate(value, std::bind(&ProtobufMutator::MutateBool, mutator_, _1));
  }

  void Mutate(FieldInstance::Enum* value) const {
    RepeatMutate(&value->index, std::bind(&ProtobufMutator::MutateEnum,
                                          mutator_, _1, value->count));
    assert(value->index < value->count);
  }

  void Mutate(std::string* value) const {
    RepeatMutate(value, std::bind(&ProtobufMutator::MutateString, mutator_, _1,
                                  size_increase_hint_));
  }

  void Mutate(std::unique_ptr<Message>*) const {
  }

 private:
  template <class T, class F>
  void RepeatMutate(T* value, F mutate) const {
    T tmp = *value;
    for (int i = 0; i < 10; ++i) {
      *value = mutate(*value);
      if (*value != tmp) return;
    }
  }

  size_t size_increase_hint_;
  ProtobufMutator* mutator_;
};

namespace {

struct MutateField : public FieldFunction<MutateField> {
  template <class T>
  void ForType(const FieldInstance& field, size_t size_increase_hint,
               ProtobufMutator* mutator) const {
    T value;
    field.Load(&value);
    FieldMutator(size_increase_hint, mutator).Mutate(&value);
    field.Store(value);
  }
};

struct CreateField : public FieldFunction<CreateField> {
 public:
  template <class T>
  void ForType(const FieldInstance& field, size_t size_increase_hint,
               ProtobufMutator* mutator) const {
    T value;
    field.GetDefault(&value);
    FieldMutator(size_increase_hint, mutator).Mutate(&value);
    field.Create(value);
  }
};

}  // namespace

ProtobufMutator::ProtobufMutator(uint32_t seed) : random_(seed) {}

void ProtobufMutator::Mutate(Message* message, size_t size_increase_hint) {
  bool repeat;
  do {
    repeat = false;
    MutationSampler mutation(keep_initialized_, size_increase_hint, &random_,
                             message);
    switch (mutation.mutation()) {
      case Mutation::None:
        break;
      case Mutation::Add:
        if (GetRandomBool(&random_)) {
          CreateField()(mutation.field(), 0, this);
        } else {
          CreateDefaultField()(mutation.field());
        }
        break;
      case Mutation::Mutate:
        MutateField()(mutation.field(), size_increase_hint / 2, this);
        break;
      case Mutation::Delete:
        DeleteField()(mutation.field());
        break;
      case Mutation::Copy: {
        DataSourceSampler source(mutation.field(), &random_, message);
        if (source.IsEmpty()) {
          repeat = true;
          break;
        }
        CopyField()(source.field(), mutation.field());
        break;
      }
      default:
        assert(false && "unexpected mutation");
    }
  } while (repeat);

  if (keep_initialized_ && !message->IsInitialized()) {
    InitializeMessage(message, kMaxInitializeDepth);
    assert(message->IsInitialized());
  }
}

void ProtobufMutator::CrossOver(const protobuf::Message& message1,
                                protobuf::Message* message2) {
  CrossOverImpl(message1, message2);

  if (keep_initialized_ && !message2->IsInitialized()) {
    InitializeMessage(message2, kMaxInitializeDepth);
    assert(message2->IsInitialized());
  }
}

void ProtobufMutator::CrossOverImpl(const protobuf::Message& message1,
                                    protobuf::Message* message2) {
  const Descriptor* descriptor = message2->GetDescriptor();
  const Reflection* reflection = message2->GetReflection();
  assert(message1.GetDescriptor() == descriptor);
  assert(message1.GetReflection() == reflection);

  for (int i = 0; i < descriptor->field_count(); ++i) {
    const FieldDescriptor* field = descriptor->field(i);

    if (field->is_repeated()) {
      const int field_size1 = reflection->FieldSize(message1, field);
      int field_size2 = reflection->FieldSize(*message2, field);
      for (int j = 0; j < field_size1; ++j) {
        ConstFieldInstance source(&message1, field, j);
        FieldInstance destination(message2, field, field_size2++);
        AppendField()(source, destination);
      }

      assert(field_size2 == reflection->FieldSize(*message2, field));

      // Shuffle
      for (int j = 0; j < field_size2; ++j) {
        if (int k = GetRandomIndex(&random_, field_size2 - j)) {
          reflection->SwapElements(message2, field, j, j + k);
        }
      }

      int keep = GetRandomIndex(&random_, field_size2 + 1);

      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
        int remove = field_size2 - keep;
        // Cross some message to keep with messages to remove.
        int cross = GetRandomIndex(&random_, std::min(keep, remove) + 1);
        for (int j = 0; j < cross; ++j) {
          int k = GetRandomIndex(&random_, keep);
          int r = keep + GetRandomIndex(&random_, remove);
          assert(k != r);
          CrossOverImpl(reflection->GetRepeatedMessage(*message2, field, r),
                        reflection->MutableRepeatedMessage(message2, field, k));
        }
      }

      for (int j = keep; j < field_size2; ++j)
        reflection->RemoveLast(message2, field);
      assert(keep == reflection->FieldSize(*message2, field));

    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
      if (!reflection->HasField(message1, field)) {
        if (GetRandomBool(&random_))
          DeleteField()(FieldInstance(message2, field));
      } else if (!reflection->HasField(*message2, field)) {
        if (GetRandomBool(&random_)) {
          ConstFieldInstance source(&message1, field);
          CopyField()(source, FieldInstance(message2, field));
        }
      } else {
        CrossOverImpl(reflection->GetMessage(message1, field),
                      reflection->MutableMessage(message2, field));
      }
    } else {
      if (GetRandomBool(&random_)) {
        if (reflection->HasField(message1, field)) {
          ConstFieldInstance source(&message1, field);
          CopyField()(source, FieldInstance(message2, field));
        } else {
          DeleteField()(FieldInstance(message2, field));
        }
      }
    }
  }
}

void ProtobufMutator::InitializeMessage(Message* message, size_t max_depth) {
  assert(keep_initialized_);
  // It's pointless but possible to have infinite recursion of required
  // messages.
  assert(max_depth);
  const Descriptor* descriptor = message->GetDescriptor();
  const Reflection* reflection = message->GetReflection();
  for (int i = 0; i < descriptor->field_count(); ++i) {
    const FieldDescriptor* field = descriptor->field(i);
    if (field->is_required() && !reflection->HasField(*message, field))
      CreateDefaultField()(FieldInstance(message, field));

    if (max_depth > 0 &&
        field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
      if (field->is_repeated()) {
        const int field_size = reflection->FieldSize(*message, field);
        for (int j = 0; j < field_size; ++j) {
          Message* nested_message =
              reflection->MutableRepeatedMessage(message, field, j);
          if (!nested_message->IsInitialized())
            InitializeMessage(nested_message, max_depth - 1);
        }
      } else if (reflection->HasField(*message, field)) {
        Message* nested_message = reflection->MutableMessage(message, field);
        if (!nested_message->IsInitialized())
          InitializeMessage(nested_message, max_depth - 1);
      }
    }
  }
}

int32_t ProtobufMutator::MutateInt32(int32_t value) {
  return FlipBit(value, &random_);
}

int64_t ProtobufMutator::MutateInt64(int64_t value) {
  return FlipBit(value, &random_);
}

uint32_t ProtobufMutator::MutateUInt32(uint32_t value) {
  return FlipBit(value, &random_);
}

uint64_t ProtobufMutator::MutateUInt64(uint64_t value) {
  return FlipBit(value, &random_);
}

float ProtobufMutator::MutateFloat(float value) {
  return FlipBit(value, &random_);
}

double ProtobufMutator::MutateDouble(double value) {
  return FlipBit(value, &random_);
}

bool ProtobufMutator::MutateBool(bool value) { return !value; }

size_t ProtobufMutator::MutateEnum(size_t index, size_t item_count) {
  return (index + 1 + GetRandomIndex(&random_, item_count - 1)) % item_count;
}

std::string ProtobufMutator::MutateString(const std::string& value,
                                          size_t size_increase_hint) {
  std::string result = value;

  while (!result.empty() && GetRandomBool(&random_)) {
    result.erase(GetRandomIndex(&random_, result.size()), 1);
  }

  while (result.size() < size_increase_hint && GetRandomBool(&random_)) {
    size_t index = GetRandomIndex(&random_, result.size() + 1);
    result.insert(result.begin() + index, GetRandomIndex(&random_, 1 << 8));
  }

  if (result != value) return result;

  if (result.empty()) {
    result.push_back(GetRandomIndex(&random_, 1 << 8));
    return result;
  }

  if (!result.empty())
    FlipBit(result.size(), reinterpret_cast<uint8_t*>(&result[0]), &random_);
  return result;
}

}  // namespace protobuf_mutator
