Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / tools / ipc_fuzzer / mutate / generate.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdlib.h>
6
7 #include <algorithm>
8 #include <iostream>
9 #include <ostream>
10 #include <set>
11 #include <vector>
12
13 #include "base/command_line.h"
14 #include "base/pickle.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "ipc/ipc_message.h"
19 #include "ipc/ipc_message_utils.h"
20 #include "ipc/ipc_switches.h"
21 #include "ipc/ipc_sync_channel.h"
22 #include "ipc/ipc_sync_message.h"
23 #include "tools/ipc_fuzzer/message_lib/message_file.h"
24 #include "tools/ipc_fuzzer/mutate/rand_util.h"
25
26 #if defined(OS_POSIX)
27 #include <unistd.h>
28 #endif
29
30 // First include of message files to provide basic type.
31 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
32 #include "ipc/ipc_message_null_macros.h"
33
34 namespace IPC {
35 class Message;
36 }  // namespace IPC
37
38 namespace {
39 // For breaking deep recursion.
40 int g_depth = 0;
41 }  // namespace
42
43 namespace ipc_fuzzer {
44
45 // Interface implemented by those who generate basic types.  The types all
46 // correspond to the types which a pickle from base/pickle.h can pickle,
47 // plus the floating point types.
48 class Generator {
49  public:
50   virtual void GenerateBool(bool* value) = 0;
51   virtual void GenerateInt(int* value) = 0;
52   virtual void GenerateLong(long* value) = 0;
53   virtual void GenerateSize(size_t* value) = 0;
54   virtual void GenerateUChar(unsigned char *value) = 0;
55   virtual void GenerateUInt16(uint16* value) = 0;
56   virtual void GenerateUInt32(uint32* value) = 0;
57   virtual void GenerateInt64(int64* value) = 0;
58   virtual void GenerateUInt64(uint64* value) = 0;
59   virtual void GenerateFloat(float *value) = 0;
60   virtual void GenerateDouble(double *value) = 0;
61   virtual void GenerateString(std::string* value) = 0;
62   virtual void GenerateString16(base::string16* value) = 0;
63   virtual void GenerateData(char* data, int length) = 0;
64   virtual void GenerateBytes(void* data, int data_len) = 0;
65 };
66
67 template <typename T>
68 void GenerateIntegralType(T* value) {
69   switch (RandInRange(16)) {
70     case 0:
71       *value = 0;
72       break;
73     case 1:
74       *value = 1;
75       break;
76     case 2:
77       *value = -1;
78       break;
79     case 3:
80       *value = 2;
81       break;
82     default:
83       *value = static_cast<T>(RandU64());
84       break;
85   }
86 }
87
88 template <typename T>
89 void GenerateFloatingType(T* value) {
90   *value = RandDouble();
91 }
92
93 template <typename T>
94 void GenerateStringType(T* value) {
95   T temp_string;
96   size_t length = RandInRange(300);
97   for (size_t i = 0; i < length; ++i)
98     temp_string += RandInRange(256);
99   *value = temp_string;
100 }
101
102 class GeneratorImpl : public Generator {
103  public:
104   GeneratorImpl() {}
105   virtual ~GeneratorImpl() {}
106
107   virtual void GenerateBool(bool* value) OVERRIDE {
108     *value = RandInRange(2);
109   }
110
111   virtual void GenerateInt(int* value) OVERRIDE {
112     GenerateIntegralType<int>(value);
113   }
114
115   virtual void GenerateLong(long* value) OVERRIDE {
116     GenerateIntegralType<long>(value);
117   }
118
119   virtual void GenerateSize(size_t* value) OVERRIDE {
120     GenerateIntegralType<size_t>(value);
121   }
122
123   virtual void GenerateUChar(unsigned char* value) OVERRIDE {
124     GenerateIntegralType<unsigned char>(value);
125   }
126
127   virtual void GenerateUInt16(uint16* value) OVERRIDE {
128     GenerateIntegralType<uint16>(value);
129   }
130
131   virtual void GenerateUInt32(uint32* value) OVERRIDE {
132     GenerateIntegralType<uint32>(value);
133   }
134
135   virtual void GenerateInt64(int64* value) OVERRIDE {
136     GenerateIntegralType<int64>(value);
137   }
138
139   virtual void GenerateUInt64(uint64* value) OVERRIDE {
140     GenerateIntegralType<uint64>(value);
141   }
142
143   virtual void GenerateFloat(float* value) OVERRIDE {
144     GenerateFloatingType<float>(value);
145   }
146
147   virtual void GenerateDouble(double* value) OVERRIDE {
148     GenerateFloatingType<double>(value);
149   }
150
151   virtual void GenerateString(std::string* value) OVERRIDE {
152     GenerateStringType<std::string>(value);
153   }
154
155   virtual void GenerateString16(base::string16* value) OVERRIDE {
156     GenerateStringType<base::string16>(value);
157   }
158
159   virtual void GenerateData(char* data, int length) OVERRIDE {
160     for (int i = 0; i < length; ++i) {
161       GenerateIntegralType<char>(&data[i]);
162     }
163   }
164
165   virtual void GenerateBytes(void* data, int data_len) OVERRIDE {
166     GenerateData(static_cast<char*>(data), data_len);
167   }
168 };
169
170 // Partially-specialized class that knows how to generate a given type.
171 template <class P>
172 struct GenerateTraits {
173   static bool Generate(P* p, Generator *generator) {
174     // This is the catch-all for types we don't have enough information
175     // to generate.
176     std::cerr << "Can't handle " << __PRETTY_FUNCTION__ << "\n";
177     return false;
178   }
179 };
180
181 // Template function to invoke partially-specialized class method.
182 template <class P>
183 static bool GenerateParam(P* p, Generator* generator) {
184   return GenerateTraits<P>::Generate(p, generator);
185 }
186
187 // Specializations to generate primitive types.
188 template <>
189 struct GenerateTraits<bool> {
190   static bool Generate(bool* p, Generator* generator) {
191     generator->GenerateBool(p);
192     return true;
193   }
194 };
195
196 template <>
197 struct GenerateTraits<int> {
198   static bool Generate(int* p, Generator* generator) {
199     generator->GenerateInt(p);
200     return true;
201   }
202 };
203
204 template <>
205 struct GenerateTraits<unsigned int> {
206   static bool Generate(unsigned int* p, Generator* generator) {
207     generator->GenerateInt(reinterpret_cast<int*>(p));
208     return true;
209   }
210 };
211
212 template <>
213 struct GenerateTraits<long> {
214   static bool Generate(long* p, Generator* generator) {
215     generator->GenerateLong(p);
216     return true;
217   }
218 };
219
220 template <>
221 struct GenerateTraits<unsigned long> {
222   static bool Generate(unsigned long* p, Generator* generator) {
223     generator->GenerateLong(reinterpret_cast<long*>(p));
224     return true;
225   }
226 };
227
228 template <>
229 struct GenerateTraits<long long> {
230   static bool Generate(long long* p, Generator* generator) {
231     generator->GenerateInt64(reinterpret_cast<int64*>(p));
232     return true;
233   }
234 };
235
236 template <>
237 struct GenerateTraits<unsigned long long> {
238   static bool Generate(unsigned long long* p, Generator* generator) {
239     generator->GenerateInt64(reinterpret_cast<int64*>(p));
240     return true;
241   }
242 };
243
244 template <>
245 struct GenerateTraits<short> {
246   static bool Generate(short* p, Generator* generator) {
247     generator->GenerateUInt16(reinterpret_cast<uint16*>(p));
248     return true;
249   }
250 };
251
252 template <>
253 struct GenerateTraits<unsigned short> {
254   static bool Generate(unsigned short* p, Generator* generator) {
255     generator->GenerateUInt16(reinterpret_cast<uint16*>(p));
256     return true;
257   }
258 };
259
260 template <>
261 struct GenerateTraits<char> {
262   static bool Generate(char* p, Generator* generator) {
263     generator->GenerateUChar(reinterpret_cast<unsigned char*>(p));
264     return true;
265   }
266 };
267
268 template <>
269 struct GenerateTraits<unsigned char> {
270   static bool Generate(unsigned char* p, Generator* generator) {
271     generator->GenerateUChar(p);
272     return true;
273   }
274 };
275
276 template <>
277 struct GenerateTraits<float> {
278   static bool Generate(float* p, Generator* generator) {
279     generator->GenerateFloat(p);
280     return true;
281   }
282 };
283
284 template <>
285 struct GenerateTraits<double> {
286   static bool Generate(double* p, Generator* generator) {
287     generator->GenerateDouble(p);
288     return true;
289   }
290 };
291
292 template <>
293 struct GenerateTraits<std::string> {
294   static bool Generate(std::string* p, Generator* generator) {
295     generator->GenerateString(p);
296     return true;
297   }
298 };
299
300 template <>
301 struct GenerateTraits<base::string16> {
302   static bool Generate(base::string16* p, Generator* generator) {
303     generator->GenerateString16(p);
304     return true;
305   }
306 };
307
308 // Specializations to generate tuples.
309 template <>
310 struct GenerateTraits<Tuple0> {
311   static bool Generate(Tuple0* p, Generator* generator) {
312     return true;
313   }
314 };
315
316 template <class A>
317 struct GenerateTraits<Tuple1<A> > {
318   static bool Generate(Tuple1<A>* p, Generator* generator) {
319     return GenerateParam(&p->a, generator);
320   }
321 };
322
323 template <class A, class B>
324 struct GenerateTraits<Tuple2<A, B> > {
325   static bool Generate(Tuple2<A, B>* p, Generator* generator) {
326     return
327         GenerateParam(&p->a, generator) &&
328         GenerateParam(&p->b, generator);
329   }
330 };
331
332 template <class A, class B, class C>
333 struct GenerateTraits<Tuple3<A, B, C> > {
334   static bool Generate(Tuple3<A, B, C>* p, Generator* generator) {
335     return
336         GenerateParam(&p->a, generator) &&
337         GenerateParam(&p->b, generator) &&
338         GenerateParam(&p->c, generator);
339   }
340 };
341
342 template <class A, class B, class C, class D>
343 struct GenerateTraits<Tuple4<A, B, C, D> > {
344   static bool Generate(Tuple4<A, B, C, D>* p, Generator* generator) {
345     return
346         GenerateParam(&p->a, generator) &&
347         GenerateParam(&p->b, generator) &&
348         GenerateParam(&p->c, generator) &&
349         GenerateParam(&p->d, generator);
350   }
351 };
352
353 template <class A, class B, class C, class D, class E>
354 struct GenerateTraits<Tuple5<A, B, C, D, E> > {
355   static bool Generate(Tuple5<A, B, C, D, E>* p, Generator* generator) {
356     return
357         GenerateParam(&p->a, generator) &&
358         GenerateParam(&p->b, generator) &&
359         GenerateParam(&p->c, generator) &&
360         GenerateParam(&p->d, generator) &&
361         GenerateParam(&p->e, generator);
362   }
363 };
364
365 // Specializations to generate containers.
366 template <class A>
367 struct GenerateTraits<std::vector<A> > {
368   static bool Generate(std::vector<A>* p, Generator* generator) {
369     size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
370     p->resize(count);
371     for (size_t i = 0; i < count; ++i) {
372       if (!GenerateParam(&p->at(i), generator)) {
373         --g_depth;
374         return false;
375       }
376     }
377     --g_depth;
378     return true;
379   }
380 };
381
382 template <class A>
383 struct GenerateTraits<std::set<A> > {
384   static bool Generate(std::set<A>* p, Generator* generator) {
385     static int g_depth = 0;
386     size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
387     A a;
388     for (size_t i = 0; i < count; ++i) {
389       if (!GenerateParam(&a, generator)) {
390         --g_depth;
391         return false;
392       }
393       p->insert(a);
394     }
395     --g_depth;
396     return true;
397   }
398 };
399
400
401 template <class A, class B>
402 struct GenerateTraits<std::map<A, B> > {
403   static bool Generate(std::map<A, B>* p, Generator* generator) {
404     static int g_depth = 0;
405     size_t count = ++g_depth > 3 ? 0 : RandInRange(20);
406     std::pair<A, B> place_holder;
407     for (size_t i = 0; i < count; ++i) {
408       if (!GenerateParam(&place_holder, generator)) {
409         --g_depth;
410         return false;
411       }
412       p->insert(place_holder);
413     }
414     --g_depth;
415     return true;
416   }
417 };
418
419 template <class A, class B>
420 struct GenerateTraits<std::pair<A, B> > {
421   static bool Generate(std::pair<A, B>* p, Generator* generator) {
422     return
423         GenerateParam(&p->first, generator) &&
424         GenerateParam(&p->second, generator);
425   }
426 };
427
428 // Specializations to generate hand-coded tyoes
429 template <>
430 struct GenerateTraits<base::NullableString16> {
431   static bool Generate(base::NullableString16* p, Generator* generator) {
432     *p = base::NullableString16();
433     return true;
434   }
435 };
436
437 template <>
438 struct GenerateTraits<base::FileDescriptor> {
439   static bool Generate(base::FileDescriptor* p, Generator* generator) {
440     // I don't think we can generate real ones due to check on construct.
441     p->fd = -1;
442     return true;
443   }
444 };
445
446 template <>
447 struct GenerateTraits<base::FilePath> {
448   static bool Generate(base::FilePath* p, Generator* generator) {
449     const char path_chars[] = "ACz0/.~:";
450     size_t count = RandInRange(60);
451     std::string random_path;
452     for (size_t i = 0; i < count; ++i)
453       random_path += path_chars[RandInRange(sizeof(path_chars) - 1)];
454     *p = base::FilePath(random_path);
455     return true;
456   }
457 };
458
459 template <>
460 struct GenerateTraits<base::File::Error> {
461   static bool Generate(base::File::Error* p, Generator* generator) {
462     int temporary;
463     if (!GenerateParam(&temporary, generator))
464       return false;
465     *p = static_cast<base::File::Error>(temporary);
466     return true;
467   }
468 };
469
470 template <>
471 struct GenerateTraits<base::File::Info> {
472   static bool Generate(base::File::Info* p, Generator* generator) {
473     double last_modified;
474     double last_accessed;
475     double creation_time;
476     if (!GenerateParam(&p->size, generator))
477       return false;
478     if (!GenerateParam(&p->is_directory, generator))
479       return false;
480     if (!GenerateParam(&last_modified, generator))
481       return false;
482     if (GenerateParam(&last_accessed, generator))
483       return false;
484     if (GenerateParam(&creation_time, generator))
485       return false;
486     p->last_modified = base::Time::FromDoubleT(last_modified);
487     p->last_accessed = base::Time::FromDoubleT(last_accessed);
488     p->creation_time = base::Time::FromDoubleT(creation_time);
489     return true;
490   }
491 };
492
493 template <>
494 struct GenerateTraits<base::Time> {
495   static bool Generate(base::Time* p, Generator* generator) {
496     *p = base::Time::FromInternalValue(RandU64());
497     return true;
498   }
499 };
500
501 template <>
502 struct GenerateTraits<base::TimeDelta> {
503   static bool Generate(base::TimeDelta* p, Generator* generator) {
504     *p = base::TimeDelta::FromInternalValue(RandU64());
505     return true;
506   }
507 };
508
509 template <>
510 struct GenerateTraits<base::TimeTicks> {
511   static bool Generate(base::TimeTicks* p, Generator* generator) {
512     *p = base::TimeTicks::FromInternalValue(RandU64());
513     return true;
514   }
515 };
516
517 template <>
518 struct GenerateTraits<base::PlatformFileInfo> {
519   static bool Generate(base::PlatformFileInfo* p, Generator* generator) {
520     return
521         GenerateParam(&p->size, generator) &&
522         GenerateParam(&p->is_directory, generator) &&
523         GenerateParam(&p->last_modified, generator) &&
524         GenerateParam(&p->last_accessed, generator) &&
525         GenerateParam(&p->creation_time, generator);
526   }
527 };
528
529
530 template <>
531 struct GenerateTraits<base::ListValue> {
532   static bool Generate(base::ListValue* p, Generator* generator) {
533     ++g_depth;
534     size_t list_length = g_depth > 3 ? 0 : RandInRange(8);
535     for (size_t index = 0; index < list_length; ++index) {
536       switch (RandInRange(8))
537       {
538         case base::Value::TYPE_BOOLEAN: {
539           bool tmp;
540           generator->GenerateBool(&tmp);
541           p->Set(index, new base::FundamentalValue(tmp));
542           break;
543         }
544         case base::Value::TYPE_INTEGER: {
545           int tmp;
546           generator->GenerateInt(&tmp);
547           p->Set(index, new base::FundamentalValue(tmp));
548           break;
549         }
550         case base::Value::TYPE_DOUBLE: {
551           double tmp;
552           generator->GenerateDouble(&tmp);
553           p->Set(index, new base::FundamentalValue(tmp));
554           break;
555         }
556         case base::Value::TYPE_STRING: {
557           std::string tmp;
558           generator->GenerateString(&tmp);
559           p->Set(index, new base::StringValue(tmp));
560           break;
561         }
562         case base::Value::TYPE_BINARY: {
563           char tmp[200];
564           size_t bin_length = RandInRange(sizeof(tmp));
565           generator->GenerateData(tmp, bin_length);
566           p->Set(index,
567                  base::BinaryValue::CreateWithCopiedBuffer(tmp, bin_length));
568           break;
569         }
570         case base::Value::TYPE_DICTIONARY: {
571           base::DictionaryValue* tmp = new base::DictionaryValue();
572           GenerateParam(tmp, generator);
573           p->Set(index, tmp);
574           break;
575         }
576         case base::Value::TYPE_LIST: {
577           base::ListValue* tmp = new base::ListValue();
578           GenerateParam(tmp, generator);
579           p->Set(index, tmp);
580           break;
581         }
582         case base::Value::TYPE_NULL:
583         default:
584           break;
585       }
586     }
587     --g_depth;
588     return true;
589   }
590 };
591
592 template <>
593 struct GenerateTraits<base::DictionaryValue> {
594   static bool Generate(base::DictionaryValue* p, Generator* generator) {
595     ++g_depth;
596     size_t dict_length = g_depth > 3 ? 0 : RandInRange(8);
597     for (size_t index = 0; index < dict_length; ++index) {
598       std::string property;
599       generator->GenerateString(&property);
600       switch (RandInRange(8))
601       {
602         case base::Value::TYPE_BOOLEAN: {
603           bool tmp;
604           generator->GenerateBool(&tmp);
605           p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
606           break;
607         }
608         case base::Value::TYPE_INTEGER: {
609           int tmp;
610           generator->GenerateInt(&tmp);
611           p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
612           break;
613         }
614         case base::Value::TYPE_DOUBLE: {
615           double tmp;
616           generator->GenerateDouble(&tmp);
617           p->SetWithoutPathExpansion(property, new base::FundamentalValue(tmp));
618           break;
619         }
620         case base::Value::TYPE_STRING: {
621           std::string tmp;
622           generator->GenerateString(&tmp);
623           p->SetWithoutPathExpansion(property, new base::StringValue(tmp));
624           break;
625         }
626         case base::Value::TYPE_BINARY: {
627           char tmp[200];
628           size_t bin_length = RandInRange(sizeof(tmp));
629           generator->GenerateData(tmp, bin_length);
630           p->SetWithoutPathExpansion(
631               property,
632               base::BinaryValue::CreateWithCopiedBuffer(tmp, bin_length));
633           break;
634         }
635         case base::Value::TYPE_DICTIONARY: {
636           base::DictionaryValue* tmp = new base::DictionaryValue();
637           GenerateParam(tmp, generator);
638           p->SetWithoutPathExpansion(property, tmp);
639           break;
640         }
641         case base::Value::TYPE_LIST: {
642           base::ListValue* tmp = new base::ListValue();
643           GenerateParam(tmp, generator);
644           p->SetWithoutPathExpansion(property, tmp);
645           break;
646         }
647         case base::Value::TYPE_NULL:
648         default:
649           break;
650       }
651     }
652     --g_depth;
653     return true;
654   }
655 };
656
657 template <>
658 struct GenerateTraits<GURL> {
659   static bool Generate(GURL *p, Generator* generator) {
660     const char url_chars[] = "Ahtp0:/.?+\%&#";
661     size_t count = RandInRange(100);
662     std::string random_url;
663     for (size_t i = 0; i < count; ++i)
664       random_url += url_chars[RandInRange(sizeof(url_chars) - 1)];
665     int selector = RandInRange(10);
666     if (selector == 0)
667       random_url = std::string("http://") + random_url;
668     else if (selector == 1)
669       random_url = std::string("file://") + random_url;
670     else if (selector == 2)
671       random_url = std::string("javascript:") + random_url;
672     else if (selector == 2)
673       random_url = std::string("data:") + random_url;
674     *p = GURL(random_url);
675     return true;
676   }
677 };
678
679 // FIXME: Actually generate something.
680 template <>
681 struct GenerateTraits<SkBitmap> {
682   static bool Generate(SkBitmap* p, Generator* generator) {
683     *p = SkBitmap();
684     return true;
685   }
686 };
687
688 template <>
689 struct GenerateTraits<IPC::ChannelHandle> {
690   static bool Generate(IPC::ChannelHandle* p, Generator* generator) {
691     return
692         GenerateParam(&p->name, generator) &&
693         GenerateParam(&p->socket, generator);
694   }
695 };
696
697 template <>
698 struct GenerateTraits<cc::CompositorFrame> {
699   // FIXME: this should actually generate something
700   static bool Generate(cc::CompositorFrame* p, Generator* generator) {
701     return true;
702   }
703 };
704
705 template <>
706 struct GenerateTraits<cc::CompositorFrameAck> {
707   // FIXME: this should actually generate something
708   static bool Generate(cc::CompositorFrameAck* p, Generator* generator) {
709     return true;
710   }
711 };
712
713 template <>
714 struct GenerateTraits<content::IndexedDBKey> {
715   static bool Generate(content::IndexedDBKey* p, Generator* generator) {
716     ++g_depth;
717     blink::WebIDBKeyType web_type =
718         static_cast<blink::WebIDBKeyType>(RandInRange(7));
719     switch (web_type)
720     {
721       case blink::WebIDBKeyTypeArray: {
722         size_t length = g_depth > 3 ? 0 : RandInRange(4);
723         std::vector<content::IndexedDBKey> array;
724         array.resize(length);
725         for (size_t i = 0; i < length; ++i) {
726           if (!GenerateParam(&array[i], generator))
727             return false;
728         }
729         *p = content::IndexedDBKey(array);
730         return true;
731       }
732       case blink::WebIDBKeyTypeBinary: {
733         std::string binary;
734         if (!GenerateParam(&binary, generator))
735           return false;
736         *p = content::IndexedDBKey(binary);
737         return true;
738       }
739       case blink::WebIDBKeyTypeString: {
740         base::string16 string;
741         if (!GenerateParam(&string, generator))
742           return false;
743         *p = content::IndexedDBKey(string);
744         return true;
745       }
746       case blink::WebIDBKeyTypeDate:
747       case blink::WebIDBKeyTypeNumber: {
748         double number;
749         if (!GenerateParam(&number, generator))
750           return false;
751         *p = content::IndexedDBKey(number, web_type);
752         return true;
753       }
754       case blink::WebIDBKeyTypeInvalid:
755       case blink::WebIDBKeyTypeNull: {
756         *p = content::IndexedDBKey(web_type);
757         return true;
758       }
759       default:
760         NOTREACHED();
761         return false;
762     }
763     --g_depth;
764     return true;
765   }
766 };
767
768 template <>
769 struct GenerateTraits<content::IndexedDBKeyRange> {
770   static bool Generate(content::IndexedDBKeyRange *p, Generator* generator) {
771     content::IndexedDBKey lower;
772     content::IndexedDBKey upper;
773     bool lower_open;
774     bool upper_open;
775     if (!GenerateParam(&lower, generator))
776       return false;
777     if (!GenerateParam(&upper, generator))
778       return false;
779     if (!GenerateParam(&lower_open, generator))
780       return false;
781     if (!GenerateParam(&upper_open, generator))
782       return false;
783     *p = content::IndexedDBKeyRange(lower, upper, lower_open, upper_open);
784     return true;
785   }
786 };
787
788 template <>
789 struct GenerateTraits<content::IndexedDBKeyPath> {
790   static bool Generate(content::IndexedDBKeyPath *p, Generator* generator) {
791     switch (RandInRange(3)) {
792       case 0: {
793         std::vector<base::string16> array;
794         if (!GenerateParam(&array, generator))
795           return false;
796         *p = content::IndexedDBKeyPath(array);
797         break;
798       }
799       case 1: {
800         base::string16 string;
801         if (!GenerateParam(&string, generator))
802           return false;
803         *p = content::IndexedDBKeyPath(string);
804         break;
805       }
806       case 2: {
807         *p = content::IndexedDBKeyPath();
808         break;
809       }
810     }
811     return true;
812   }
813 };
814
815 template <>
816 struct GenerateTraits<content::PageState> {
817   static bool Generate(content::PageState *p, Generator* generator) {
818     std::string junk;
819     if (!GenerateParam(&junk, generator))
820       return false;
821     *p = content::PageState::CreateFromEncodedData(junk);
822     return true;
823   }
824 };
825
826 template <>
827 struct GenerateTraits<gpu::Mailbox> {
828   static bool Generate(gpu::Mailbox *p, Generator* generator) {
829     generator->GenerateBytes(p->name, sizeof(p->name));
830     return true;
831   }
832 };
833
834 template <>
835 struct GenerateTraits<media::AudioParameters> {
836   static bool Generate(media::AudioParameters *p, Generator* generator) {
837     int format;
838     int channel_layout;
839     int channels;
840     int input_channels;
841     int sample_rate;
842     int bits_per_sample;
843     int frames_per_buffer;
844     int effects;
845     if (!GenerateParam(&format, generator))
846       return false;
847     if (!GenerateParam(&channel_layout, generator))
848       return false;
849     if (!GenerateParam(&channels, generator))
850       return false;
851     if (!GenerateParam(&input_channels, generator))
852       return false;
853     if (!GenerateParam(&sample_rate, generator))
854       return false;
855     if (!GenerateParam(&bits_per_sample, generator))
856       return false;
857     if (!GenerateParam(&frames_per_buffer, generator))
858       return false;
859     if (!GenerateParam(&effects, generator))
860       return false;
861     media::AudioParameters params(
862         static_cast<media::AudioParameters::Format>(format),
863         static_cast<media::ChannelLayout>(channel_layout),
864         channels, input_channels, sample_rate,
865         bits_per_sample, frames_per_buffer, effects);
866     *p = params;
867     return true;
868   }
869 };
870
871 template <>
872 struct GenerateTraits<media::VideoCaptureFormat> {
873   static bool Generate(media::VideoCaptureFormat *p, Generator* generator) {
874     int frame_size_width;
875     int frame_size_height;
876     int pixel_format;
877     if (!GenerateParam(&frame_size_height, generator))
878       return false;
879     if (!GenerateParam(&frame_size_width, generator))
880       return false;
881     if (!GenerateParam(&pixel_format, generator))
882       return false;
883     if (!GenerateParam(&p->frame_rate, generator))
884       return false;
885     p->frame_size.SetSize(frame_size_width, frame_size_height);
886     p->pixel_format = static_cast<media::VideoPixelFormat>(pixel_format);
887     return true;
888   }
889 };
890
891
892 template <>
893 struct GenerateTraits<net::LoadTimingInfo> {
894   static bool Generate(net::LoadTimingInfo *p, Generator* generator) {
895     return
896         GenerateParam(&p->socket_log_id, generator) &&
897         GenerateParam(&p->socket_reused, generator) &&
898         GenerateParam(&p->request_start_time, generator) &&
899         GenerateParam(&p->request_start, generator) &&
900         GenerateParam(&p->proxy_resolve_start, generator) &&
901         GenerateParam(&p->proxy_resolve_end, generator) &&
902         GenerateParam(&p->connect_timing.dns_start, generator) &&
903         GenerateParam(&p->connect_timing.dns_end, generator) &&
904         GenerateParam(&p->connect_timing.connect_start, generator) &&
905         GenerateParam(&p->connect_timing.connect_end, generator) &&
906         GenerateParam(&p->connect_timing.ssl_start, generator) &&
907         GenerateParam(&p->connect_timing.ssl_end, generator) &&
908         GenerateParam(&p->send_start, generator) &&
909         GenerateParam(&p->send_end, generator) &&
910         GenerateParam(&p->receive_headers_end, generator);
911   }
912 };
913
914 template <>
915 struct GenerateTraits<net::HostPortPair> {
916   static bool Generate(net::HostPortPair *p, Generator* generator) {
917     std::string host;
918     uint16 port;
919     if (!GenerateParam(&host, generator))
920       return false;
921     if (!GenerateParam(&port, generator))
922       return false;
923     p->set_host(host);
924     p->set_port(port);
925     return true;
926   }
927 };
928
929 template <>
930 struct GenerateTraits<net::IPEndPoint> {
931   static bool Generate(net::IPEndPoint *p, Generator* generator) {
932     net::IPAddressNumber address;
933     int port;
934     if (!GenerateParam(&address, generator))
935       return false;
936     if (!GenerateParam(&port, generator))
937       return false;
938     net::IPEndPoint ip_endpoint(address, port);
939     *p = ip_endpoint;
940     return true;
941   }
942 };
943
944 template <>
945 struct GenerateTraits<gfx::Point> {
946   static bool Generate(gfx::Point *p, Generator* generator) {
947     int x;
948     int y;
949     if (!GenerateParam(&x, generator))
950       return false;
951     if (!GenerateParam(&y, generator))
952       return false;
953     p->SetPoint(x, y);
954     return true;
955   }
956 };
957
958 template <>
959 struct GenerateTraits<gfx::PointF> {
960   static bool Generate(gfx::PointF *p, Generator* generator) {
961     float x;
962     float y;
963     if (!GenerateParam(&x, generator))
964       return false;
965     if (!GenerateParam(&y, generator))
966       return false;
967     p->SetPoint(x, y);
968     return true;
969   }
970 };
971
972 template <>
973 struct GenerateTraits<gfx::Size> {
974   static bool Generate(gfx::Size *p, Generator* generator) {
975     int w;
976     int h;
977     if (!GenerateParam(&w, generator))
978       return false;
979     if (!GenerateParam(&h, generator))
980       return false;
981     p->SetSize(w, h);
982     return true;
983   }
984 };
985
986 template <>
987 struct GenerateTraits<gfx::SizeF> {
988   static bool Generate(gfx::SizeF *p, Generator* generator) {
989     float w;
990     float h;
991     if (!GenerateParam(&w, generator))
992       return false;
993     if (!GenerateParam(&h, generator))
994       return false;
995     p->SetSize(w, h);
996     return true;
997   }
998 };
999
1000 template <>
1001 struct GenerateTraits<gfx::Rect> {
1002   static bool Generate(gfx::Rect *p, Generator* generator) {
1003     gfx::Point origin;
1004     gfx::Size  size;
1005     if (!GenerateParam(&origin, generator))
1006       return false;
1007     if (!GenerateParam(&size, generator))
1008       return false;
1009     p->set_origin(origin);
1010     p->set_size(size);
1011     return true;
1012   }
1013 };
1014
1015 template <>
1016 struct GenerateTraits<gfx::RectF> {
1017   static bool Generate(gfx::RectF *p, Generator* generator) {
1018     gfx::PointF origin;
1019     gfx::SizeF  size;
1020     if (!GenerateParam(&origin, generator))
1021       return false;
1022     if (!GenerateParam(&size, generator))
1023       return false;
1024     p->set_origin(origin);
1025     p->set_size(size);
1026     return true;
1027   }
1028 };
1029
1030 template <>
1031 struct GenerateTraits<gfx::Range> {
1032   static bool Generate(gfx::Range *p, Generator* generator) {
1033     size_t start;
1034     size_t end;
1035     if (!GenerateParam(&start, generator))
1036       return false;
1037     if (!GenerateParam(&end, generator))
1038       return false;
1039     *p = gfx::Range(start, end);
1040     return true;
1041   }
1042 };
1043
1044 template <>
1045 struct GenerateTraits<gfx::Vector2d> {
1046   static bool Generate(gfx::Vector2d *p, Generator* generator) {
1047     int x;
1048     int y;
1049     if (!GenerateParam(&x, generator))
1050       return false;
1051     if (!GenerateParam(&y, generator))
1052       return false;
1053     *p = gfx::Vector2d(x, y);
1054     return true;
1055   }
1056 };
1057
1058 template <>
1059 struct GenerateTraits<gfx::Vector2dF> {
1060   static bool Generate(gfx::Vector2dF *p, Generator* generator) {
1061     float x;
1062     float y;
1063     if (!GenerateParam(&x, generator))
1064       return false;
1065     if (!GenerateParam(&y, generator))
1066       return false;
1067     *p = gfx::Vector2dF(x, y);
1068     return true;
1069   }
1070 };
1071
1072 // PP_ traits.
1073 template <>
1074 struct GenerateTraits<PP_Bool> {
1075   static bool Generate(PP_Bool *p, Generator* generator) {
1076     bool tmp;
1077     if (!GenerateParam(&tmp, generator))
1078       return false;
1079     *p = PP_FromBool(tmp);
1080     return true;
1081   }
1082 };
1083
1084 template <>
1085 struct GenerateTraits<PP_NetAddress_Private> {
1086   static bool Generate(PP_NetAddress_Private *p, Generator* generator) {
1087     p->size = RandInRange(sizeof(p->data) + 1);
1088     generator->GenerateBytes(&p->data, p->size);
1089     return true;
1090   }
1091 };
1092
1093 template <>
1094 struct GenerateTraits<ppapi::HostResource> {
1095   static bool Generate(ppapi::HostResource *p, Generator* generator) {
1096     PP_Instance instance;
1097     PP_Resource resource;
1098     if (!GenerateParam(&instance, generator))
1099       return false;
1100     if (!GenerateParam(&resource, generator))
1101       return false;
1102     p->SetHostResource(instance, resource);
1103     return true;
1104   }
1105 };
1106
1107 template <>
1108 struct GenerateTraits<ppapi::PepperFilePath> {
1109   static bool Generate(ppapi::PepperFilePath *p, Generator* generator) {
1110     unsigned domain = RandInRange(ppapi::PepperFilePath::DOMAIN_MAX_VALID+1);
1111     base::FilePath path;
1112     if (!GenerateParam(&path, generator))
1113       return false;
1114     *p = ppapi::PepperFilePath(
1115         static_cast<ppapi::PepperFilePath::Domain>(domain), path);
1116     return true;
1117   }
1118 };
1119
1120 template <>
1121 struct GenerateTraits<ppapi::PpapiPermissions> {
1122   static bool Generate(ppapi::PpapiPermissions *p, Generator* generator) {
1123     uint32_t bits;
1124     if (!GenerateParam(&bits, generator))
1125       return false;
1126     *p = ppapi::PpapiPermissions(bits);
1127     return true;
1128   }
1129 };
1130
1131 template <>
1132 struct GenerateTraits<ppapi::SocketOptionData> {
1133   static bool Generate(ppapi::SocketOptionData *p, Generator* generator) {
1134     // FIXME: we can do better here.
1135     int32 temp;
1136     if (!GenerateParam(&temp, generator))
1137       return false;
1138     p->SetInt32(temp);
1139     return true;
1140   }
1141 };
1142
1143 // Redefine macros to generate generating from traits declarations.
1144 // STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur.
1145 #undef IPC_STRUCT_BEGIN
1146 #undef IPC_STRUCT_BEGIN_WITH_PARENT
1147 #undef IPC_STRUCT_MEMBER
1148 #undef IPC_STRUCT_END
1149 #define IPC_STRUCT_BEGIN_WITH_PARENT(struct_name, parent) \
1150   IPC_STRUCT_BEGIN(struct_name)
1151 #define IPC_STRUCT_BEGIN(struct_name) IPC_STRUCT_TRAITS_BEGIN(struct_name)
1152 #define IPC_STRUCT_MEMBER(type, name, ...) IPC_STRUCT_TRAITS_MEMBER(name)
1153 #define IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
1154
1155 // Set up so next include will generate generate trait classes.
1156 #undef IPC_STRUCT_TRAITS_BEGIN
1157 #undef IPC_STRUCT_TRAITS_MEMBER
1158 #undef IPC_STRUCT_TRAITS_PARENT
1159 #undef IPC_STRUCT_TRAITS_END
1160 #define IPC_STRUCT_TRAITS_BEGIN(struct_name) \
1161   template <> \
1162   struct GenerateTraits<struct_name> { \
1163     static bool Generate(struct_name *p, Generator* generator) {
1164
1165 #define IPC_STRUCT_TRAITS_MEMBER(name) \
1166       if (!GenerateParam(&p->name, generator)) \
1167         return false;
1168
1169 #define IPC_STRUCT_TRAITS_PARENT(type) \
1170       if (!GenerateParam(static_cast<type*>(p), generator)) \
1171         return false;
1172
1173 #define IPC_STRUCT_TRAITS_END() \
1174       return true; \
1175     } \
1176   };
1177
1178 // If |condition| isn't met, the messsge will fail to serialize. Try
1179 // increasingly smaller ranges until we find one that happens to meet
1180 // the condition, or fail trying.
1181 #undef IPC_ENUM_TRAITS_VALIDATE
1182 #define IPC_ENUM_TRAITS_VALIDATE(enum_name, condition)             \
1183   template <>                                                      \
1184   struct GenerateTraits<enum_name> {                               \
1185     static bool Generate(enum_name* p, Generator* generator) {     \
1186       for (int shift = 30; shift; --shift) {                       \
1187         for (int tries = 0; tries < 2; ++tries) {                  \
1188           int value = RandInRange(1 << shift);                     \
1189           if (condition) {                                         \
1190             *reinterpret_cast<int*>(p) = value;                    \
1191             return true;                                           \
1192           }                                                        \
1193         }                                                          \
1194       }                                                            \
1195       std::cerr << "failed to satisfy " << #condition << "\n";     \
1196       return false;                                                \
1197     }                                                              \
1198   };
1199
1200 // Bring them into existence.
1201 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
1202 #include "ipc/ipc_message_null_macros.h"
1203
1204 // Redefine macros to generate generating funtions
1205 #undef IPC_MESSAGE_DECL
1206 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist)       \
1207   IPC_##kind##_##type##_GENERATE(name, in, out, ilist, olist)
1208
1209 #define IPC_EMPTY_CONTROL_GENERATE(name, in, out, ilist, olist)         \
1210   IPC::Message* generator_for_##name(Generator* generator) {            \
1211     return new name();                                                  \
1212   }
1213
1214 #define IPC_EMPTY_ROUTED_GENERATE(name, in, out, ilist, olist)          \
1215   IPC::Message* generator_for_##name(Generator* generator) {            \
1216     return new name(RandInRange(MAX_FAKE_ROUTING_ID));                  \
1217   }
1218
1219 #define IPC_ASYNC_CONTROL_GENERATE(name, in, out, ilist, olist)         \
1220   IPC::Message* generator_for_##name(Generator* generator) {            \
1221     IPC_TUPLE_IN_##in ilist p;                                          \
1222     if (GenerateParam(&p, generator)) {                                 \
1223       return new name(IPC_MEMBERS_IN_##in(p));                          \
1224     }                                                                   \
1225     std::cerr << "Don't know how to generate " << #name << "\n";        \
1226     return 0;                                                           \
1227   }
1228
1229 #define IPC_ASYNC_ROUTED_GENERATE(name, in, out, ilist, olist)          \
1230   IPC::Message* generator_for_##name(Generator* generator) {            \
1231     IPC_TUPLE_IN_##in ilist p;                                          \
1232     if (GenerateParam(&p, generator)) {                                 \
1233       return new name(RandInRange(MAX_FAKE_ROUTING_ID)                  \
1234                       IPC_COMMA_##in                                    \
1235                       IPC_MEMBERS_IN_##in(p));                          \
1236     }                                                                   \
1237     std::cerr << "Don't know how to generate " << #name << "\n";        \
1238     return 0;                                                           \
1239   }
1240
1241 #define IPC_SYNC_CONTROL_GENERATE(name, in, out, ilist, olist)          \
1242   IPC::Message* generator_for_##name(Generator* generator) {            \
1243     IPC_TUPLE_IN_##in ilist p;                                          \
1244     if (GenerateParam(&p, generator)) {                                 \
1245       return new name(IPC_MEMBERS_IN_##in(p)                            \
1246                       IPC_COMMA_AND_##out(IPC_COMMA_##in)               \
1247                       IPC_MEMBERS_OUT_##out());                         \
1248     }                                                                   \
1249     std::cerr << "Don't know how to generate " << #name << "\n";        \
1250     return 0;                                                           \
1251   }
1252
1253 #define IPC_SYNC_ROUTED_GENERATE(name, in, out, ilist, olist)           \
1254   IPC::Message* generator_for_##name(Generator* generator) {            \
1255     IPC_TUPLE_IN_##in ilist p;                                          \
1256     if (GenerateParam(&p, generator)) {                                 \
1257       return new name(RandInRange(MAX_FAKE_ROUTING_ID)                  \
1258                       IPC_COMMA_OR_##out(IPC_COMMA_##in)                \
1259                       IPC_MEMBERS_IN_##in(p)                            \
1260                       IPC_COMMA_AND_##out(IPC_COMMA_##in)               \
1261                       IPC_MEMBERS_OUT_##out());                         \
1262     }                                                                   \
1263     std::cerr << "Don't know how to generate " << #name << "\n";        \
1264     return 0;                                                           \
1265   }
1266
1267 #define MAX_FAKE_ROUTING_ID 15
1268
1269 #define IPC_MEMBERS_IN_0(p)
1270 #define IPC_MEMBERS_IN_1(p) p.a
1271 #define IPC_MEMBERS_IN_2(p) p.a, p.b
1272 #define IPC_MEMBERS_IN_3(p) p.a, p.b, p.c
1273 #define IPC_MEMBERS_IN_4(p) p.a, p.b, p.c, p.d
1274 #define IPC_MEMBERS_IN_5(p) p.a, p.b, p.c, p.d, p.e
1275
1276 #define IPC_MEMBERS_OUT_0()
1277 #define IPC_MEMBERS_OUT_1() NULL
1278 #define IPC_MEMBERS_OUT_2() NULL, NULL
1279 #define IPC_MEMBERS_OUT_3() NULL, NULL, NULL
1280 #define IPC_MEMBERS_OUT_4() NULL, NULL, NULL, NULL
1281 #define IPC_MEMBERS_OUT_5() NULL, NULL, NULL, NULL, NULL
1282
1283 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
1284 #include "ipc/ipc_message_null_macros.h"
1285
1286 typedef IPC::Message* (*GeneratorFunction)(Generator*);
1287 typedef std::vector<GeneratorFunction> GeneratorFunctionVector;
1288
1289 void PopulateGeneratorFunctionVector(
1290     GeneratorFunctionVector *function_vector) {
1291 #undef IPC_MESSAGE_DECL
1292 #define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
1293   function_vector->push_back(generator_for_##name);
1294 #include "tools/ipc_fuzzer/message_lib/all_messages.h"
1295 }
1296
1297 static const char kCountSwitch[] = "count";
1298 static const char kHelpSwitch[] = "help";
1299
1300 int GenerateMain(int argc, char** argv) {
1301   CommandLine::Init(argc, argv);
1302   CommandLine* cmd = CommandLine::ForCurrentProcess();
1303   CommandLine::StringVector args = cmd->GetArgs();
1304
1305   if (args.size() != 1 || cmd->HasSwitch(kHelpSwitch)) {
1306     std::cerr << "Usage: ipc_fuzzer_generate [--help] [--count=n] outfile\n";
1307     return EXIT_FAILURE;
1308   }
1309   std::string output_file_name = args[0];
1310
1311   int message_count = 1000;
1312   if (cmd->HasSwitch(kCountSwitch))
1313     message_count = atoi(cmd->GetSwitchValueASCII(kCountSwitch).c_str());
1314
1315   InitRand();
1316
1317   GeneratorFunctionVector function_vector;
1318   PopulateGeneratorFunctionVector(&function_vector);
1319   std::cerr << "Counted " << function_vector.size()
1320             << " distinct messages present in chrome.\n";
1321
1322   Generator* generator = new GeneratorImpl();
1323   MessageVector message_vector;
1324
1325   int bad_count = 0;
1326   if (message_count < 0) {
1327     // Enumerate them all.
1328     for (size_t i = 0; i < function_vector.size(); ++i) {
1329       if (IPC::Message* new_message = (*function_vector[i])(generator))
1330         message_vector.push_back(new_message);
1331       else
1332         bad_count += 1;
1333     }
1334   } else {
1335     // Generate a random batch.
1336     for (int i = 0; i < message_count; ++i) {
1337       size_t index = RandInRange(function_vector.size());
1338       if (IPC::Message* new_message = (*function_vector[index])(generator))
1339         message_vector.push_back(new_message);
1340       else
1341         bad_count += 1;
1342     }
1343   }
1344
1345   std::cerr << "Failed to generate " << bad_count << " messages.\n";
1346
1347   if (!MessageFile::Write(base::FilePath(output_file_name), message_vector))
1348     return EXIT_FAILURE;
1349
1350   return EXIT_SUCCESS;
1351 }
1352
1353 }  // namespace ipc_fuzzer
1354
1355 int main(int argc, char** argv) {
1356   return ipc_fuzzer::GenerateMain(argc, argv);
1357 }