root/tools/ipc_fuzzer/mutate/generate.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GenerateIntegralType
  2. GenerateFloatingType
  3. GenerateStringType
  4. GenerateBool
  5. GenerateInt
  6. GenerateLong
  7. GenerateSize
  8. GenerateUChar
  9. GenerateUInt16
  10. GenerateUInt32
  11. GenerateInt64
  12. GenerateUInt64
  13. GenerateFloat
  14. GenerateDouble
  15. GenerateString
  16. GenerateString16
  17. GenerateData
  18. GenerateBytes
  19. GenerateParam
  20. PopulateGeneratorFunctionVector
  21. GenerateMain
  22. main

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdlib.h>

#include <algorithm>
#include <iostream>
#include <ostream>
#include <set>
#include <vector>

#include "base/command_line.h"
#include "base/pickle.h"
#include "base/strings/string_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_utils.h"
#include "ipc/ipc_switches.h"
#include "ipc/ipc_sync_channel.h"
#include "ipc/ipc_sync_message.h"
#include "tools/ipc_fuzzer/message_lib/message_file.h"
#include "tools/ipc_fuzzer/mutate/rand_util.h"

#if defined(OS_POSIX)
#include <unistd.h>
#endif

// First include of message files to provide basic type.
#include "tools/ipc_fuzzer/message_lib/all_messages.h"
#include "ipc/ipc_message_null_macros.h"

namespace IPC {
class Message;
}  // namespace IPC

namespace {
// For breaking deep recursion.
int g_depth = 0;
}  // namespace

namespace ipc_fuzzer {

// Interface implemented by those who generate basic types.  The types all
// correspond to the types which a pickle from base/pickle.h can pickle,
// plus the floating point types.
class Generator {
 public:
  virtual void GenerateBool(bool* value) = 0;
  virtual void GenerateInt(int* value) = 0;
  virtual void GenerateLong(long* value) = 0;
  virtual void GenerateSize(size_t* value) = 0;
  virtual void GenerateUChar(unsigned char *value) = 0;
  virtual void GenerateUInt16(uint16* value) = 0;
  virtual void GenerateUInt32(uint32* value) = 0;
  virtual void GenerateInt64(int64* value) = 0;
  virtual void GenerateUInt64(uint64* value) = 0;
  virtual void GenerateFloat(float *value) = 0;
  virtual void GenerateDouble(double *value) = 0;
  virtual void GenerateString(std::string* value) = 0;
  virtual void GenerateString16(base::string16* value) = 0;
  virtual void GenerateData(char* data, int length) = 0;
  virtual void GenerateBytes(void* data, int data_len) = 0;
};

template <typename T>
void GenerateIntegralType(T* value) {
  switch (RandInRange(16)) {
    case 0:
      *value = 0;
      break;
    case 1:
      *value = 1;
      break;
    case 2:
      *value = -1;
      break;
    case 3:
      *value = 2;
      break;
    default:
      *value = static_cast<T>(RandU64());
      break;
  }
}

template <typename T>
void GenerateFloatingType(T* value) {
  *value = RandDouble();
}

template <typename T>
void GenerateStringType(T* value) {
  T temp_string;
  size_t length = RandInRange(300);
  for (size_t i = 0; i < length; ++i)
    temp_string += RandInRange(256);
  *value = temp_string;
}

class GeneratorImpl : public Generator {
 public:
  GeneratorImpl() {}
  virtual ~GeneratorImpl() {}

  virtual void GenerateBool(bool* value) OVERRIDE {
    *value = RandInRange(2);
  }

  virtual void GenerateInt(int* value) OVERRIDE {
    GenerateIntegralType<int>(value);
  }

  virtual void GenerateLong(long* value) OVERRIDE {
    GenerateIntegralType<long>(value);
  }

  virtual void GenerateSize(size_t* value) OVERRIDE {
    GenerateIntegralType<size_t>(value);
  }

  virtual void GenerateUChar(unsigned char* value) OVERRIDE {
    GenerateIntegralType<unsigned char>(value);
  }

  virtual void GenerateUInt16(uint16* value) OVERRIDE {
    GenerateIntegralType<uint16>(value);
  }

  virtual void GenerateUInt32(uint32* value) OVERRIDE {
    GenerateIntegralType<uint32>(value);
  }

  virtual void GenerateInt64(int64* value) OVERRIDE {
    GenerateIntegralType<int64>(value);
  }

  virtual void GenerateUInt64(uint64* value) OVERRIDE {
    GenerateIntegralType<uint64>(value);
  }

  virtual void GenerateFloat(float* value) OVERRIDE {
    GenerateFloatingType<float>(value);
  }

  virtual void GenerateDouble(double* value) OVERRIDE {
    GenerateFloatingType<double>(value);
  }

  virtual void GenerateString(std::string* value) OVERRIDE {
    GenerateStringType<std::string>(value);
  }

  virtual void GenerateString16(base::string16* value) OVERRIDE {
    GenerateStringType<base::string16>(value);
  }

  virtual void GenerateData(char* data, int length) OVERRIDE {
    for (int i = 0; i < length; ++i) {
      GenerateIntegralType<char>(&data[i]);
    }
  }

  virtual void GenerateBytes(void* data, int data_len) OVERRIDE {
    GenerateData(static_cast<char*>(data), data_len);
  }
};

// Partially-specialized class that knows how to generate a given type.
template <class P>
struct GenerateTraits {
  static bool Generate(P* p, Generator *generator) {
    // This is the catch-all for types we don't have enough information
    // to generate.
    std::cerr << "Can't handle " << __PRETTY_FUNCTION__ << "\n";
    return false;
  }
};

// Template function to invoke partially-specialized class method.
template <class P>
static bool GenerateParam(P* p, Generator* generator) {
  return GenerateTraits<P>::Generate(p, generator);
}

// Specializations to generate primitive types.
template <>
struct GenerateTraits<bool> {
  static bool Generate(bool* p, Generator* generator) {
    generator->GenerateBool(p);
    return true;
  }
};

template <>
struct GenerateTraits<int> {
  static bool Generate(int* p, Generator* generator) {
    generator->GenerateInt(p);
    return true;
  }
};

template <>
struct GenerateTraits<unsigned int> {
  static bool Generate(unsigned int* p, Generator* generator) {
    generator->GenerateInt(reinterpret_cast<int*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<long> {
  static bool Generate(long* p, Generator* generator) {
    generator->GenerateLong(p);
    return true;
  }
};

template <>
struct GenerateTraits<unsigned long> {
  static bool Generate(unsigned long* p, Generator* generator) {
    generator->GenerateLong(reinterpret_cast<long*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<long long> {
  static bool Generate(long long* p, Generator* generator) {
    generator->GenerateInt64(reinterpret_cast<int64*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<unsigned long long> {
  static bool Generate(unsigned long long* p, Generator* generator) {
    generator->GenerateInt64(reinterpret_cast<int64*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<short> {
  static bool Generate(short* p, Generator* generator) {
    generator->GenerateUInt16(reinterpret_cast<uint16*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<unsigned short> {
  static bool Generate(unsigned short* p, Generator* generator) {
    generator->GenerateUInt16(reinterpret_cast<uint16*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<char> {
  static bool Generate(char* p, Generator* generator) {
    generator->GenerateUChar(reinterpret_cast<unsigned char*>(p));
    return true;
  }
};

template <>
struct GenerateTraits<unsigned char> {
  static bool Generate(unsigned char* p, Generator* generator) {
    generator->GenerateUChar(p);
    return true;
  }
};

template <>
struct GenerateTraits<float> {
  static bool Generate(float* p, Generator* generator) {
    generator->GenerateFloat(p);
    return true;
  }
};

template <>
struct GenerateTraits<double> {
  static bool Generate(double* p, Generator* generator) {
    generator->GenerateDouble(p);
    return true;
  }
};

template <>
struct GenerateTraits<std::string> {
  static bool Generate(std::string* p, Generator* generator) {
    generator->GenerateString(p);
    return true;
  }
};

template <>
struct GenerateTraits<base::string16> {
  static bool Generate(base::string16* p, Generator* generator) {
    generator->GenerateString16(p);
    return true;
  }
};

// Specializations to generate tuples.
template <>
struct GenerateTraits<Tuple0> {
  static bool Generate(Tuple0* p, Generator* generator) {
    return true;
  }
};

template <class A>
struct GenerateTraits<Tuple1<A> > {
  static bool Generate(Tuple1<A>* p, Generator* generator) {
    return GenerateParam(&p->a, generator);
  }
};

template <class A, class B>
struct GenerateTraits<Tuple2<A, B> > {
  static bool Generate(Tuple2<A, B>* p, Generator* generator) {
    return
        GenerateParam(&p->a, generator) &&
        GenerateParam(&p->b, generator);
  }
};

template <class A, class B, class C>
struct GenerateTraits<Tuple3<A, B, C> > {
  static bool Generate(Tuple3<A, B, C>* p, Generator* generator) {
    return
        GenerateParam(&p->a, generator) &&
        GenerateParam(&p->b, generator) &&
        GenerateParam(&p->c, generator);
  }
};

template <class A, class B, class C, class D>
struct GenerateTraits<Tuple4<A, B, C, D> > {
  static bool Generate(Tuple4<A, B, C, D>* p, Generator* generator) {
    return
        GenerateParam(&p->a, generator) &&
        GenerateParam(&p->b, generator) &&
        GenerateParam(&p->c, generator) &&
        GenerateParam(&p->d, generator);
  }
};

template <class A, class B, class C, class D, class E>
struct GenerateTraits<Tuple5<A, B, C, D, E> > {
  static bool Generate(Tuple5<A, B, C, D, E>* p, Generator* generator) {
    return
        GenerateParam(&p->a, generator) &&
        GenerateParam(&p->b, generator) &&
        GenerateParam(&p->c, generator) &&
        GenerateParam(&p->d, generator) &&
        GenerateParam(&p->e, generator);
  }
};

// Specializations to generate containers.
template <class A>
struct GenerateTraits<std::vector<A> > {
  static bool Generate(std::vector<A>* p, Generator* generator) {
    size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
    p->resize(count);
    for (size_t i = 0; i < count; ++i) {
      if (!GenerateParam(&p->at(i), generator)) {
        --g_depth;
        return false;
      }
    }
    --g_depth;
    return true;
  }
};

template <class A>
struct GenerateTraits<std::set<A> > {
  static bool Generate(std::set<A>* p, Generator* generator) {
    static int g_depth = 0;
    size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
    A a;
    for (size_t i = 0; i < count; ++i) {
      if (!GenerateParam(&a, generator)) {
        --g_depth;
        return false;
      }
      p->insert(a);
    }
    --g_depth;
    return true;
  }
};


template <class A, class B>
struct GenerateTraits<std::map<A, B> > {
  static bool Generate(std::map<A, B>* p, Generator* generator) {
    static int g_depth = 0;
    size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
    std::pair<A, B> place_holder;
    for (size_t i = 0; i < count; ++i) {
      if (!GenerateParam(&place_holder, generator)) {
        --g_depth;
        return false;
      }
      p->insert(place_holder);
    }
    --g_depth;
    return true;
  }
};

template <class A, class B>
struct GenerateTraits<std::pair<A, B> > {
  static bool Generate(std::pair<A, B>* p, Generator* generator) {
    return
        GenerateParam(&p->first, generator) &&
        GenerateParam(&p->second, generator);
  }
};

// Specializations to generate hand-coded tyoes
template <>
struct GenerateTraits<base::NullableString16> {
  static bool Generate(base::NullableString16* p, Generator* generator) {
    *p = base::NullableString16();
    return true;
  }
};

template <>
struct GenerateTraits<base::FileDescriptor> {
  static bool Generate(base::FileDescriptor* p, Generator* generator) {
    // I don't think we can generate real ones due to check on construct.
    p->fd = -1;
    return true;
  }
};

template <>
struct GenerateTraits<base::FilePath> {
  static bool Generate(base::FilePath* p, Generator* generator) {
    const char path_chars[] = "ACz0/.~:";
    size_t count = RandInRange(60);
    std::string random_path;
    for (size_t i = 0; i < count; ++i)
      random_path += path_chars[RandInRange(sizeof(path_chars) - 1)];
    *p = base::FilePath(random_path);
    return true;
  }
};

template <>
struct GenerateTraits<base::File::Error> {
  static bool Generate(base::File::Error* p, Generator* generator) {
    int temporary;
    if (!GenerateParam(&temporary, generator))
      return false;
    *p = static_cast<base::File::Error>(temporary);
    return true;
  }
};

template <>
struct GenerateTraits<base::File::Info> {
  static bool Generate(base::File::Info* p, Generator* generator) {
    double last_modified;
    double last_accessed;
    double creation_time;
    if (!GenerateParam(&p->size, generator))
      return false;
    if (!GenerateParam(&p->is_directory, generator))
      return false;
    if (!GenerateParam(&last_modified, generator))
      return false;
    if (GenerateParam(&last_accessed, generator))
      return false;
    if (GenerateParam(&creation_time, generator))
      return false;
    p->last_modified = base::Time::FromDoubleT(last_modified);
    p->last_accessed = base::Time::FromDoubleT(last_accessed);
    p->creation_time = base::Time::FromDoubleT(creation_time);
    return true;
  }
};

template <>
struct GenerateTraits<base::Time> {
  static bool Generate(base::Time* p, Generator* generator) {
    *p = base::Time::FromInternalValue(RandU64());
    return true;
  }
};

template <>
struct GenerateTraits<base::TimeDelta> {
  static bool Generate(base::TimeDelta* p, Generator* generator) {
    *p = base::TimeDelta::FromInternalValue(RandU64());
    return true;
  }
};

template <>
struct GenerateTraits<base::TimeTicks> {
  static bool Generate(base::TimeTicks* p, Generator* generator) {
    *p = base::TimeTicks::FromInternalValue(RandU64());
    return true;
  }
};

template <>
struct GenerateTraits<base::PlatformFileInfo> {
  static bool Generate(base::PlatformFileInfo* p, Generator* generator) {
    return
        GenerateParam(&p->size, generator) &&
        GenerateParam(&p->is_directory, generator) &&
        GenerateParam(&p->last_modified, generator) &&
        GenerateParam(&p->last_accessed, generator) &&
        GenerateParam(&p->creation_time, generator);
  }
};


template <>
struct GenerateTraits<base::ListValue> {
  static bool Generate(base::ListValue* p, Generator* generator) {
    ++g_depth;
    size_t list_length = g_depth > 3 ? 0 : RandInRange(8);
    for (size_t index = 0; index < list_length; ++index) {
      switch (RandInRange(8))
      {
        case base::Value::TYPE_BOOLEAN: {
          bool tmp;
          generator->GenerateBool(&tmp);
          p->Set(index, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_INTEGER: {
          int tmp;
          generator->GenerateInt(&tmp);
          p->Set(index, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_DOUBLE: {
          double tmp;
          generator->GenerateDouble(&tmp);
          p->Set(index, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_STRING: {
          std::string tmp;
          generator->GenerateString(&tmp);
          p->Set(index, new base::StringValue(tmp));
          break;
        }
        case base::Value::TYPE_BINARY: {
          char tmp[200];
          size_t bin_length = RandInRange(sizeof(tmp));
          generator->GenerateData(tmp, bin_length);
          p->Set(index,
                 base::BinaryValue::CreateWithCopiedBuffer(tmp, bin_length));
          break;
        }
        case base::Value::TYPE_DICTIONARY: {
          base::DictionaryValue* tmp = new base::DictionaryValue();
          GenerateParam(tmp, generator);
          p->Set(index, tmp);
          break;
        }
        case base::Value::TYPE_LIST: {
          base::ListValue* tmp = new base::ListValue();
          GenerateParam(tmp, generator);
          p->Set(index, tmp);
          break;
        }
        case base::Value::TYPE_NULL:
        default:
          break;
      }
    }
    --g_depth;
    return true;
  }
};

template <>
struct GenerateTraits<base::DictionaryValue> {
  static bool Generate(base::DictionaryValue* p, Generator* generator) {
    ++g_depth;
    size_t dict_length = g_depth > 3 ? 0 : RandInRange(8);
    for (size_t index = 0; index < dict_length; ++index) {
      std::string property;
      generator->GenerateString(&property);
      switch (RandInRange(8))
      {
        case base::Value::TYPE_BOOLEAN: {
          bool tmp;
          generator->GenerateBool(&tmp);
          p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_INTEGER: {
          int tmp;
          generator->GenerateInt(&tmp);
          p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_DOUBLE: {
          double tmp;
          generator->GenerateDouble(&tmp);
          p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
          break;
        }
        case base::Value::TYPE_STRING: {
          std::string tmp;
          generator->GenerateString(&tmp);
          p->SetWithoutPathExpansion(property, new base::StringValue(tmp));
          break;
        }
        case base::Value::TYPE_BINARY: {
          char tmp[200];
          size_t bin_length = RandInRange(sizeof(tmp));
          generator->GenerateData(tmp, bin_length);
          p->SetWithoutPathExpansion(
              property,
              base::BinaryValue::CreateWithCopiedBuffer(tmp, bin_length));
          break;
        }
        case base::Value::TYPE_DICTIONARY: {
          base::DictionaryValue* tmp = new base::DictionaryValue();
          GenerateParam(tmp, generator);
          p->SetWithoutPathExpansion(property, tmp);
          break;
        }
        case base::Value::TYPE_LIST: {
          base::ListValue* tmp = new base::ListValue();
          GenerateParam(tmp, generator);
          p->SetWithoutPathExpansion(property, tmp);
          break;
        }
        case base::Value::TYPE_NULL:
        default:
          break;
      }
    }
    --g_depth;
    return true;
  }
};

template <>
struct GenerateTraits<GURL> {
  static bool Generate(GURL *p, Generator* generator) {
    const char url_chars[] = "Ahtp0:/.?+\%&#";
    size_t count = RandInRange(100);
    std::string random_url;
    for (size_t i = 0; i < count; ++i)
      random_url += url_chars[RandInRange(sizeof(url_chars) - 1)];
    int selector = RandInRange(10);
    if (selector == 0)
      random_url = std::string("http://") + random_url;
    else if (selector == 1)
      random_url = std::string("file://") + random_url;
    else if (selector == 2)
      random_url = std::string("javascript:") + random_url;
    else if (selector == 2)
      random_url = std::string("data:") + random_url;
    *p = GURL(random_url);
    return true;
  }
};

// FIXME: Actually generate something.
template <>
struct GenerateTraits<SkBitmap> {
  static bool Generate(SkBitmap* p, Generator* generator) {
    *p = SkBitmap();
    return true;
  }
};

template <>
struct GenerateTraits<IPC::ChannelHandle> {
  static bool Generate(IPC::ChannelHandle* p, Generator* generator) {
    return
        GenerateParam(&p->name, generator) &&
        GenerateParam(&p->socket, generator);
  }
};

template <>
struct GenerateTraits<cc::CompositorFrame> {
  // FIXME: this should actually generate something
  static bool Generate(cc::CompositorFrame* p, Generator* generator) {
    return true;
  }
};

template <>
struct GenerateTraits<cc::CompositorFrameAck> {
  // FIXME: this should actually generate something
  static bool Generate(cc::CompositorFrameAck* p, Generator* generator) {
    return true;
  }
};

template <>
struct GenerateTraits<content::IndexedDBKey> {
  static bool Generate(content::IndexedDBKey* p, Generator* generator) {
    ++g_depth;
    blink::WebIDBKeyType web_type =
        static_cast<blink::WebIDBKeyType>(RandInRange(7));
    switch (web_type)
    {
      case blink::WebIDBKeyTypeArray: {
        size_t length = g_depth > 3 ? 0 : RandInRange(4);
        std::vector<content::IndexedDBKey> array;
        array.resize(length);
        for (size_t i = 0; i < length; ++i) {
          if (!GenerateParam(&array[i], generator))
            return false;
        }
        *p = content::IndexedDBKey(array);
        return true;
      }
      case blink::WebIDBKeyTypeBinary: {
        std::string binary;
        if (!GenerateParam(&binary, generator))
          return false;
        *p = content::IndexedDBKey(binary);
        return true;
      }
      case blink::WebIDBKeyTypeString: {
        base::string16 string;
        if (!GenerateParam(&string, generator))
          return false;
        *p = content::IndexedDBKey(string);
        return true;
      }
      case blink::WebIDBKeyTypeDate:
      case blink::WebIDBKeyTypeNumber: {
        double number;
        if (!GenerateParam(&number, generator))
          return false;
        *p = content::IndexedDBKey(number, web_type);
        return true;
      }
      case blink::WebIDBKeyTypeInvalid:
      case blink::WebIDBKeyTypeNull: {
        *p = content::IndexedDBKey(web_type);
        return true;
      }
      default:
        NOTREACHED();
        return false;
    }
    --g_depth;
    return true;
  }
};

template <>
struct GenerateTraits<content::IndexedDBKeyRange> {
  static bool Generate(content::IndexedDBKeyRange *p, Generator* generator) {
    content::IndexedDBKey lower;
    content::IndexedDBKey upper;
    bool lower_open;
    bool upper_open;
    if (!GenerateParam(&lower, generator))
      return false;
    if (!GenerateParam(&upper, generator))
      return false;
    if (!GenerateParam(&lower_open, generator))
      return false;
    if (!GenerateParam(&upper_open, generator))
      return false;
    *p = content::IndexedDBKeyRange(lower, upper, lower_open, upper_open);
    return true;
  }
};

template <>
struct GenerateTraits<content::IndexedDBKeyPath> {
  static bool Generate(content::IndexedDBKeyPath *p, Generator* generator) {
    switch (RandInRange(3)) {
      case 0: {
        std::vector<base::string16> array;
        if (!GenerateParam(&array, generator))
          return false;
        *p = content::IndexedDBKeyPath(array);
        break;
      }
      case 1: {
        base::string16 string;
        if (!GenerateParam(&string, generator))
          return false;
        *p = content::IndexedDBKeyPath(string);
        break;
      }
      case 2: {
        *p = content::IndexedDBKeyPath();
        break;
      }
    }
    return true;
  }
};

template <>
struct GenerateTraits<content::PageState> {
  static bool Generate(content::PageState *p, Generator* generator) {
    std::string junk;
    if (!GenerateParam(&junk, generator))
      return false;
    *p = content::PageState::CreateFromEncodedData(junk);
    return true;
  }
};

template <>
struct GenerateTraits<gpu::Mailbox> {
  static bool Generate(gpu::Mailbox *p, Generator* generator) {
    generator->GenerateBytes(p->name, sizeof(p->name));
    return true;
  }
};

template <>
struct GenerateTraits<media::AudioParameters> {
  static bool Generate(media::AudioParameters *p, Generator* generator) {
    int format;
    int channel_layout;
    int channels;
    int input_channels;
    int sample_rate;
    int bits_per_sample;
    int frames_per_buffer;
    int effects;
    if (!GenerateParam(&format, generator))
      return false;
    if (!GenerateParam(&channel_layout, generator))
      return false;
    if (!GenerateParam(&channels, generator))
      return false;
    if (!GenerateParam(&input_channels, generator))
      return false;
    if (!GenerateParam(&sample_rate, generator))
      return false;
    if (!GenerateParam(&bits_per_sample, generator))
      return false;
    if (!GenerateParam(&frames_per_buffer, generator))
      return false;
    if (!GenerateParam(&effects, generator))
      return false;
    media::AudioParameters params(
        static_cast<media::AudioParameters::Format>(format),
        static_cast<media::ChannelLayout>(channel_layout),
        channels, input_channels, sample_rate,
        bits_per_sample, frames_per_buffer, effects);
    *p = params;
    return true;
  }
};

template <>
struct GenerateTraits<media::VideoCaptureFormat> {
  static bool Generate(media::VideoCaptureFormat *p, Generator* generator) {
    int frame_size_width;
    int frame_size_height;
    int pixel_format;
    if (!GenerateParam(&frame_size_height, generator))
      return false;
    if (!GenerateParam(&frame_size_width, generator))
      return false;
    if (!GenerateParam(&pixel_format, generator))
      return false;
    if (!GenerateParam(&p->frame_rate, generator))
      return false;
    p->frame_size.SetSize(frame_size_width, frame_size_height);
    p->pixel_format = static_cast<media::VideoPixelFormat>(pixel_format);
    return true;
  }
};


template <>
struct GenerateTraits<net::LoadTimingInfo> {
  static bool Generate(net::LoadTimingInfo *p, Generator* generator) {
    return
        GenerateParam(&p->socket_log_id, generator) &&
        GenerateParam(&p->socket_reused, generator) &&
        GenerateParam(&p->request_start_time, generator) &&
        GenerateParam(&p->request_start, generator) &&
        GenerateParam(&p->proxy_resolve_start, generator) &&
        GenerateParam(&p->proxy_resolve_end, generator) &&
        GenerateParam(&p->connect_timing.dns_start, generator) &&
        GenerateParam(&p->connect_timing.dns_end, generator) &&
        GenerateParam(&p->connect_timing.connect_start, generator) &&
        GenerateParam(&p->connect_timing.connect_end, generator) &&
        GenerateParam(&p->connect_timing.ssl_start, generator) &&
        GenerateParam(&p->connect_timing.ssl_end, generator) &&
        GenerateParam(&p->send_start, generator) &&
        GenerateParam(&p->send_end, generator) &&
        GenerateParam(&p->receive_headers_end, generator);
  }
};

template <>
struct GenerateTraits<net::HostPortPair> {
  static bool Generate(net::HostPortPair *p, Generator* generator) {
    std::string host;
    uint16 port;
    if (!GenerateParam(&host, generator))
      return false;
    if (!GenerateParam(&port, generator))
      return false;
    p->set_host(host);
    p->set_port(port);
    return true;
  }
};

template <>
struct GenerateTraits<net::IPEndPoint> {
  static bool Generate(net::IPEndPoint *p, Generator* generator) {
    net::IPAddressNumber address;
    int port;
    if (!GenerateParam(&address, generator))
      return false;
    if (!GenerateParam(&port, generator))
      return false;
    net::IPEndPoint ip_endpoint(address, port);
    *p = ip_endpoint;
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Point> {
  static bool Generate(gfx::Point *p, Generator* generator) {
    int x;
    int y;
    if (!GenerateParam(&x, generator))
      return false;
    if (!GenerateParam(&y, generator))
      return false;
    p->SetPoint(x, y);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::PointF> {
  static bool Generate(gfx::PointF *p, Generator* generator) {
    float x;
    float y;
    if (!GenerateParam(&x, generator))
      return false;
    if (!GenerateParam(&y, generator))
      return false;
    p->SetPoint(x, y);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Size> {
  static bool Generate(gfx::Size *p, Generator* generator) {
    int w;
    int h;
    if (!GenerateParam(&w, generator))
      return false;
    if (!GenerateParam(&h, generator))
      return false;
    p->SetSize(w, h);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::SizeF> {
  static bool Generate(gfx::SizeF *p, Generator* generator) {
    float w;
    float h;
    if (!GenerateParam(&w, generator))
      return false;
    if (!GenerateParam(&h, generator))
      return false;
    p->SetSize(w, h);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Rect> {
  static bool Generate(gfx::Rect *p, Generator* generator) {
    gfx::Point origin;
    gfx::Size  size;
    if (!GenerateParam(&origin, generator))
      return false;
    if (!GenerateParam(&size, generator))
      return false;
    p->set_origin(origin);
    p->set_size(size);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::RectF> {
  static bool Generate(gfx::RectF *p, Generator* generator) {
    gfx::PointF origin;
    gfx::SizeF  size;
    if (!GenerateParam(&origin, generator))
      return false;
    if (!GenerateParam(&size, generator))
      return false;
    p->set_origin(origin);
    p->set_size(size);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Range> {
  static bool Generate(gfx::Range *p, Generator* generator) {
    size_t start;
    size_t end;
    if (!GenerateParam(&start, generator))
      return false;
    if (!GenerateParam(&end, generator))
      return false;
    *p = gfx::Range(start, end);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Vector2d> {
  static bool Generate(gfx::Vector2d *p, Generator* generator) {
    int x;
    int y;
    if (!GenerateParam(&x, generator))
      return false;
    if (!GenerateParam(&y, generator))
      return false;
    *p = gfx::Vector2d(x, y);
    return true;
  }
};

template <>
struct GenerateTraits<gfx::Vector2dF> {
  static bool Generate(gfx::Vector2dF *p, Generator* generator) {
    float x;
    float y;
    if (!GenerateParam(&x, generator))
      return false;
    if (!GenerateParam(&y, generator))
      return false;
    *p = gfx::Vector2dF(x, y);
    return true;
  }
};

// PP_ traits.
template <>
struct GenerateTraits<PP_Bool> {
  static bool Generate(PP_Bool *p, Generator* generator) {
    bool tmp;
    if (!GenerateParam(&tmp, generator))
      return false;
    *p = PP_FromBool(tmp);
    return true;
  }
};

template <>
struct GenerateTraits<PP_NetAddress_Private> {
  static bool Generate(PP_NetAddress_Private *p, Generator* generator) {
    p->size = RandInRange(sizeof(p->data) + 1);
    generator->GenerateBytes(&p->data, p->size);
    return true;
  }
};

template <>
struct GenerateTraits<ppapi::HostResource> {
  static bool Generate(ppapi::HostResource *p, Generator* generator) {
    PP_Instance instance;
    PP_Resource resource;
    if (!GenerateParam(&instance, generator))
      return false;
    if (!GenerateParam(&resource, generator))
      return false;
    p->SetHostResource(instance, resource);
    return true;
  }
};

template <>
struct GenerateTraits<ppapi::PepperFilePath> {
  static bool Generate(ppapi::PepperFilePath *p, Generator* generator) {
    unsigned domain = RandInRange(ppapi::PepperFilePath::DOMAIN_MAX_VALID+1);
    base::FilePath path;
    if (!GenerateParam(&path, generator))
      return false;
    *p = ppapi::PepperFilePath(
        static_cast<ppapi::PepperFilePath::Domain>(domain), path);
    return true;
  }
};

template <>
struct GenerateTraits<ppapi::PpapiPermissions> {
  static bool Generate(ppapi::PpapiPermissions *p, Generator* generator) {
    uint32_t bits;
    if (!GenerateParam(&bits, generator))
      return false;
    *p = ppapi::PpapiPermissions(bits);
    return true;
  }
};

template <>
struct GenerateTraits<ppapi::SocketOptionData> {
  static bool Generate(ppapi::SocketOptionData *p, Generator* generator) {
    // FIXME: we can do better here.
    int32 temp;
    if (!GenerateParam(&temp, generator))
      return false;
    p->SetInt32(temp);
    return true;
  }
};

// Redefine macros to generate generating from traits declarations.
// STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
#undef IPC_STRUCT_BEGIN
#undef IPC_STRUCT_BEGIN_WITH_PARENT
#undef IPC_STRUCT_MEMBER
#undef IPC_STRUCT_END
#define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \
  IPC_STRUCT_BEGIN(struct_name)
#define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name)
#define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name)
#define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()

// Set up so next include will generate generate trait classes.
#undef IPC_STRUCT_TRAITS_BEGIN
#undef IPC_STRUCT_TRAITS_MEMBER
#undef IPC_STRUCT_TRAITS_PARENT
#undef IPC_STRUCT_TRAITS_END
#define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
  template <> \
  struct GenerateTraits<struct_name> { \
    static bool Generate(struct_name *p, Generator* generator) {

#define IPC_STRUCT_TRAITS_MEMBER(name) \
      if (!GenerateParam(&p->name, generator)) \
        return false;

#define IPC_STRUCT_TRAITS_PARENT(type) \
      if (!GenerateParam(static_cast<type*>(p), generator)) \
        return false;

#define IPC_STRUCT_TRAITS_END() \
      return true; \
    } \
  };

// If |condition| isn't met, the messsge will fail to serialize. Try
// increasingly smaller ranges until we find one that happens to meet
// the condition, or fail trying.
#undef IPC_ENUM_TRAITS_VALIDATE
#define IPC_ENUM_TRAITS_VALIDATE(enum_name, condition)             \
  template <>                                                      \
  struct GenerateTraits<enum_name> {                               \
    static bool Generate(enum_name* p, Generator* generator) {     \
      for (int shift = 30; shift; --shift) {                       \
        for (int tries = 0; tries < 2; ++tries) {                  \
          int value = RandInRange(1 << shift);                     \
          if (condition) {                                         \
            *reinterpret_cast<int*>(p) = value;                    \
            return true;                                           \
          }                                                        \
        }                                                          \
      }                                                            \
      std::cerr << "failed to satisfy " << #condition << "\n";     \
      return false;                                                \
    }                                                              \
  };

// Bring them into existence.
#include "tools/ipc_fuzzer/message_lib/all_messages.h"
#include "ipc/ipc_message_null_macros.h"

// Redefine macros to generate generating funtions
#undef IPC_MESSAGE_DECL
#define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist)       \
  IPC_##kind##_##type##_GENERATE(name, in, out, ilist, olist)

#define IPC_EMPTY_CONTROL_GENERATE(name, in, out, ilist, olist)         \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    return new name();                                                  \
  }

#define IPC_EMPTY_ROUTED_GENERATE(name, in, out, ilist, olist)          \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    return new name(RandInRange(MAX_FAKE_ROUTING_ID));                  \
  }

#define IPC_ASYNC_CONTROL_GENERATE(name, in, out, ilist, olist)         \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    IPC_TUPLE_IN_##in ilist p;                                          \
    if (GenerateParam(&p, generator)) {                                 \
      return new name(IPC_MEMBERS_IN_##in(p));                          \
    }                                                                   \
    std::cerr << "Don't know how to generate " << #name << "\n";        \
    return 0;                                                           \
  }

#define IPC_ASYNC_ROUTED_GENERATE(name, in, out, ilist, olist)          \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    IPC_TUPLE_IN_##in ilist p;                                          \
    if (GenerateParam(&p, generator)) {                                 \
      return new name(RandInRange(MAX_FAKE_ROUTING_ID)                  \
                      IPC_COMMA_##in                                    \
                      IPC_MEMBERS_IN_##in(p));                          \
    }                                                                   \
    std::cerr << "Don't know how to generate " << #name << "\n";        \
    return 0;                                                           \
  }

#define IPC_SYNC_CONTROL_GENERATE(name, in, out, ilist, olist)          \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    IPC_TUPLE_IN_##in ilist p;                                          \
    if (GenerateParam(&p, generator)) {                                 \
      return new name(IPC_MEMBERS_IN_##in(p)                            \
                      IPC_COMMA_AND_##out(IPC_COMMA_##in)               \
                      IPC_MEMBERS_OUT_##out());                         \
    }                                                                   \
    std::cerr << "Don't know how to generate " << #name << "\n";        \
    return 0;                                                           \
  }

#define IPC_SYNC_ROUTED_GENERATE(name, in, out, ilist, olist)           \
  IPC::Message* generator_for_##name(Generator* generator) {            \
    IPC_TUPLE_IN_##in ilist p;                                          \
    if (GenerateParam(&p, generator)) {                                 \
      return new name(RandInRange(MAX_FAKE_ROUTING_ID)                  \
                      IPC_COMMA_OR_##out(IPC_COMMA_##in)                \
                      IPC_MEMBERS_IN_##in(p)                            \
                      IPC_COMMA_AND_##out(IPC_COMMA_##in)               \
                      IPC_MEMBERS_OUT_##out());                         \
    }                                                                   \
    std::cerr << "Don't know how to generate " << #name << "\n";        \
    return 0;                                                           \
  }

#define MAX_FAKE_ROUTING_ID 15

#define IPC_MEMBERS_IN_0(p)
#define IPC_MEMBERS_IN_1(p) p.a
#define IPC_MEMBERS_IN_2(p) p.a, p.b
#define IPC_MEMBERS_IN_3(p) p.a, p.b, p.c
#define IPC_MEMBERS_IN_4(p) p.a, p.b, p.c, p.d
#define IPC_MEMBERS_IN_5(p) p.a, p.b, p.c, p.d, p.e

#define IPC_MEMBERS_OUT_0()
#define IPC_MEMBERS_OUT_1() NULL
#define IPC_MEMBERS_OUT_2() NULL, NULL
#define IPC_MEMBERS_OUT_3() NULL, NULL, NULL
#define IPC_MEMBERS_OUT_4() NULL, NULL, NULL, NULL
#define IPC_MEMBERS_OUT_5() NULL, NULL, NULL, NULL, NULL

#include "tools/ipc_fuzzer/message_lib/all_messages.h"
#include "ipc/ipc_message_null_macros.h"

typedef IPC::Message* (*GeneratorFunction)(Generator*);
typedef std::vector<GeneratorFunction> GeneratorFunctionVector;

void PopulateGeneratorFunctionVector(
    GeneratorFunctionVector *function_vector) {
#undef IPC_MESSAGE_DECL
#define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
  function_vector->push_back(generator_for_##name);
#include "tools/ipc_fuzzer/message_lib/all_messages.h"
}

static const char kCountSwitch[] = "count";
static const char kHelpSwitch[] = "help";

int GenerateMain(int argc, char** argv) {
  CommandLine::Init(argc, argv);
  CommandLine* cmd = CommandLine::ForCurrentProcess();
  CommandLine::StringVector args = cmd->GetArgs();

  if (args.size() != 1 || cmd->HasSwitch(kHelpSwitch)) {
    std::cerr << "Usage: ipc_fuzzer_generate [--help] [--count=n] outfile\n";
    return EXIT_FAILURE;
  }
  std::string output_file_name = args[0];

  int message_count = 1000;
  if (cmd->HasSwitch(kCountSwitch))
    message_count = atoi(cmd->GetSwitchValueASCII(kCountSwitch).c_str());

  InitRand();

  GeneratorFunctionVector function_vector;
  PopulateGeneratorFunctionVector(&function_vector);
  std::cerr << "Counted " << function_vector.size()
            << " distinct messages present in chrome.\n";

  Generator* generator = new GeneratorImpl();
  MessageVector message_vector;

  int bad_count = 0;
  if (message_count < 0) {
    // Enumerate them all.
    for (size_t i = 0; i < function_vector.size(); ++i) {
      if (IPC::Message* new_message = (*function_vector[i])(generator))
        message_vector.push_back(new_message);
      else
        bad_count += 1;
    }
  } else {
    // Generate a random batch.
    for (int i = 0; i < message_count; ++i) {
      size_t index = RandInRange(function_vector.size());
      if (IPC::Message* new_message = (*function_vector[index])(generator))
        message_vector.push_back(new_message);
      else
        bad_count += 1;
    }
  }

  std::cerr << "Failed to generate " << bad_count << " messages.\n";

  if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
    return EXIT_FAILURE;

  return EXIT_SUCCESS;
}

}  // namespace ipc_fuzzer

int main(int argc, char** argv) {
  return ipc_fuzzer::GenerateMain(argc, argv);
}

/* [<][>][^][v][top][bottom][index][help] */